From 494105cc0f7e20d3e4f38bbee177e4e354870fb2 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 11 Jun 2015 11:23:00 +0300 Subject: [PATCH 01/29] linux: switch to linux-4.1 for generic/legacy --- packages/linux/package.mk | 6 +- .../4.1-rc8/linux-003-no_dev_console.patch | 21 + .../linux-051-ouya_controller_support.patch | 315 + .../linux-052-XBOX_remote_support.patch | 1029 + .../linux-053-spinelplus-remote-0.2.patch | 161 + ...1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 12 + ...-add_Adaptec_eHome_Infrared_Receiver.patch | 21 + ...tomer-code-restriction-in-rc6-decode.patch | 28 + ..._Manufacturing_Inc_Infrared_Receiver.patch | 13 + ..._sony-add_autorepeat_for_PS3_remotes.patch | 64 + .../linux-062-imon_pad_ignore_diagonal.patch | 21 + ...x-203-stb0899_enable_low_symbol_rate.patch | 12 + ...linux-212-mantis_stb0899_faster_lock.patch | 138 + .../4.1-rc8/linux-221-ngene-octopus.patch | 34137 ++++++++++++++++ .../linux-222-stb0899_signal_quality.patch | 62 + ...-video-artifacts-with-tt-3600-s2-usb.patch | 17 + .../linux-224-STK1160-addFramescaling.patch | 284 + ...linux-227-ds3000-invalid-symbol-rate.patch | 18 + .../4.1-rc8/linux-706-Sitecom-N300.patch | 11 + ...x-950-saa716x_PCIe_interface_chipset.patch | 13031 ++++++ ...utputting-HDMI-audio-before-prepare-.patch | 83 + .../linux-995-CX24120-13Z_frontend.patch | 1577 + .../linux-999-i915-use-legacy-turbo.patch | 30 + ...able-async-suspend-resume-by-default.patch | 25 + ...alize-partitions-on-RPMB-flagged-are.patch | 26 + projects/Generic/linux/linux.x86_64.conf | 69 +- .../Nvidia_Legacy/linux/linux.x86_64.conf | 67 +- projects/RPi/options | 2 +- projects/RPi2/options | 2 +- 29 files changed, 51219 insertions(+), 63 deletions(-) create mode 100644 packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch create mode 100644 packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch diff --git a/packages/linux/package.mk b/packages/linux/package.mk index 5517ec1e73..84ee3eb5b9 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -39,10 +39,14 @@ case "$LINUX" in PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET imx6-status-led imx6-soc-fan" ;; - *) + 4.0) PKG_VERSION="4.0.5" PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/$PKG_NAME-$PKG_VERSION.tar.xz" ;; + *) + PKG_VERSION="4.1-rc8" + PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/testing/$PKG_NAME-$PKG_VERSION.tar.xz" + ;; esac PKG_IS_ADDON="no" diff --git a/packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch b/packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch new file mode 100644 index 0000000000..df35a7ab9a --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch @@ -0,0 +1,21 @@ +diff --git a/init/main.c b/init/main.c +index 9484f4b..db55edd 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -880,8 +880,14 @@ static noinline void __init kernel_init_freeable(void) + do_basic_setup(); + + /* Open the /dev/console on the rootfs, this should never fail */ +- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) +- pr_err("Warning: unable to open an initial console.\n"); ++ char *console = "/dev_console"; ++ ++ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) { ++ sys_mknod(console, S_IFCHR|0600, (TTYAUX_MAJOR<<8)|1); ++ if (sys_open(console, O_RDWR, 0) < 0) ++ printk(KERN_WARNING "Warning: unable to open an initial console.\n"); ++ sys_unlink(console); ++ } + + (void) sys_dup(0); + (void) sys_dup(0); diff --git a/packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch b/packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch new file mode 100644 index 0000000000..9b0f253372 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch @@ -0,0 +1,315 @@ +diff -Naur linux-3.19.orig/drivers/hid/hid-core.c linux-3.19/drivers/hid/hid-core.c +--- linux-3.19.orig/drivers/hid/hid-core.c 2015-02-20 14:01:17.080322846 -0800 ++++ linux-3.19/drivers/hid/hid-core.c 2015-02-20 14:03:30.375519421 -0800 +@@ -1884,6 +1884,7 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, + { 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) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, +diff -Naur linux-3.19.orig/drivers/hid/hid-ids.h linux-3.19/drivers/hid/hid-ids.h +--- linux-3.19.orig/drivers/hid/hid-ids.h 2015-02-20 14:01:17.080322846 -0800 ++++ linux-3.19/drivers/hid/hid-ids.h 2015-02-20 14:03:30.382519482 -0800 +@@ -721,6 +721,9 @@ + #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 + #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 + ++#define USB_VENDOR_ID_OUYA 0x2836 ++#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001 ++ + #define USB_VENDOR_ID_PLANTRONICS 0x047f + + #define USB_VENDOR_ID_PANASONIC 0x04da +diff -Naur linux-3.19.orig/drivers/hid/hid-ouya.c linux-3.19/drivers/hid/hid-ouya.c +--- linux-3.19.orig/drivers/hid/hid-ouya.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.19/drivers/hid/hid-ouya.c 2015-02-20 14:03:30.371519386 -0800 +@@ -0,0 +1,260 @@ ++/* ++ * HID driver for OUYA Game Controller(s) ++ * ++ * Copyright (c) 2013 OUYA ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define OUYA_TOUCHPAD_FIXUP (1 << 0) ++ ++struct ouya_sc { ++ unsigned long quirks; ++}; ++ ++/* Fixed report descriptor */ ++static __u8 ouya_rdesc_fixed[] = { ++ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x05, /* Usage (Game Pad), */ ++ ++ 0xA1, 0x01, /* Collection (Application), */ ++ 0x85, 0x07, /* Report ID (7), */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x30, /* Usage (X), */ ++ 0x09, 0x31, /* Usage (Y), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x33, /* Usage (Rx), */ ++ 0x09, 0x34, /* Usage (Ry), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x32, /* Usage (Z), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x35, /* Usage (Rz), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0x05, 0x09, /* Usage Page (Button), */ ++ 0x19, 0x01, /* Usage Minimum (01h), */ ++ 0x29, 0x10, /* Usage Maximum (10h), */ ++ 0x95, 0x10, /* Report Count (16), */ ++ 0x75, 0x01, /* Report Size (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ ++ /* ORIGINAL REPORT DESCRIPTOR FOR TOUCHPAD INPUT */ ++ /* 06 00 ff a1 02 09 02 15 00 26 ff 00 35 00 46 ff 00 95 03 75 08 81 02 c0 */ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0x09, 0x02, /* Usage (Mouse), */ ++ 0x09, 0x01, /* Usage (Pointer), */ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x05, 0x09, /* Usage Page (Button), */ ++ 0x19, 0x01, /* Usage Minimum (01h), */ ++ 0x29, 0x03, /* Usage Maximum (03h), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x25, 0x01, /* Logical Maximum (1), */ ++ 0x95, 0x03, /* Report Count (3), */ ++ 0x75, 0x01, /* Report Size (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x05, /* Report Size (5), */ ++ 0x81, 0x01, /* Input (Constant), */ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x30, /* Usage (X), */ ++ 0x09, 0x31, /* Usage (Y), */ ++ 0x15, 0x81, /* Logical Minimum (-127), */ ++ 0x25, 0x7f, /* Logical Maximum (127), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x06, /* Input (Relative), */ ++ 0xC0, /* End Collection, */ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0xA1, 0x02, /* Collection (Logical), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x07, /* Report Count (7), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x09, 0x01, /* Usage (Pointer), */ ++ 0x91, 0x02, /* Output (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xC0, /* End Collection */ ++ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0x05, 0x0C, /* Usage Page (Consumer), */ ++ 0x09, 0x01, /* Usage (Consumer Control), */ ++ ++ 0xA1, 0x01, /* Collection (Application), */ ++ 0x85, 0x03, /* Report ID (3), */ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x06, /* Usage (Keyboard), */ ++ 0xA1, 0x02, /* Collection (Logical), */ ++ 0x05, 0x06, /* Usage Page (Generic), */ ++ 0x09, 0x20, /* Usage (Battery Strgth), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x06, 0xBC, 0xFF, /* Usage Page (Custom), */ ++ ++ 0x0A, 0xAD, 0xBD, /* UNKNOWN */ ++ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x06, /* Report Count (6), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xC0, /* End Collection */ ++ ++ 0x00 ++}; ++ ++static __u8 *ouya_report_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ struct ouya_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & OUYA_TOUCHPAD_FIXUP) { ++ rdesc = ouya_rdesc_fixed; ++ *rsize = sizeof(ouya_rdesc_fixed); ++ } ++ return rdesc; ++} ++ ++static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ struct ouya_sc *sc = hid_get_drvdata(hdev); ++ ++ if (!(sc->quirks & OUYA_TOUCHPAD_FIXUP)) { ++ return 0; ++ } ++ ++ if ((usage->hid & 0x90000) == 0x90000 && ++ (field->physical & 0xff000000) == 0xff000000 && ++ usage->collection_index == 5 && ++ field->report_count == 3) { ++ ++ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_MOUSE + (usage->hid - 0x90001)); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id) ++{ ++ int ret; ++ struct ouya_sc *sc; ++ ++ sc = kzalloc(sizeof(*sc), GFP_KERNEL); ++ if (sc == NULL) { ++ hid_err(hdev, "can't alloc ouya descriptor\n"); ++ return -ENOMEM; ++ } ++ ++ if(((hdev->version & 0xff00) == 0x0100 && (hdev->version & 0xff) >= 0x04) || ++ ((hdev->version & 0xff00) == 0xe100 && (hdev->version & 0xff) >= 0x3a)) { ++ hid_info(hdev, "ouya controller - new version\n"); ++ sc->quirks = OUYA_TOUCHPAD_FIXUP; ++ } else { ++ sc->quirks = 0; ++ } ++ hid_set_drvdata(hdev, sc); ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ hid_err(hdev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ++ HID_CONNECT_HIDDEV_FORCE); ++ if (ret) { ++ hid_err(hdev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++ ++err_free: ++ kfree(sc); ++ return ret; ++} ++ ++static void ouya_remove(struct hid_device *hdev) ++{ ++ hid_hw_stop(hdev); ++ kfree(hid_get_drvdata(hdev)); ++} ++ ++static const struct hid_device_id ouya_devices[] = { ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, ouya_devices); ++ ++static struct hid_driver ouya_driver = { ++ .name = "ouya", ++ .id_table = ouya_devices, ++ .probe = ouya_probe, ++ .remove = ouya_remove, ++ .input_mapping = ouya_input_mapping, ++ .report_fixup = ouya_report_fixup ++}; ++ ++static int __init ouya_init(void) ++{ ++ return hid_register_driver(&ouya_driver); ++} ++ ++static void __exit ouya_exit(void) ++{ ++ hid_unregister_driver(&ouya_driver); ++} ++ ++module_init(ouya_init); ++module_exit(ouya_exit); +diff -Naur linux-3.19.orig/drivers/hid/Kconfig linux-3.19/drivers/hid/Kconfig +--- linux-3.19.orig/drivers/hid/Kconfig 2015-02-20 14:01:17.081322855 -0800 ++++ linux-3.19/drivers/hid/Kconfig 2015-02-20 14:03:30.381519473 -0800 +@@ -528,6 +528,12 @@ + - Ortek WKB-2000 + - Skycable wireless presenter + ++config HID_OUYA ++ tristate "OUYA Game Controller" ++ depends on USB_HID ++ ---help--- ++ Support for OUYA Game Controller. ++ + config HID_PANTHERLORD + tristate "Pantherlord/GreenAsia game controller" + depends on HID +diff -Naur linux-3.19.orig/drivers/hid/Makefile linux-3.19/drivers/hid/Makefile +--- linux-3.19.orig/drivers/hid/Makefile 2015-02-20 14:01:17.081322855 -0800 ++++ linux-3.19/drivers/hid/Makefile 2015-02-20 14:03:30.382519482 -0800 +@@ -70,6 +70,7 @@ + obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o + obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o + obj-$(CONFIG_HID_ORTEK) += hid-ortek.o ++obj-$(CONFIG_HID_OUYA) += hid-ouya.o + obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o + obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o + obj-$(CONFIG_HID_PENMOUNT) += hid-penmount.o diff --git a/packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch b/packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch new file mode 100644 index 0000000000..6b43f9b315 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch @@ -0,0 +1,1029 @@ +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Kconfig linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig +--- linux-3.9.4/drivers/staging/media/lirc/Kconfig 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig 2013-05-30 18:18:57.238957100 +0200 +@@ -63,10 +63,17 @@ + help + Driver for the SIR IrDA port + ++config LIRC_XBOX ++ tristate "XBOX USB IR Remote" ++ depends on LIRC && USB ++ help ++ Driver for the Microsoft XBOX USB IR Remote ++ + config LIRC_ZILOG + tristate "Zilog/Hauppauge IR Transmitter" + depends on LIRC && I2C + help + Driver for the Zilog/Hauppauge IR Transmitter, found on + PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards ++ + endif +diff -Naur linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c +--- linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c 2013-05-30 18:40:22.523775446 +0200 +@@ -0,0 +1,995 @@ ++/* ++ * lirc_xbox - USB remote support for LIRC ++ * (supports Microsoft XBOX DVD Dongle) ++ * ++ * Copyright (C) 2003-2004 Paul Miller ++ * ++ * This driver was derived from: ++ * Vladimir Dergachev 's 2002 ++ * "USB ATI Remote support" (input device) ++ * Adrian Dewhurst 's 2002 ++ * "USB StreamZap remote driver" (LIRC) ++ * Artur Lipowski 's 2002 ++ * "lirc_dev" and "lirc_gpio" LIRC modules ++ * Michael Wojciechowski ++ * initial xbox support ++ * Vassilis Virvilis 2006 ++ * reworked the patch for lirc submission ++ * Paul Miller's 2004 ++ * lirc_atiusb - removed all ati remote support ++ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++ ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) ++//#include ++//#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//#include "drivers/kcompat.h" ++//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) ++#include ++#include ++//#else ++//#include "drivers/lirc.h" ++//#include "drivers/lirc_dev/lirc_dev.h" ++//#endif ++ ++#define DRIVER_VERSION "$Revision: 0.01 $" ++#define DRIVER_AUTHOR "Jason Martin " ++#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" ++#define DRIVER_NAME "lirc_xbox" ++ ++#define CODE_LENGTH 6 ++#define CODE_MIN_LENGTH 6 ++#define DECODE_LENGTH 1 ++ ++#ifndef URB_ASYNC_UNLINK ++#define URB_ASYNC_UNLINK 0 ++#endif ++ ++/* module parameters */ ++#ifdef CONFIG_USB_DEBUG ++static int debug = 1; ++#else ++static int debug; ++#endif ++ ++#define dprintk(fmt, args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_DEBUG fmt, ## args); \ ++ } while (0) ++ ++/* ++ * USB_BUFF_LEN must be the maximum value of the code_length array. ++ * It is used for static arrays. ++ */ ++#define USB_BUFF_LEN 6 ++ ++static int mask = 0xFFFF; /* channel acceptance bit mask */ ++static int unique; /* enable channel-specific codes */ ++static int repeat = 10; /* repeat time in 1/100 sec */ ++static unsigned long repeat_jiffies; /* repeat timeout */ ++ ++/* get hi and low bytes of a 16-bits int */ ++#define HI(a) ((unsigned char)((a) >> 8)) ++#define LO(a) ((unsigned char)((a) & 0xff)) ++ ++/* general constants */ ++#define SEND_FLAG_IN_PROGRESS 1 ++#define SEND_FLAG_COMPLETE 2 ++#define FREE_ALL 0xFF ++ ++/* endpoints */ ++#define EP_KEYS 0 ++#define EP_MOUSE 1 ++#define EP_MOUSE_ADDR 0x81 ++#define EP_KEYS_ADDR 0x82 ++ ++/* USB vendor ids for XBOX DVD Dongles */ ++#define VENDOR_MS1 0x040b ++#define VENDOR_MS2 0x045e ++#define VENDOR_MS3 0xFFFF ++ ++static struct usb_device_id usb_remote_table[] = { ++ /* Gamester Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS1, 0x6521) }, ++ ++ /* Microsoft Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS2, 0x0284) }, ++ ++ /* ++ * Some Chinese manufacturer -- conflicts with the joystick from the ++ * same manufacturer ++ */ ++ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, ++ ++ /* Terminating entry */ ++ { } ++}; ++ ++/* init strings */ ++#define USB_OUTLEN 7 ++ ++static char init1[] = {0x01, 0x00, 0x20, 0x14}; ++static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; ++ ++struct in_endpt { ++ /* inner link in list of endpoints for the remote specified by ir */ ++ struct list_head iep_list_link; ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ unsigned int len; ++ dma_addr_t dma; ++ ++ /* handle repeats */ ++ unsigned char old[USB_BUFF_LEN]; ++ unsigned long old_jiffies; ++}; ++ ++struct out_endpt { ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ dma_addr_t dma; ++ ++ /* handle sending (init strings) */ ++ int send_flags; ++ wait_queue_head_t wait; ++}; ++ ++ ++/* data structure for each usb remote */ ++struct xbox_dev { ++ /* inner link in list of all remotes managed by this module */ ++ struct list_head remote_list_link; ++ /* Number of usb interfaces associated with this device */ ++ int dev_refcount; ++ ++ /* usb */ ++ struct usb_device *usbdev; ++ /* Head link to list of all inbound endpoints in this remote */ ++ struct list_head iep_listhead; ++ struct out_endpt *out_init; ++ int devnum; ++ ++ /* lirc */ ++ struct lirc_driver *d; ++ int connected; ++ ++ /* locking */ ++ struct mutex lock; ++}; ++ ++/* list of all registered devices via the remote_list_link in xbox_dev */ ++static struct list_head remote_list; ++ ++/* ++ * Convenience macros to retrieve a pointer to the surrounding struct from ++ * the given list_head reference within, pointed at by link. ++ */ ++#define get_iep_from_link(link) \ ++ list_entry((link), struct in_endpt, iep_list_link); ++#define get_irctl_from_link(link) \ ++ list_entry((link), struct xbox_dev, remote_list_link); ++ ++/* send packet - used to initialize remote */ ++static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) ++{ ++ struct xbox_dev *ir = oep->ir; ++ DECLARE_WAITQUEUE(wait, current); ++ int timeout = HZ; /* 1 second */ ++ unsigned char buf[USB_OUTLEN]; ++ ++ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); ++ ++ mutex_lock(&ir->lock); ++ oep->urb->transfer_buffer_length = LO(cmd) + 1; ++ oep->urb->dev = oep->ir->usbdev; ++ oep->send_flags = SEND_FLAG_IN_PROGRESS; ++ ++ memcpy(buf+1, data, LO(cmd)); ++ buf[0] = HI(cmd); ++ memcpy(oep->buf, buf, LO(cmd)+1); ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&oep->wait, &wait); ++ ++ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++ ++ while (timeout && (oep->urb->status == -EINPROGRESS) ++ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { ++ timeout = schedule_timeout(timeout); ++ rmb(); ++ } ++ ++ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++} ++ ++static int unregister_from_lirc(struct xbox_dev *ir) ++{ ++ struct lirc_driver *d = ir->d; ++ int devnum; ++ ++ devnum = ir->devnum; ++ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); ++ ++ lirc_unregister_driver(d->minor); ++ ++ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); ++ return 0; ++} ++ ++static int set_use_inc(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ int rtn; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); ++ return -EIO; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (!ir->connected) { ++ if (!ir->usbdev) { ++ mutex_unlock(&ir->lock); ++ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); ++ return -ENOENT; ++ } ++ ++ /* Iterate through the inbound endpoints */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ /* extract the current in_endpt */ ++ iep = get_iep_from_link(pos); ++ iep->urb->dev = ir->usbdev; ++ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); ++ if (rtn) { ++ printk(DRIVER_NAME "[%d]: open result = %d " ++ "error submitting urb\n", ++ ir->devnum, rtn); ++ mutex_unlock(&ir->lock); ++ return -EIO; ++ } ++ } ++ ir->connected = 1; ++ } ++ mutex_unlock(&ir->lock); ++ ++ return 0; ++} ++ ++static void set_use_dec(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); ++ return; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (ir->connected) { ++ /* Free inbound usb urbs */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ iep = get_iep_from_link(pos); ++ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ usb_kill_urb(iep->urb); ++ } ++ ir->connected = 0; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static void print_data(struct in_endpt *iep, char *buf, int len) ++{ ++ const int clen = CODE_LENGTH; ++ char codes[clen * 3 + 1]; ++ int i; ++ ++ if (len <= 0) ++ return; ++ ++ for (i = 0; i < len && i < clen; i++) ++ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); ++ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", ++ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); ++} ++ ++static int code_check_xbox(struct in_endpt *iep, int len) ++{ ++ // struct xbox_dev *ir = iep->ir; ++ const int clen = CODE_LENGTH; ++ ++ if (len != clen) { ++ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " ++ "ir.. ?\n", len, clen); ++ return -1; ++ } ++ ++ /* check for repeats */ ++ if (memcmp(iep->old, iep->buf, len) == 0) { ++ if (iep->old_jiffies + repeat_jiffies > jiffies) ++ return -1; ++ } else { ++ /* ++ * the third byte of xbox ir packet seems to contain key info ++ * the last two bytes are.. some kind of clock? ++ */ ++ iep->buf[0] = iep->buf[2]; ++ memset(iep->buf + 1, 0, len - 1); ++ memcpy(iep->old, iep->buf, len); ++ } ++ iep->old_jiffies = jiffies; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_recv(struct urb *urb) ++#endif ++{ ++ struct in_endpt *iep; ++ int len, result = -1; ++ ++ if (!urb) ++ return; ++ iep = urb->context; ++ if (!iep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!iep->ir->usbdev) ++ return; ++ ++ len = urb->actual_length; ++ if (debug) ++ print_data(iep, urb->transfer_buffer, len); ++ ++ switch (urb->status) { ++ ++ case 0: ++ result = code_check_xbox(iep, len); ++ ++ if (result < 0) ++ break; ++ ++ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); ++ wake_up(&iep->ir->d->rbuf->wait_poll); ++ break; ++ ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ ++ case -EPIPE: ++ default: ++ break; ++ } ++ ++ usb_submit_urb(urb, GFP_ATOMIC); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_send(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_send(struct urb *urb) ++#endif ++{ ++ struct out_endpt *oep; ++ ++ if (!urb) ++ return; ++ oep = urb->context; ++ if (!oep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!oep->ir->usbdev) ++ return; ++ ++ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); ++ ++ if (urb->status) ++ return; ++ ++ oep->send_flags |= SEND_FLAG_COMPLETE; ++ wmb(); ++ if (waitqueue_active(&oep->wait)) ++ wake_up(&oep->wait); ++} ++ ++ ++/* ++ * Initialization and removal ++ */ ++ ++/* ++ * Free iep according to mem_failure which specifies a checkpoint into the ++ * initialization sequence for rollback recovery. ++ */ ++static void free_in_endpt(struct in_endpt *iep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); ++ if (!iep) ++ return; ++ ++ ir = iep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 5: ++ list_del(&iep->iep_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " ++ "from list\n", ir->devnum, iep->ep->bEndpointAddress); ++ case 4: ++ if (iep->urb) { ++ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(iep->urb); ++ usb_free_urb(iep->urb); ++ iep->urb = 0; ++ } else ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", ++ ir->devnum); ++ case 3: ++ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); ++ iep->buf = 0; ++ case 2: ++ kfree(iep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++/* ++ * Construct a new inbound endpoint for this remote, and add it to the list of ++ * in_epts in ir. ++ */ ++static struct in_endpt *new_in_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct in_endpt *iep; ++ int pipe, maxp, len, addr; ++ int mem_failure; ++ ++ addr = ep->bEndpointAddress; ++ pipe = usb_rcvintpipe(dev, addr); ++ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ++ ++/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; ++ * len -= (len % CODE_LENGTH); */ ++ len = CODE_LENGTH; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " ++ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); ++ ++ mem_failure = 0; ++ iep = kzalloc(sizeof(*iep), GFP_KERNEL); ++ if (!iep) { ++ mem_failure = 1; ++ goto new_in_endpt_failure_check; ++ } ++ iep->ir = ir; ++ iep->ep = ep; ++ iep->len = len; ++ ++ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); ++ if (!iep->buf) { ++ mem_failure = 2; ++ goto new_in_endpt_failure_check; ++ } ++ ++ iep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!iep->urb) ++ mem_failure = 3; ++ ++new_in_endpt_failure_check: ++ ++ if (mem_failure) { ++ free_in_endpt(iep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, addr, mem_failure); ++ return NULL; ++ } ++ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); ++ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", ++ ir->devnum, iep->ep->bEndpointAddress); ++ return iep; ++} ++ ++static void free_out_endpt(struct out_endpt *oep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); ++ if (!oep) ++ return; ++ ++ wake_up_all(&oep->wait); ++ ++ ir = oep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 4: ++ if (oep->urb) { ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++ usb_free_urb(oep->urb); ++ oep->urb = 0; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", ++ ir->devnum); ++ } ++ case 3: ++ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, ++ oep->buf, oep->dma); ++ oep->buf = 0; ++ case 2: ++ kfree(oep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct out_endpt *new_out_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct out_endpt *oep; ++ int mem_failure; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", ++ ir->devnum, ep->bEndpointAddress); ++ ++ mem_failure = 0; ++ oep = kzalloc(sizeof(*oep), GFP_KERNEL); ++ if (!oep) ++ mem_failure = 1; ++ else { ++ oep->ir = ir; ++ oep->ep = ep; ++ init_waitqueue_head(&oep->wait); ++ ++ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, ++ GFP_ATOMIC, &oep->dma); ++ if (!oep->buf) ++ mem_failure = 2; ++ else { ++ oep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!oep->urb) ++ mem_failure = 3; ++ } ++ } ++ if (mem_failure) { ++ free_out_endpt(oep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, ep->bEndpointAddress, mem_failure); ++ return NULL; ++ } ++ return oep; ++} ++ ++static void free_irctl(struct xbox_dev *ir, int mem_failure) ++{ ++ struct list_head *pos, *n; ++ struct in_endpt *in; ++ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); ++ ++ if (!ir) ++ return; ++ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ in = get_iep_from_link(pos); ++ free_in_endpt(in, FREE_ALL); ++ } ++ if (ir->out_init) { ++ free_out_endpt(ir->out_init, FREE_ALL); ++ ir->out_init = NULL; ++ } ++ ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 6: ++ if (!--ir->dev_refcount) { ++ list_del(&ir->remote_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " ++ "remote from list\n", ir->devnum); ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," ++ "aborting free_irctl\n", ++ ir->devnum, ir->dev_refcount); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ case 5: ++ case 4: ++ case 3: ++ if (ir->d) { ++ switch (mem_failure) { ++ case 5: ++ lirc_buffer_free(ir->d->rbuf); ++ case 4: ++ kfree(ir->d->rbuf); ++ case 3: ++ kfree(ir->d); ++ } ++ } else ++ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", ++ ir->devnum); ++ case 2: ++ mutex_unlock(&ir->lock); ++ kfree(ir); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct xbox_dev *new_irctl(struct usb_interface *intf) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct xbox_dev *ir; ++ struct lirc_driver *driver; ++ int devnum, dclen; ++ int mem_failure; ++ ++ devnum = dev->devnum; ++ ++ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); ++ ++ mem_failure = 0; ++ ir = kzalloc(sizeof(*ir), GFP_KERNEL); ++ if (!ir) { ++ mem_failure = 1; ++ goto new_irctl_failure_check; ++ } ++ ++ dclen = DECODE_LENGTH; ++ ++ /* ++ * add this infrared remote struct to remote_list, keeping track ++ * of the number of drivers registered. ++ */ ++ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); ++ list_add_tail(&ir->remote_list_link, &remote_list); ++ ir->dev_refcount = 1; ++ ++ driver = kzalloc(sizeof(*driver), GFP_KERNEL); ++ if (!driver) { ++ mem_failure = 2; ++ goto new_irctl_failure_check; ++ } ++ ++ ir->d = driver; ++ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); ++ if (!driver->rbuf) { ++ mem_failure = 3; ++ goto new_irctl_failure_check; ++ } ++ ++ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { ++ mem_failure = 4; ++ goto new_irctl_failure_check; ++ } ++ ++ strcpy(driver->name, DRIVER_NAME " "); ++ driver->minor = -1; ++ driver->code_length = dclen * 8; ++ driver->features = LIRC_CAN_REC_LIRCCODE; ++ driver->data = ir; ++ driver->set_use_inc = &set_use_inc; ++ driver->set_use_dec = &set_use_dec; ++ driver->dev = &intf->dev; ++ driver->owner = THIS_MODULE; ++ ir->usbdev = dev; ++ ir->devnum = devnum; ++ ++ mutex_init(&ir->lock); ++ INIT_LIST_HEAD(&ir->iep_listhead); ++ ++new_irctl_failure_check: ++ ++ if (mem_failure) { ++ free_irctl(ir, mem_failure); ++ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", ++ devnum, mem_failure); ++ return NULL; ++ } ++ return ir; ++} ++ ++/* ++ * Scan the global list of remotes to see if the device listed is one of them. ++ * If it is, the corresponding xbox_dev is returned, with its dev_refcount ++ * incremented. Otherwise, returns null. ++ */ ++static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) ++{ ++ struct list_head *pos; ++ struct xbox_dev *ir = NULL; ++ ++ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); ++ list_for_each(pos, &remote_list) { ++ ir = get_irctl_from_link(pos); ++ if (ir->usbdev != dev) { ++ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", ++ dev->devnum, ir->devnum); ++ ir = NULL; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", ++ dev->devnum); ++ ir->dev_refcount++; ++ break; ++ } ++ } ++ return ir; ++} ++ ++/* ++ * If the USB interface has an out endpoint for control. ++ */ ++static void send_outbound_init(struct xbox_dev *ir) ++{ ++ if (ir->out_init) { ++ struct out_endpt *oep = ir->out_init; ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " ++ "outbound ep\n", ir->devnum); ++ usb_fill_int_urb(oep->urb, ir->usbdev, ++ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), ++ oep->buf, USB_OUTLEN, usb_remote_send, ++ oep, oep->ep->bInterval); ++ oep->urb->transfer_dma = oep->dma; ++ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ send_packet(oep, 0x8004, init1); ++ send_packet(oep, 0x8007, init2); ++ } ++} ++ ++/* Log driver and usb info */ ++static void log_usb_dev_info(struct usb_device *dev) ++{ ++ char buf[63], name[128] = ""; ++ ++ if (dev->descriptor.iManufacturer ++ && usb_string(dev, dev->descriptor.iManufacturer, ++ buf, sizeof(buf)) > 0) ++ strlcpy(name, buf, sizeof(name)); ++ if (dev->descriptor.iProduct ++ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) ++ snprintf(name + strlen(name), sizeof(name) - strlen(name), ++ " %s", buf); ++ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, ++ dev->bus->busnum, dev->devnum); ++} ++ ++ ++static int usb_remote_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct usb_host_interface *idesc; ++ struct usb_endpoint_descriptor *ep; ++ struct in_endpt *iep; ++ struct xbox_dev *ir; ++ int i; ++ ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", ++ dev->devnum, dev, intf, id); ++ ++ idesc = intf->cur_altsetting; ++ ++ /* Check if a usb remote has already been registered for this device */ ++ ir = get_prior_reg_ir(dev); ++ ++ if (!ir) { ++ ir = new_irctl(intf); ++ if (!ir) ++ return -ENOMEM; ++ } ++ ++ /* ++ * step through the endpoints to find first in and first out endpoint ++ * of type interrupt transfer ++ */ ++ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { ++ ep = &idesc->endpoint[i].desc; ++ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", ++ dev->devnum, i); ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_IN) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT)) { ++ ++ iep = new_in_endpt(ir, ep); ++ if (iep) ++ { ++ usb_fill_int_urb(iep->urb, dev, ++ usb_rcvintpipe(dev, ++ iep->ep->bEndpointAddress), ++ iep->buf, iep->len, usb_remote_recv, ++ iep, iep->ep->bInterval); ++ iep->urb->transfer_dma = iep->dma; ++ iep->urb->transfer_flags |= ++ URB_NO_TRANSFER_DMA_MAP; ++ } ++ } ++ ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_OUT) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT) && ++ (ir->out_init == NULL)) ++ ir->out_init = new_out_endpt(ir, ep); ++ } ++ if (list_empty(&ir->iep_listhead)) { ++ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", ++ ir->devnum); ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ if (ir->dev_refcount == 1) { ++ ir->d->minor = lirc_register_driver(ir->d); ++ if (ir->d->minor < 0) { ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ ++ /* Note new driver registration in kernel logs */ ++ log_usb_dev_info(dev); ++ ++ /* outbound data (initialization) */ ++ send_outbound_init(ir); ++ } ++ ++ usb_set_intfdata(intf, ir); ++ return 0; ++} ++ ++static void usb_remote_disconnect(struct usb_interface *intf) ++{ ++ /* struct usb_device *dev = interface_to_usbdev(intf); */ ++ struct xbox_dev *ir = usb_get_intfdata(intf); ++ usb_set_intfdata(intf, NULL); ++ ++ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", ++ (ir ? ir->devnum : -1)); ++ if (!ir || !ir->d) ++ return; ++ ++ if (ir->usbdev) { ++ /* Only unregister once */ ++ ir->usbdev = NULL; ++ unregister_from_lirc(ir); ++ } ++ ++ /* This also removes the current remote from remote_list */ ++ free_irctl(ir, FREE_ALL); ++} ++ ++static struct usb_driver usb_remote_driver = { ++ .name = DRIVER_NAME, ++ .probe = usb_remote_probe, ++ .disconnect = usb_remote_disconnect, ++ .id_table = usb_remote_table ++}; ++ ++static int __init usb_remote_init(void) ++{ ++ int i; ++ ++ INIT_LIST_HEAD(&remote_list); ++ ++ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " ++ DRIVER_VERSION "\n"); ++ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); ++ dprintk(DRIVER_NAME ": debug mode enabled: " ++ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); ++ ++ repeat_jiffies = repeat*HZ/100; ++ ++ i = usb_register(&usb_remote_driver); ++ if (i) { ++ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit usb_remote_exit(void) ++{ ++ usb_deregister(&usb_remote_driver); ++} ++ ++module_init(usb_remote_init); ++module_exit(usb_remote_exit); ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(usb, usb_remote_table); ++ ++module_param(debug, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); ++ ++module_param(mask, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); ++ ++module_param(unique, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); ++ ++module_param(repeat, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Makefile linux-3.9.4.patch/drivers/staging/media/lirc/Makefile +--- linux-3.9.4/drivers/staging/media/lirc/Makefile 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Makefile 2013-05-30 18:17:39.163634834 +0200 +@@ -10,4 +10,5 @@ + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o + obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o + obj-$(CONFIG_LIRC_SIR) += lirc_sir.o ++obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o + obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch new file mode 100644 index 0000000000..a4068872d2 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch @@ -0,0 +1,161 @@ +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,9 @@ + { 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) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, + { 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,9 @@ + + #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_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 @@ ++/* ++ * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes ++ * ++ * Copyright (c) 2010 Panagiotis Skintzos ++ * ++ * Renamed to Spinel, cleanup and modified to also support ++ * Spinel Plus 0471:20CC by Stephan Raue 2012. ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define spinelplus_map_key(c) set_bit(EV_REP, hi->input->evbit); \ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) ++ ++static int spinelplus_input_mapping(struct hid_device *hdev, ++ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ switch (usage->hid) { ++ case 0xffbc000d: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0024: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0027: spinelplus_map_key(KEY_ZOOM); break; ++ case 0xffbc0033: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0035: spinelplus_map_key(KEY_CAMERA); break; ++ case 0xffbc0036: spinelplus_map_key(KEY_EPG); break; ++ case 0xffbc0037: spinelplus_map_key(KEY_DVD); break; ++ case 0xffbc0038: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0039: spinelplus_map_key(KEY_MP3); break; ++ case 0xffbc003a: spinelplus_map_key(KEY_VIDEO); break; ++ case 0xffbc005a: spinelplus_map_key(KEY_TEXT); break; ++ case 0xffbc005b: spinelplus_map_key(KEY_RED); break; ++ case 0xffbc005c: spinelplus_map_key(KEY_GREEN); break; ++ case 0xffbc005d: spinelplus_map_key(KEY_YELLOW); break; ++ case 0xffbc005e: spinelplus_map_key(KEY_BLUE); break; ++ default: ++ return 0; ++ } ++ return 1; ++} ++ ++static int spinelplus_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ int ret; ++ /* Connect only to hid input (not hiddev & hidraw)*/ ++ unsigned int cmask = HID_CONNECT_HIDINPUT; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ dev_err(&hdev->dev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, cmask); ++ if (ret) { ++ dev_err(&hdev->dev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++err_free: ++ return ret; ++} ++ ++static const struct hid_device_id spinelplus_devices[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, spinelplus_devices); ++ ++static struct hid_driver spinelplus_driver = { ++ .name = "SpinelPlus", ++ .id_table = spinelplus_devices, ++ .input_mapping = spinelplus_input_mapping, ++ .probe = spinelplus_probe, ++}; ++ ++static int __init spinelplus_init(void) ++{ ++ return hid_register_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) 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/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch new file mode 100644 index 0000000000..08566d1f13 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch @@ -0,0 +1,12 @@ +diff -Naur linux-3.0/drivers/media/rc/nuvoton-cir.c linux-3.0.patch/drivers/media/rc/nuvoton-cir.c +--- linux-3.0/drivers/media/rc/nuvoton-cir.c 2011-07-22 04:17:23.000000000 +0200 ++++ linux-3.0.patch/drivers/media/rc/nuvoton-cir.c 2011-07-22 21:30:48.374591146 +0200 +@@ -1110,7 +1110,7 @@ + rdev->dev.parent = &pdev->dev; + rdev->driver_name = NVT_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; +- rdev->timeout = MS_TO_NS(100); ++ rdev->timeout = US_TO_NS(1000); + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ + rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); + #if 0 diff --git a/packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch b/packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch new file mode 100644 index 0000000000..4116b9ff86 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch @@ -0,0 +1,21 @@ +diff -Naur linux-3.17.1/drivers/media/rc/mceusb.c linux-3.17.1.patch/drivers/media/rc/mceusb.c +--- linux-3.17.1/drivers/media/rc/mceusb.c 2014-10-15 12:29:30.000000000 +0200 ++++ linux-3.17.1.patch/drivers/media/rc/mceusb.c 2014-10-16 11:45:57.480176874 +0200 +@@ -188,6 +188,8 @@ + #define VENDOR_TWISTEDMELON 0x2596 + #define VENDOR_HAUPPAUGE 0x2040 + #define VENDOR_PCTV 0x2013 ++#define VENDOR_ADAPTEC 0x03f3 ++ + + enum mceusb_model_type { + MCE_GEN2 = 0, /* Most boards */ +@@ -401,6 +403,8 @@ + .driver_info = HAUPPAUGE_CX_HYBRID_TV }, + { USB_DEVICE(VENDOR_PCTV, 0x025e), + .driver_info = HAUPPAUGE_CX_HYBRID_TV }, ++ /* Adaptec / HP eHome Receiver */ ++ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, + + /* Terminating entry */ + { } diff --git a/packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch new file mode 100644 index 0000000000..2bc9542311 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch @@ -0,0 +1,28 @@ +--- linux/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:08:13.148418669 -0800 ++++ linux.patch/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:07:48.864417975 -0800 +@@ -39,7 +39,6 @@ + #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ +-#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ + #endif +@@ -257,14 +256,9 @@ again: + toggle = 0; + break; + case 32: +- if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { +- protocol = RC_TYPE_RC6_MCE; +- toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); +- scancode &= ~RC6_6A_MCE_TOGGLE_MASK; +- } else { +- protocol = RC_BIT_RC6_6A_32; +- toggle = 0; +- } ++ protocol = RC_TYPE_RC6_MCE; ++ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); ++ scancode &= ~RC6_6A_MCE_TOGGLE_MASK; + break; + default: + IR_dprintk(1, "RC6(6A) unsupported length\n"); diff --git a/packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch b/packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch new file mode 100644 index 0000000000..67fc7a0de8 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch @@ -0,0 +1,13 @@ +diff -Naur linux-3.9.4/drivers/media/rc/mceusb.c linux-3.9.4.patch/drivers/media/rc/mceusb.c +--- linux-3.9.4/drivers/media/rc/mceusb.c 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/media/rc/mceusb.c 2013-05-27 12:28:12.811230633 +0200 +@@ -309,6 +309,9 @@ + /* SMK/I-O Data GV-MC7/RCKIT Receiver */ + { USB_DEVICE(VENDOR_SMK, 0x0353), + .driver_info = MCE_GEN2_NO_TX }, ++ /* SMK Manufacturing, Inc. Receiver */ ++ { USB_DEVICE(VENDOR_SMK, 0x0357), ++ .driver_info = MCE_GEN2_NO_TX }, + /* Tatung eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, + /* Shuttle eHome Infrared Transceiver */ diff --git a/packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 0000000000..6fa866dfe8 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,64 @@ +From 7051422474e4c4e302ede3d07ffd8ef2682e07a2 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 22 Apr 2014 16:05:14 +0300 +Subject: [PATCH] [RFC] hid/sony: add autorepeat for PS3 remotes + +adapted to 3.17 + +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. +--- +diff -Naur linux-3.17.1/drivers/hid/hid-sony.c linux-3.17.1.patch/drivers/hid/hid-sony.c +--- linux-3.17.1/drivers/hid/hid-sony.c 2014-10-15 12:29:30.000000000 +0200 ++++ linux-3.17.1.patch/drivers/hid/hid-sony.c 2014-10-16 12:55:43.979181366 +0200 +@@ -875,6 +875,25 @@ + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} ++ + static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +@@ -1932,6 +1951,8 @@ + goto err_stop; + + sony_init_work(sc, dualshock4_state_worker); ++ } else if (sc->quirks & PS3REMOTE) { ++ ret = ps3remote_setup_repeat(hdev); + } else { + ret = 0; + } diff --git a/packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch b/packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch new file mode 100644 index 0000000000..677de3ed7f --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch @@ -0,0 +1,21 @@ +diff -Naur linux-3.16.1/drivers/media/rc/imon.c linux-3.16.1.patch/drivers/media/rc/imon.c +--- linux-3.16.1/drivers/media/rc/imon.c 2014-08-14 04:36:35.000000000 +0200 ++++ linux-3.16.1.patch/drivers/media/rc/imon.c 2014-08-15 13:57:16.587620642 +0200 +@@ -1344,6 +1344,17 @@ + } + } else { + /* ++ * For users without stabilized, just ignore any value getting ++ * to close to the diagonal. ++ */ ++ if ((abs(rel_y) < 2 && abs(rel_x) < 2) || ++ abs(abs(rel_y) - abs(rel_x)) < 2 ) { ++ spin_lock_irqsave(&ictx->kc_lock, flags); ++ ictx->kc = KEY_UNKNOWN; ++ spin_unlock_irqrestore(&ictx->kc_lock, flags); ++ return; ++ } ++ /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ diff --git a/packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch b/packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch new file mode 100644 index 0000000000..f302b6ce1b --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch @@ -0,0 +1,12 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:25:43.479645317 +0100 +@@ -1581,7 +1581,7 @@ + .frequency_max = 2150000, + .frequency_stepsize = 0, + .frequency_tolerance = 0, +- .symbol_rate_min = 5000000, ++ .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + + .caps = FE_CAN_INVERSION_AUTO | diff --git a/packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch b/packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch new file mode 100644 index 0000000000..eef4e1effc --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch @@ -0,0 +1,138 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-16 10:28:33.633409961 +0100 +@@ -206,7 +206,6 @@ + static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) + { + struct stb0899_internal *internal = &state->internal; +- struct stb0899_params *params = &state->params; + + short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; + int index = 0; +@@ -216,10 +215,9 @@ + + /* timing loop computation & symbol rate optimisation */ + derot_limit = (internal->sub_range / 2L) / internal->mclk; +- derot_step = (params->srate / 2L) / internal->mclk; ++ derot_step = internal->derot_step * 4; /* dertot_step = decreasing delta */ + + while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { +- index++; + derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ + + if (abs(derot_freq) > derot_limit) +@@ -230,6 +228,7 @@ + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + } ++ index++; + internal->direction = -internal->direction; /* Change zigzag direction */ + } + +@@ -278,14 +277,18 @@ + { + struct stb0899_internal *internal = &state->internal; + +- short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; ++ short int derot_freq = 0, last_derot_freq = 0, derot_limit, derot_step, next_loop = 3; + int index = 0; ++ int base_freq; + u8 cfr[2]; + u8 reg; + + internal->status = NOCARRIER; + derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_freq = internal->derot_freq; ++ derot_step = internal->derot_step * 2; ++ last_derot_freq = internal->derot_freq; ++ base_freq = internal->derot_freq; + + reg = stb0899_read_reg(state, STB0899_CFD); + STB0899_SETFIELD_VAL(CFD_ON, reg, 1); +@@ -294,11 +297,10 @@ + do { + dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); + if (stb0899_check_carrier(state) == NOCARRIER) { +- index++; + last_derot_freq = derot_freq; +- derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ ++ derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ + +- if(abs(derot_freq) > derot_limit) ++ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) + next_loop--; + + if (next_loop) { +@@ -310,9 +312,10 @@ + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + } ++ index++; ++ internal->direction = -internal->direction; /* Change zigzag direction */ + } + +- internal->direction = -internal->direction; /* Change zigzag direction */ + } while ((internal->status != CARRIEROK) && next_loop); + + if (internal->status == CARRIEROK) { +@@ -338,6 +341,7 @@ + int lock = 0, index = 0, dataTime = 500, loop; + u8 reg; + ++ msleep(1); + internal->status = NODATA; + + /* RESET FEC */ +@@ -348,6 +352,7 @@ + reg = stb0899_read_reg(state, STB0899_TSTRES); + STB0899_SETFIELD_VAL(FRESACS, reg, 0); + stb0899_write_reg(state, STB0899_TSTRES, reg); ++ msleep(1); + + if (params->srate <= 2000000) + dataTime = 2000; +@@ -363,6 +368,7 @@ + + stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ + while (1) { ++ msleep(1); // Alex: added 1 mSec + /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ + reg = stb0899_read_reg(state, STB0899_VSTATUS); + lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); +@@ -390,20 +396,21 @@ + short int derot_freq, derot_step, derot_limit, next_loop = 3; + u8 cfr[2]; + u8 reg; +- int index = 1; ++ int index = 0; ++ int base_freq; + + struct stb0899_internal *internal = &state->internal; +- struct stb0899_params *params = &state->params; + +- derot_step = (params->srate / 4L) / internal->mclk; ++ derot_step = internal->derot_step; + derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_freq = internal->derot_freq; ++ base_freq = internal->derot_freq; + + do { + if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { + + derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ +- if (abs(derot_freq) > derot_limit) ++ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) + next_loop--; + + if (next_loop) { +@@ -417,9 +424,9 @@ + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + + stb0899_check_carrier(state); +- index++; + } + } ++ index++; + internal->direction = -internal->direction; /* change zig zag direction */ + } while ((internal->status != DATAOK) && next_loop); + diff --git a/packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch b/packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch new file mode 100644 index 0000000000..65cc8cb00e --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch @@ -0,0 +1,34137 @@ +From 4e0cb03f8d73ecda1283c6690f30b2944f169455 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Thu, 11 Jun 2015 10:45:56 +0300 +Subject: [PATCH] dvb: ngene/octopus + +source: http://linuxtv.org/hg/~endriss/media_build_experimental/ + +note: SYS_DVBC2 not added. ci extensions (en50221) not added. +--- + drivers/media/dvb-core/Makefile | 2 +- + drivers/media/dvb-core/dvb_netstream.c | 259 ++ + drivers/media/dvb-core/dvb_netstream.h | 94 + + drivers/media/dvb-core/dvbdev.c | 11 +- + drivers/media/dvb-core/dvbdev.h | 4 + + drivers/media/dvb-frontends/Kconfig | 27 + + drivers/media/dvb-frontends/Makefile | 3 + + drivers/media/dvb-frontends/cxd2843.c | 2022 ++++++++++++ + drivers/media/dvb-frontends/cxd2843.h | 30 + + drivers/media/dvb-frontends/drxk_hard.c | 3614 +++++++++----------- + drivers/media/dvb-frontends/drxk_hard.h | 298 +- + drivers/media/dvb-frontends/drxk_map.h | 3 - + drivers/media/dvb-frontends/lnbh25.c | 153 + + drivers/media/dvb-frontends/lnbh25.h | 28 + + drivers/media/dvb-frontends/stv0367dd.c | 2331 +++++++++++++ + drivers/media/dvb-frontends/stv0367dd.h | 17 + + drivers/media/dvb-frontends/stv0367dd_regs.h | 3431 +++++++++++++++++++ + drivers/media/dvb-frontends/stv090x.c | 45 +- + drivers/media/dvb-frontends/stv0910.c | 1371 ++++++++ + drivers/media/dvb-frontends/stv0910.h | 31 + + drivers/media/dvb-frontends/stv0910_regs.h | 3998 +++++++++++++++++++++++ + drivers/media/dvb-frontends/stv6111.c | 450 +++ + drivers/media/dvb-frontends/stv6111.h | 5 + + drivers/media/dvb-frontends/tda18212dd.c | 974 ++++++ + drivers/media/dvb-frontends/tda18212dd.h | 5 + + drivers/media/dvb-frontends/tda18271c2dd.c | 17 +- + drivers/media/dvb-frontends/tda18271c2dd.h | 6 +- + drivers/media/dvb-frontends/tda18271c2dd_maps.h | 8 +- + drivers/media/pci/ddbridge/Kconfig | 11 +- + drivers/media/pci/ddbridge/Makefile | 2 - + drivers/media/pci/ddbridge/ddbridge-core.c | 3941 ++++++++++++++++------ + drivers/media/pci/ddbridge/ddbridge-i2c.c | 257 ++ + drivers/media/pci/ddbridge/ddbridge-i2c.h | 105 + + drivers/media/pci/ddbridge/ddbridge-mod.c | 1148 +++++++ + drivers/media/pci/ddbridge/ddbridge-ns.c | 489 +++ + drivers/media/pci/ddbridge/ddbridge-regs.h | 347 +- + drivers/media/pci/ddbridge/ddbridge.c | 470 +++ + drivers/media/pci/ddbridge/ddbridge.h | 419 ++- + drivers/media/pci/ddbridge/octonet.c | 199 ++ + drivers/media/pci/ngene/Kconfig | 4 + + drivers/media/pci/ngene/Makefile | 3 +- + drivers/media/pci/ngene/ngene-av.c | 348 ++ + drivers/media/pci/ngene/ngene-cards.c | 975 ++++-- + drivers/media/pci/ngene/ngene-core.c | 410 ++- + drivers/media/pci/ngene/ngene-dvb.c | 379 ++- + drivers/media/pci/ngene/ngene-eeprom.c | 284 ++ + drivers/media/pci/ngene/ngene-i2c.c | 113 + + drivers/media/pci/ngene/ngene.h | 42 +- + include/uapi/linux/dvb/mod.h | 22 + + include/uapi/linux/dvb/ns.h | 68 + + 50 files changed, 25733 insertions(+), 3540 deletions(-) + create mode 100644 drivers/media/dvb-core/dvb_netstream.c + create mode 100644 drivers/media/dvb-core/dvb_netstream.h + create mode 100644 drivers/media/dvb-frontends/cxd2843.c + create mode 100644 drivers/media/dvb-frontends/cxd2843.h + create mode 100644 drivers/media/dvb-frontends/lnbh25.c + create mode 100644 drivers/media/dvb-frontends/lnbh25.h + create mode 100644 drivers/media/dvb-frontends/stv0367dd.c + create mode 100644 drivers/media/dvb-frontends/stv0367dd.h + create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h + create mode 100644 drivers/media/dvb-frontends/stv0910.c + create mode 100644 drivers/media/dvb-frontends/stv0910.h + create mode 100644 drivers/media/dvb-frontends/stv0910_regs.h + create mode 100644 drivers/media/dvb-frontends/stv6111.c + create mode 100644 drivers/media/dvb-frontends/stv6111.h + create mode 100644 drivers/media/dvb-frontends/tda18212dd.c + create mode 100644 drivers/media/dvb-frontends/tda18212dd.h + create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c + create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.h + create mode 100644 drivers/media/pci/ddbridge/ddbridge-mod.c + create mode 100644 drivers/media/pci/ddbridge/ddbridge-ns.c + create mode 100644 drivers/media/pci/ddbridge/ddbridge.c + create mode 100644 drivers/media/pci/ddbridge/octonet.c + create mode 100644 drivers/media/pci/ngene/ngene-av.c + create mode 100644 drivers/media/pci/ngene/ngene-eeprom.c + create mode 100644 include/uapi/linux/dvb/mod.h + create mode 100644 include/uapi/linux/dvb/ns.h + +diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile +index 8f22bcd..5ff851a 100644 +--- a/drivers/media/dvb-core/Makefile ++++ b/drivers/media/dvb-core/Makefile +@@ -6,6 +6,6 @@ dvb-net-$(CONFIG_DVB_NET) := dvb_net.o + + dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ + dvb_ca_en50221.o dvb_frontend.o \ +- $(dvb-net-y) dvb_ringbuffer.o dvb_math.o ++ $(dvb-net-y) dvb_ringbuffer.o dvb_math.o dvb_netstream.o + + obj-$(CONFIG_DVB_CORE) += dvb-core.o +diff --git a/drivers/media/dvb-core/dvb_netstream.c b/drivers/media/dvb-core/dvb_netstream.c +new file mode 100644 +index 0000000..43322c7 +--- /dev/null ++++ b/drivers/media/dvb-core/dvb_netstream.c +@@ -0,0 +1,259 @@ ++/* ++ * dvb_netstream.c: support for DVB to network streaming hardware ++ * ++ * Copyright (C) 2012-2013 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include "dvb_netstream.h" ++ ++static ssize_t ns_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++static ssize_t ns_read(struct file *file, char *buf, ++ size_t count, loff_t *ppos) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++static unsigned int ns_poll(struct file *file, poll_table *wait) ++{ ++ printk("%s\n", __func__); ++ return 0; ++} ++ ++static int ns_stop(struct dvbnss *nss) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ ++ mutex_lock(&ns->mutex); ++ if (nss->running && ns->stop) { ++ ns->stop(nss); ++ nss->running = 0; ++ } ++ mutex_unlock(&ns->mutex); ++ return 0; ++} ++ ++static int ns_release(struct inode *inode, struct file *file) ++{ ++ struct dvbnss *nss = file->private_data; ++ struct dvb_netstream *ns = nss->ns; ++ ++ ns_stop(nss); ++ if (ns->free) ++ ns->free(nss); ++ mutex_lock(&ns->mutex); ++ list_del(&nss->nssl); ++ mutex_unlock(&ns->mutex); ++ vfree(nss); ++ return 0; ++} ++ ++static int ns_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct dvb_netstream *ns = dvbdev->priv; ++ struct dvbnss *nss; ++ ++ nss = vmalloc(sizeof(*nss)); ++ if (!nss) ++ return -ENOMEM; ++ nss->ns = ns; ++ if (ns->alloc && ns->alloc(nss) < 0) { ++ vfree(nss); ++ return -EBUSY; ++ } ++ file->private_data = nss; ++ nss->running = 0; ++ mutex_lock(&ns->mutex); ++ list_add(&nss->nssl, &ns->nssl); ++ mutex_unlock(&ns->mutex); ++ return 0; ++} ++ ++static int set_net(struct dvbnss *nss, struct dvb_ns_params *p) ++{ ++ return 0; ++} ++ ++static int do_ioctl(struct file *file, unsigned int cmd, void *parg) ++{ ++ struct dvbnss *nss = file->private_data; ++ struct dvb_netstream *ns = nss->ns; ++ //unsigned long arg = (unsigned long) parg; ++ int ret = 0; ++ ++ switch (cmd) { ++ case NS_SET_RTCP_MSG: ++ { ++ struct dvb_ns_rtcp *rtcpm = parg; ++ ++ if (ns->set_rtcp_msg) { ++ //printk("%s calling NS_SET_RTCP_MSG\n", __func__); ++ ret = ns->set_rtcp_msg(nss, rtcpm->msg, rtcpm->len); ++ } ++ break; ++ } ++ ++ case NS_SET_NET: ++ memcpy(&nss->params, parg, sizeof(nss->params)); ++ if (ns->set_net) { ++ ret = ns->set_net(nss); ++ } else ++ ret = set_net(nss, (struct dvb_ns_params *) parg); ++ break; ++ ++ case NS_START: ++ mutex_lock(&ns->mutex); ++ if (nss->running) { ++ ret = -EBUSY; ++ } else if (ns->start) { ++ ret = ns->start(nss); ++ nss->running = 1; ++ } ++ mutex_unlock(&ns->mutex); ++ break; ++ ++ case NS_STOP: ++ ns_stop(nss); ++ break; ++ ++ case NS_SET_PACKETS: ++ { ++ struct dvb_ns_packet *packet = parg; ++ if (ns->set_ts_packets) { ++ ret = ns->set_ts_packets(nss, packet->buf, packet->count * 188); ++ } ++ break; ++ } ++ ++ case NS_INSERT_PACKETS: ++ { ++ u8 count = *(u8 *) parg; ++ if (ns->insert_ts_packets) ++ ret = ns->insert_ts_packets(nss, count); ++ break; ++ } ++ ++ case NS_SET_PID: ++ { ++ u16 pid = *(u16 *) parg; ++ u16 byte = (pid & 0x1fff) >> 3; ++ u8 bit = 1 << (pid & 7); ++ ++ if (pid & 0x2000) { ++ if (pid & 0x8000) ++ memset(nss->pids, 0xff, 0x400); ++ else ++ memset(nss->pids, 0x00, 0x400); ++ } else { ++ if (pid & 0x8000) ++ nss->pids[byte] |= bit; ++ else ++ nss->pids[byte] &= ~bit; ++ } ++ if (ns->set_pid) ++ ret = ns->set_pid(nss, pid); ++ break; ++ } ++ ++ case NS_SET_PIDS: ++ ret = copy_from_user(nss->pids, *(u8 **) parg, 0x400); ++ if (ret < 0) ++ return ret; ++ if (ns->set_pids) ++ ret = ns->set_pids(nss); ++ break; ++ ++ case NS_SET_CI: ++ { ++ u8 ci = *(u8 *) parg; ++ ++ if (nss->running) ++ ret = -EBUSY; ++ else if (ns->set_ci) ++ ret = ns->set_ci(nss, ci); ++ break; ++ } ++ ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++static long ns_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return dvb_usercopy(file, cmd, arg, do_ioctl); ++} ++ ++static const struct file_operations ns_fops = { ++ .owner = THIS_MODULE, ++ .read = ns_read, ++ .write = ns_write, ++ .open = ns_open, ++ .release = ns_release, ++ .poll = ns_poll, ++ .mmap = 0, ++ .unlocked_ioctl = ns_ioctl, ++}; ++ ++static struct dvb_device ns_dev = { ++ .priv = 0, ++ .readers = 1, ++ .writers = 1, ++ .users = 1, ++ .fops = &ns_fops, ++}; ++ ++ ++int dvb_netstream_init(struct dvb_adapter *dvb_adapter, struct dvb_netstream *ns) ++{ ++ mutex_init(&ns->mutex); ++ spin_lock_init(&ns->lock); ++ ns->exit = 0; ++ dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns, ++ DVB_DEVICE_NS); ++ INIT_LIST_HEAD(&ns->nssl); ++ return 0; ++} ++ ++EXPORT_SYMBOL(dvb_netstream_init); ++ ++void dvb_netstream_release(struct dvb_netstream *ns) ++{ ++ ns->exit=1; ++ if (ns->dvbdev->users > 1) { ++ wait_event(ns->dvbdev->wait_queue, ++ ns->dvbdev->users == 1); ++ } ++ dvb_unregister_device(ns->dvbdev); ++} ++ ++EXPORT_SYMBOL(dvb_netstream_release); +diff --git a/drivers/media/dvb-core/dvb_netstream.h b/drivers/media/dvb-core/dvb_netstream.h +new file mode 100644 +index 0000000..df73ed5 +--- /dev/null ++++ b/drivers/media/dvb-core/dvb_netstream.h +@@ -0,0 +1,94 @@ ++/* ++ * dvb_netstream.c: support for DVB to network streaming hardware ++ * ++ * Copyright (C) 2012-2013 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef _DVB_NETSTREAM_H_ ++#define _DVB_NETSTREAM_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvbdev.h" ++ ++#define DVBNS_MAXPIDS 32 ++ ++struct dvbnss { ++ struct dvb_netstream *ns; ++ void *priv; ++ ++ u8 pids[1024]; ++ u8 packet[1328]; ++ u32 pp; ++ ++ struct socket *sock; ++ struct sockaddr_in sadr; ++ u32 sn; ++ ++ struct dvb_ns_params params; ++ ++ struct list_head nssl; ++ int running; ++}; ++ ++#define MAX_DVBNSS 32 ++ ++struct dvb_netstream { ++ void *priv; ++ ++ struct mutex mutex; ++ spinlock_t lock; ++ struct dvb_device *dvbdev; ++ int exit; ++ ++ struct list_head nssl; ++ ++ int (*set_net) (struct dvbnss *); ++ int (*set_pid) (struct dvbnss *, u16); ++ int (*set_pids) (struct dvbnss *); ++ int (*set_ci) (struct dvbnss *, u8); ++ int (*set_rtcp_msg) (struct dvbnss *, u8 *, u32); ++ int (*set_ts_packets) (struct dvbnss *, u8 *, u32); ++ int (*insert_ts_packets) (struct dvbnss *, u8); ++ int (*start) (struct dvbnss *); ++ int (*stop) (struct dvbnss *); ++ int (*alloc) (struct dvbnss *); ++ void (*free) (struct dvbnss *); ++ ++}; ++ ++ ++void dvb_netstream_release(struct dvb_netstream *); ++int dvb_netstream_init(struct dvb_adapter *, struct dvb_netstream *); ++ ++ ++#endif +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index 13bb57f..ef320af 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -47,7 +47,7 @@ static DEFINE_MUTEX(dvbdev_register_lock); + + static const char * const dnames[] = { + "video", "audio", "sec", "frontend", "demux", "dvr", "ca", +- "net", "osd" ++ "net", "osd", "ci", "mod", "ns", "nsd" + }; + + #ifdef CONFIG_DVB_DYNAMIC_MINORS +@@ -68,7 +68,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) + { + struct dvb_device *dvbdev; + +- mutex_lock(&dvbdev_mutex); ++ //mutex_lock(&dvbdev_mutex); + down_read(&minor_rwsem); + dvbdev = dvb_minors[iminor(inode)]; + +@@ -84,12 +84,12 @@ static int dvb_device_open(struct inode *inode, struct file *file) + if (file->f_op->open) + err = file->f_op->open(inode,file); + up_read(&minor_rwsem); +- mutex_unlock(&dvbdev_mutex); ++ //mutex_unlock(&dvbdev_mutex); + return err; + } + fail: + up_read(&minor_rwsem); +- mutex_unlock(&dvbdev_mutex); ++ //mutex_unlock(&dvbdev_mutex); + return -ENODEV; + } + +@@ -553,8 +553,10 @@ int dvb_usercopy(struct file *file, + } + + /* call driver */ ++ //mutex_lock(&dvbdev_mutex); + if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = -ENOTTY; ++ //mutex_unlock(&dvbdev_mutex); + + if (err < 0) + goto out; +@@ -573,6 +575,7 @@ out: + kfree(mbuf); + return err; + } ++EXPORT_SYMBOL(dvb_usercopy); + + static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) + { +diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h +index 12629b8..e918a09 100644 +--- a/drivers/media/dvb-core/dvbdev.h ++++ b/drivers/media/dvb-core/dvbdev.h +@@ -48,6 +48,10 @@ + #define DVB_DEVICE_CA 6 + #define DVB_DEVICE_NET 7 + #define DVB_DEVICE_OSD 8 ++#define DVB_DEVICE_CI 9 ++#define DVB_DEVICE_MOD 10 ++#define DVB_DEVICE_NS 11 ++#define DVB_DEVICE_NSD 12 + + #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ + static short adapter_nr[] = \ +diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +index 97c151d..2bf9390 100644 +--- a/drivers/media/dvb-frontends/Kconfig ++++ b/drivers/media/dvb-frontends/Kconfig +@@ -72,6 +72,33 @@ config DVB_SI2165 + + Say Y when you want to support this frontend. + ++config DVB_STV0367DD ++ tristate "STV 0367 (DD)" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ STV 0367 DVB-C/T demodulator (Digital Devices driver). ++ ++ Say Y when you want to support this frontend. ++ ++config DVB_TDA18212DD ++ tristate "NXP TDA18212 silicon tuner (DD)" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ NXP TDA18212 silicon tuner (Digital Devices driver). ++ ++ Say Y when you want to support this tuner. ++ ++config DVB_CXD2843 ++ tristate "Sony CXD2843 DVB-C/T demodulator family" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ Sony CXD2843 demodulator (Digital Devices driver). ++ ++ Say Y when you want to support this frontend. ++ + comment "DVB-S (satellite) frontends" + depends on DVB_CORE + +diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +index 23d399b..db9b87a 100644 +--- a/drivers/media/dvb-frontends/Makefile ++++ b/drivers/media/dvb-frontends/Makefile +@@ -106,6 +106,9 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o + obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o + obj-$(CONFIG_DVB_DRXK) += drxk.o + obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o ++obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o ++obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o ++obj-$(CONFIG_DVB_CXD2843) += cxd2843.o + obj-$(CONFIG_DVB_SI2165) += si2165.o + obj-$(CONFIG_DVB_A8293) += a8293.o + obj-$(CONFIG_DVB_SP2) += sp2.o +diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c +new file mode 100644 +index 0000000..27e5eac +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2843.c +@@ -0,0 +1,2022 @@ ++/* ++ * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator. ++ * Also supports the CXD2837ER DVB-T/T2/C and the ++ * CXD2838ER ISDB-T demodulator. ++ * ++ * Copyright (C) 2013-2014 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "cxd2843.h" ++ ++#define USE_ALGO 1 ++ ++enum EDemodType { CXD2843, CXD2837, CXD2838 }; ++enum EDemodState { Unknown, Shutdown, Sleep, ActiveT, ++ ActiveT2, ActiveC, ActiveC2, ActiveIT }; ++enum ET2Profile { T2P_Base, T2P_Lite }; ++enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC, ++ OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT }; ++ ++struct cxd_state { ++ struct dvb_frontend frontend; ++ struct i2c_adapter *i2c; ++ struct mutex mutex; ++ ++ u8 adrt; ++ u8 curbankt; ++ ++ u8 adrx; ++ u8 curbankx; ++ ++ enum EDemodType type; ++ enum EDemodState state; ++ enum ET2Profile T2Profile; ++ enum omode omode; ++ ++ u8 IF_FS; ++ int ContinuousClock; ++ int SerialMode; ++ u8 SerialClockFrequency; ++ ++ u32 LockTimeout; ++ u32 TSLockTimeout; ++ u32 L1PostTimeout; ++ u32 DataSliceID; ++ int FirstTimeLock; ++ u32 plp; ++ u32 last_status; ++ ++ u32 bandwidth; ++ u32 bw; ++ ++ unsigned long tune_time; ++ ++ u32 LastBERNominator; ++ u32 LastBERDenominator; ++ u8 BERScaleMax; ++}; ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = { ++ .addr = adr, .flags = 0, .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ pr_err("cxd2843: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int writeregs(struct cxd_state *state, u8 adr, u8 reg, ++ u8 *regd, u16 len) ++{ ++ u8 data[len + 1]; ++ ++ data[0] = reg; ++ memcpy(data + 1, regd, len); ++ return i2c_write(state->i2c, adr, data, len + 1); ++} ++ ++static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) ++{ ++ u8 mm[2] = {reg, dat}; ++ ++ return i2c_write(state->i2c, adr, mm, 2); ++} ++ ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ pr_err("cxd2843: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int readregs(struct cxd_state *state, u8 adr, u8 reg, ++ u8 *val, int count) ++{ ++ return i2c_read(state->i2c, adr, ®, 1, val, count); ++} ++ ++static int readregst_unlocked(struct cxd_state *cxd, u8 bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status = 0; ++ ++ if (bank != 0xFF && cxd->curbankt != bank) { ++ status = writereg(cxd, cxd->adrt, 0, bank); ++ if (status < 0) { ++ cxd->curbankt = 0xFF; ++ return status; ++ } ++ cxd->curbankt = bank; ++ } ++ status = readregs(cxd, cxd->adrt, Address, pValue, count); ++ return status; ++} ++ ++static int readregst(struct cxd_state *cxd, u8 Bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status; ++ ++ mutex_lock(&cxd->mutex); ++ status = readregst_unlocked(cxd, Bank, Address, pValue, count); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status = 0; ++ ++ if (Bank != 0xFF && cxd->curbankx != Bank) { ++ status = writereg(cxd, cxd->adrx, 0, Bank); ++ if (status < 0) { ++ cxd->curbankx = 0xFF; ++ return status; ++ } ++ cxd->curbankx = Bank; ++ } ++ status = readregs(cxd, cxd->adrx, Address, pValue, count); ++ return status; ++} ++ ++static int readregsx(struct cxd_state *cxd, u8 Bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status; ++ ++ mutex_lock(&cxd->mutex); ++ status = readregsx_unlocked(cxd, Bank, Address, pValue, count); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status = 0; ++ ++ if (Bank != 0xFF && cxd->curbankx != Bank) { ++ status = writereg(cxd, cxd->adrx, 0, Bank); ++ if (status < 0) { ++ cxd->curbankx = 0xFF; ++ return status; ++ } ++ cxd->curbankx = Bank; ++ } ++ status = writeregs(cxd, cxd->adrx, Address, pValue, count); ++ return status; ++} ++ ++static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address, ++ u8 *pValue, u16 count) ++{ ++ int status; ++ ++ mutex_lock(&cxd->mutex); ++ status = writeregsx_unlocked(cxd, Bank, Address, pValue, count); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) ++{ ++ return writeregsx(cxd, Bank, Address, &val, 1); ++} ++ ++static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank, ++ u8 Address, u8 *pValue, u16 count) ++{ ++ int status = 0; ++ ++ if (Bank != 0xFF && cxd->curbankt != Bank) { ++ status = writereg(cxd, cxd->adrt, 0, Bank); ++ if (status < 0) { ++ cxd->curbankt = 0xFF; ++ return status; ++ } ++ cxd->curbankt = Bank; ++ } ++ status = writeregs(cxd, cxd->adrt, Address, pValue, count); ++ return status; ++} ++ ++static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address, ++ u8 *pValue, u16 count) ++{ ++ int status; ++ ++ mutex_lock(&cxd->mutex); ++ status = writeregst_unlocked(cxd, Bank, Address, pValue, count); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) ++{ ++ return writeregst(cxd, Bank, Address, &val, 1); ++} ++ ++static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address, ++ u8 Value, u8 Mask) ++{ ++ int status = 0; ++ u8 tmp; ++ ++ mutex_lock(&cxd->mutex); ++ status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1); ++ if (status < 0) ++ return status; ++ tmp = (tmp & ~Mask) | Value; ++ status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address, ++ u8 Value, u8 Mask) ++{ ++ int status = 0; ++ u8 Tmp = 0x00; ++ ++ mutex_lock(&cxd->mutex); ++ status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1); ++ if (status < 0) ++ return status; ++ Tmp = (Tmp & ~Mask) | Value; ++ status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static int freeze_regst(struct cxd_state *cxd) ++{ ++ mutex_lock(&cxd->mutex); ++ return writereg(cxd, cxd->adrt, 1, 1); ++} ++ ++static int unfreeze_regst(struct cxd_state *cxd) ++{ ++ int status = 0; ++ ++ status = writereg(cxd, cxd->adrt, 1, 0); ++ mutex_unlock(&cxd->mutex); ++ return status; ++} ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++/* TPSData[0] [7:6] CNST[1:0] */ ++/* TPSData[0] [5:3] HIER[2:0] */ ++/* TPSData[0] [2:0] HRATE[2:0] */ ++/* TPSData[1] [7:5] LRATE[2:0] */ ++/* TPSData[1] [4:3] GI[1:0] */ ++/* TPSData[1] [2:1] MODE[1:0] */ ++/* TPSData[2] [7:6] FNUM[1:0] */ ++/* TPSData[2] [5:0] LENGTH_INDICATOR[5:0] */ ++/* TPSData[3] [7:0] CELLID[15:8] */ ++/* TPSData[4] [7:0] CELLID[7:0] */ ++/* TPSData[5] [5:0] RESERVE_EVEN[5:0] */ ++/* TPSData[6] [5:0] RESERVE_ODD[5:0] */ ++ ++static int read_tps(struct cxd_state *state, u8 *tps) ++{ ++ if (state->last_status != 0x1f) ++ return 0; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x10, 0x2f, tps, 7); ++ unfreeze_regst(state); ++ return 0; ++} ++ ++static void Active_to_Sleep(struct cxd_state *state) ++{ ++ if (state->state <= Sleep) ++ return; ++ ++ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ ++ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ ++ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ ++ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ ++ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ ++ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ ++ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ ++ state->state = Sleep; ++} ++ ++static void ActiveT2_to_Sleep(struct cxd_state *state) ++{ ++ if (state->state <= Sleep) ++ return; ++ ++ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ ++ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ ++ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ ++ ++ writeregt(state, 0x13, 0x83, 0x40); ++ writeregt(state, 0x13, 0x86, 0x21); ++ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); ++ writeregt(state, 0x13, 0x9F, 0xFB); ++ ++ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ ++ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ ++ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ ++ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ ++ state->state = Sleep; ++} ++ ++static void ActiveC2_to_Sleep(struct cxd_state *state) ++{ ++ if (state->state <= Sleep) ++ return; ++ ++ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ ++ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ ++ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ ++ ++ writeregt(state, 0x20, 0xC2, 0x11); ++ writebitst(state, 0x25, 0x6A, 0x02, 0x03); ++ { ++ static u8 data[3] = { 0x07, 0x61, 0x36 }; ++ writeregst(state, 0x25, 0x89, data, sizeof(data)); ++ } ++ writebitst(state, 0x25, 0xCB, 0x05, 0x07); ++ { ++ static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 }; ++ writeregst(state, 0x25, 0xDC, data, sizeof(data)); ++ } ++ writeregt(state, 0x25, 0xE2, 0x2F); ++ writeregt(state, 0x25, 0xE5, 0x2F); ++ writebitst(state, 0x27, 0x20, 0x00, 0x01); ++ writebitst(state, 0x27, 0x35, 0x00, 0x01); ++ writebitst(state, 0x27, 0xD9, 0x19, 0x3F); ++ writebitst(state, 0x2A, 0x78, 0x01, 0x07); ++ writeregt(state, 0x2A, 0x86, 0x08); ++ writeregt(state, 0x2A, 0x88, 0x14); ++ writebitst(state, 0x2B, 0x2B, 0x00, 0x1F); ++ { ++ u8 data[2] = { 0x75, 0x75 }; ++ writeregst(state, 0x2D, 0x24, data, sizeof(data)); ++ } ++ ++ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ ++ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ ++ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ ++ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ ++ state->state = Sleep; ++} ++ ++static int ConfigureTS(struct cxd_state *state, ++ enum EDemodState newDemodState) ++{ ++ int status = 0; ++ u8 OSERCKMODE = state->SerialMode ? 1 : 0; ++ u8 OSERDUTYMODE = state->SerialMode ? 1 : 0; ++ u8 OTSCKPERIOD = 8; ++ u8 OREG_CKSEL_TSIF = state->SerialMode ? ++ state->SerialClockFrequency : 0; ++ ++ if (state->SerialMode && state->SerialClockFrequency >= 3) { ++ OSERCKMODE = 2; ++ OSERDUTYMODE = 2; ++ OTSCKPERIOD = 16; ++ OREG_CKSEL_TSIF = state->SerialClockFrequency - 3; ++ } ++ writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */ ++ writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */ ++ writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */ ++ writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */ ++ /* OREG_CKSEL_TSIF */ ++ writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); ++ writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */ ++ ++ if (newDemodState == ActiveT) ++ writebitst(state, 0x10, 0x66, 0x01, 0x01); ++ if (newDemodState == ActiveC) ++ writebitst(state, 0x40, 0x66, 0x01, 0x01); ++ ++ return status; ++} ++ ++static void BandSettingT(struct cxd_state *state, u32 iffreq) ++{ ++ u8 IF_data[3] = { (iffreq >> 16) & 0xff, ++ (iffreq >> 8) & 0xff, iffreq & 0xff}; ++ ++ switch (state->bw) { ++ default: ++ case 8: ++ { ++ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; ++ u8 CL_data[] = { 0x01, 0xE0 }; ++ u8 NF_data[] = { 0x01, 0x02 }; ++ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x00, 0x07); ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); ++ break; ++ } ++ case 7: ++ { ++ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; ++ u8 CL_data[] = { 0x12, 0xF8 }; ++ u8 NF_data[] = { 0x00, 0x03 }; ++ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x02, 0x07); ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); ++ break; ++ } ++ case 6: ++ { ++ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; ++ u8 CL_data[] = { 0x1F, 0xDC }; ++ u8 NF_data[] = { 0x00, 0x03 }; ++ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x04, 0x07); ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); ++ break; ++ } ++ case 5: ++ { ++ static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; ++ static u8 CL_data[] = { 0x26, 0x3C }; ++ static u8 NF_data[] = { 0x00, 0x03 }; ++ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x06, 0x07); ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); ++ break; ++ } ++ } ++} ++ ++static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq) ++{ ++ ConfigureTS(state, ActiveT); ++ writeregx(state, 0x00, 0x17, 0x01); /* Mode */ ++ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ ++ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ ++ { ++ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ ++ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ ++ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ ++ } ++ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ ++ ++ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */ ++ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ ++ ++ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ ++ ++ writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */ ++ writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */ ++ writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */ ++ ++ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ ++ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ ++ ++ BandSettingT(state, iffreq); ++ ++ writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */ ++ ++ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ ++ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ ++} ++ ++static void BandSettingT2(struct cxd_state *state, u32 iffreq) ++{ ++ u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, ++ iffreq & 0xff}; ++ ++ switch (state->bw) { ++ default: ++ case 8: ++ { ++ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; ++ /* Timing recovery */ ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ /* Add EQ Optimisation for tuner here */ ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ /* System Bandwidth */ ++ writebitst(state, 0x10, 0xD7, 0x00, 0x07); ++ } ++ break; ++ case 7: ++ { ++ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x02, 0x07); ++ } ++ break; ++ case 6: ++ { ++ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x04, 0x07); ++ } ++ break; ++ case 5: ++ { ++ u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x06, 0x07); ++ } ++ break; ++ case 2: /* 1.7 MHz */ ++ { ++ u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC }; ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x03, 0x07); ++ } ++ break; ++ } ++} ++ ++ ++static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq) ++{ ++ ConfigureTS(state, ActiveT2); ++ ++ writeregx(state, 0x00, 0x17, 0x02); /* Mode */ ++ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ ++ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ ++ ++ { ++ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ ++ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ ++ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ ++ } ++ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ ++ ++ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ ++ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ ++ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ ++ ++ writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */ ++ writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */ ++ ++ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ ++ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ ++ ++ writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */ ++ writeregt(state, 0x13, 0x86, 0x34); ++ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); ++ writeregt(state, 0x13, 0x9F, 0xD8); ++ ++ BandSettingT2(state, iffreq); ++ ++ writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */ ++ ++ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ ++ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ ++} ++ ++ ++static void BandSettingC(struct cxd_state *state, u32 iffreq) ++{ ++ u8 data[3]; ++ ++ data[0] = (iffreq >> 16) & 0xFF; ++ data[1] = (iffreq >> 8) & 0xFF; ++ data[2] = (iffreq) & 0xFF; ++ writeregst(state, 0x10, 0xB6, data, 3); ++} ++ ++static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq) ++{ ++ ConfigureTS(state, ActiveC); ++ ++ writeregx(state, 0x00, 0x17, 0x04); /* Mode */ ++ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ ++ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ ++ ++ { ++ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ ++ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ ++ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ ++ } ++ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ ++ ++ writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */ ++ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ ++ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ ++ ++ writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */ ++ ++ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ ++ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ ++ ++ BandSettingC(state, iffreq); ++ ++ writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */ ++ ++ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ ++ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ ++} ++ ++static void BandSettingC2(struct cxd_state *state, u32 iffreq) ++{ ++ u8 IF_data[3] = { (iffreq >> 16) & 0xff, ++ (iffreq >> 8) & 0xff, iffreq & 0xff}; ++ ++ switch (state->bw) { ++ default: ++ case 8: ++ { ++ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; ++ u8 data[2] = { 0x11, 0x9E }; ++ ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x00, 0x07); ++ writeregst(state, 0x50, 0xEC, data, sizeof(data)); ++ writeregt(state, 0x50, 0xEF, 0x11); ++ writeregt(state, 0x50, 0xF1, 0x9E); ++ } ++ break; ++ case 6: ++ { ++ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; ++ u8 data[2] = { 0x17, 0x70 }; ++ ++ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writebitst(state, 0x10, 0xD7, 0x04, 0x07); ++ writeregst(state, 0x50, 0xEC, data, sizeof(data)); ++ writeregt(state, 0x50, 0xEF, 0x17); ++ writeregt(state, 0x50, 0xF1, 0x70); ++ } ++ break; ++ } ++} ++ ++static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq) ++{ ++ ConfigureTS(state, ActiveC2); ++ ++ writeregx(state, 0x00, 0x17, 0x05); /* Mode */ ++ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ ++ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ ++ ++ { ++ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ ++ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ ++ writeregst(state, 0x00, 0x43, data, sizeof(data)); ++ /* Enable ADC 2+3 */ ++ } ++ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ ++ ++ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ ++ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ ++ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ ++ ++ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ ++ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ ++ ++ writeregt(state, 0x20, 0xC2, 0x00); ++ writebitst(state, 0x25, 0x6A, 0x00, 0x03); ++ { ++ u8 data[3] = { 0x0C, 0xD1, 0x40 }; ++ writeregst(state, 0x25, 0x89, data, sizeof(data)); ++ } ++ writebitst(state, 0x25, 0xCB, 0x01, 0x07); ++ { ++ u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 }; ++ writeregst(state, 0x25, 0xDC, data, sizeof(data)); ++ } ++ writeregt(state, 0x25, 0xE2, 0x30); ++ writeregt(state, 0x25, 0xE5, 0x30); ++ writebitst(state, 0x27, 0x20, 0x01, 0x01); ++ writebitst(state, 0x27, 0x35, 0x01, 0x01); ++ writebitst(state, 0x27, 0xD9, 0x18, 0x3F); ++ writebitst(state, 0x2A, 0x78, 0x00, 0x07); ++ writeregt(state, 0x2A, 0x86, 0x20); ++ writeregt(state, 0x2A, 0x88, 0x32); ++ writebitst(state, 0x2B, 0x2B, 0x10, 0x1F); ++ { ++ u8 data[2] = { 0x01, 0x01 }; ++ writeregst(state, 0x2D, 0x24, data, sizeof(data)); ++ } ++ ++ BandSettingC2(state, iffreq); ++ ++ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ ++ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ ++} ++ ++ ++static void BandSettingIT(struct cxd_state *state, u32 iffreq) ++{ ++ u8 IF_data[3] = { (iffreq >> 16) & 0xff, ++ (iffreq >> 8) & 0xff, iffreq & 0xff}; ++ ++ switch (state->bw) { ++ default: ++ case 8: ++ { ++ u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */ ++ u8 CL_data[] = { 0x15, 0xA8 }; ++ ++ /*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ /* Add EQ Optimisation for tuner here */ ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ ++ writeregt(state, 0x10, 0xD7, 0x00); /* System Bandwidth */ ++ /*u8 CL_data[] = { 0x13, 0xFC }; */ ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ } ++ break; ++ case 7: ++ { ++ u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 }; ++ u8 CL_data[] = { 0x1B, 0x5D }; ++ ++ /*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ ++ writeregt(state, 0x10, 0xD7, 0x02); ++ /*static u8 CL_data[] = { 0x1A, 0xFA };*/ ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ } ++ break; ++ case 6: ++ { ++ u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 }; ++ u8 CL_data[] = { 0x1F, 0xEC }; ++ /*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */ ++ /*u8 CL_data[] = { 0x1F, 0x79 }; */ ++ ++ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); ++ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); ++ writeregt(state, 0x10, 0xD7, 0x04); ++ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); ++ } ++ break; ++ } ++} ++ ++static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq) ++{ ++ u8 data2[3] = { 0xB9, 0xBA, 0x63 }; /* 20.5/41 MHz */ ++ /*u8 data2[3] = { 0xB7,0x1B,0x00 }; */ /* 24 MHz */ ++ u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */ ++ /*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */ ++ ++ pr_info("%s\n", __func__); ++ ++ ConfigureTS(state, ActiveIT); ++ ++ /* writeregx(state, 0x00,0x17,0x01); */ /* 2838 has only one Mode */ ++ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ ++ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ ++ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ ++ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ ++ ++ { ++ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz, 24 MHz */ ++ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ ++ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ ++ } ++ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ ++ ++ writeregst(state, 0x60, 0xA8, data2, sizeof(data2)); ++ ++ writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); ++ ++ writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */ ++ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ ++ ++ BandSettingIT(state, iffreq); ++ ++ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ ++ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ ++} ++ ++static void T2_SetParameters(struct cxd_state *state) ++{ ++ u8 Profile = 0x01; /* Profile Base */ ++ u8 notT2time = 12; /* early unlock detection time */ ++ ++ if (state->T2Profile == T2P_Lite) { ++ Profile = 0x05; ++ notT2time = 40; ++ } ++ ++ if (state->plp != 0xffffffff) { ++ state->T2Profile = ((state->plp & 0x100) != 0) ? ++ T2P_Lite : T2P_Base; ++ writeregt(state, 0x23, 0xAF, state->plp); ++ writeregt(state, 0x23, 0xAD, 0x01); ++ } else { ++ state->T2Profile = T2P_Base; ++ writeregt(state, 0x23, 0xAD, 0x00); ++ } ++ ++ writebitst(state, 0x2E, 0x10, Profile, 0x07); ++ writeregt(state, 0x2B, 0x19, notT2time); ++} ++ ++static void C2_ReleasePreset(struct cxd_state *state) ++{ ++ { ++ static u8 data[2] = { 0x02, 0x80}; ++ writeregst(state, 0x27, 0xF4, data, sizeof(data)); ++ } ++ writebitst(state, 0x27, 0x51, 0x40, 0xF0); ++ writebitst(state, 0x27, 0x73, 0x07, 0x0F); ++ writebitst(state, 0x27, 0x74, 0x19, 0x3F); ++ writebitst(state, 0x27, 0x75, 0x19, 0x3F); ++ writebitst(state, 0x27, 0x76, 0x19, 0x3F); ++ if (state->bw == 6) { ++ static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA}; ++ writeregst(state, 0x20, 0x9F, data, sizeof(data)); ++ } else { ++ static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00}; ++ writeregst(state, 0x20, 0x9F, data, sizeof(data)); ++ } ++ writebitst(state, 0x27, 0xC9, 0x07, 0x07); ++ writebitst(state, 0x20, 0xC2, 0x11, 0x33); ++ { ++ static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8, ++ 0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 }; ++ writeregst(state, 0x2A, 0x20, data, sizeof(data)); ++ } ++ { ++ static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 }; ++ writeregst(state, 0x50, 0x6B, data, sizeof(data)); ++ } ++ writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */ ++} ++ ++static void C2_DemodSetting2(struct cxd_state *state) ++{ ++ u8 data[6]; ++ u32 TunePosition = ++ state->frontend.dtv_property_cache.frequency / 1000; ++ ++ if (state->bw == 6) ++ TunePosition = ((TunePosition * 1792) / 3) / 1000; ++ else ++ TunePosition = (TunePosition * 448) / 1000; ++ ++ TunePosition = ((TunePosition + 6) / 12) * 12; ++ ++ pr_info("TunePosition = %u\n", TunePosition); ++ ++ data[0] = ((TunePosition >> 16) & 0xFF); ++ data[1] = ((TunePosition >> 8) & 0xFF); ++ data[2] = (TunePosition & 0xFF); ++ data[3] = 0x02; ++ data[4] = (state->DataSliceID & 0xFF); ++ data[5] = (state->plp & 0xFF); ++ writeregst(state, 0x50, 0x7A, data, sizeof(data)); ++ writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */ ++} ++ ++static void Stop(struct cxd_state *state) ++{ ++ ++ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ ++} ++ ++static void ShutDown(struct cxd_state *state) ++{ ++ switch (state->state) { ++ case ActiveT2: ++ ActiveT2_to_Sleep(state); ++ break; ++ case ActiveC2: ++ ActiveC2_to_Sleep(state); ++ break; ++ default: ++ Active_to_Sleep(state); ++ break; ++ } ++} ++ ++static int gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ ++ return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01); ++} ++ ++static void release(struct dvb_frontend *fe) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ ++ Stop(state); ++ ShutDown(state); ++ kfree(state); ++} ++ ++static int Start(struct cxd_state *state, u32 IntermediateFrequency) ++{ ++ enum EDemodState newDemodState = Unknown; ++ u32 iffreq; ++ ++ if (state->state < Sleep) ++ return -EINVAL; ++ ++ iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000); ++ ++ switch (state->omode) { ++ case OM_DVBT: ++ if (state->type == CXD2838) ++ return -EINVAL; ++ newDemodState = ActiveT; ++ break; ++ case OM_DVBT2: ++ if (state->type == CXD2838) ++ return -EINVAL; ++ newDemodState = ActiveT2; ++ break; ++ case OM_DVBC: ++ case OM_QAM_ITU_C: ++ if (state->type == CXD2838) ++ return -EINVAL; ++ newDemodState = ActiveC; ++ break; ++ case OM_DVBC2: ++ if (state->type != CXD2843) ++ return -EINVAL; ++ newDemodState = ActiveC2; ++ break; ++ case OM_ISDBT: ++ if (state->type != CXD2838) ++ return -EINVAL; ++ newDemodState = ActiveIT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ state->LockTimeout = 0; ++ state->TSLockTimeout = 0; ++ state->L1PostTimeout = 0; ++ state->last_status = 0; ++ state->FirstTimeLock = 1; ++ state->LastBERNominator = 0; ++ state->LastBERDenominator = 1; ++ state->BERScaleMax = 19; ++ ++ if (state->state == newDemodState) { ++ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS Output */ ++ switch (newDemodState) { ++ case ActiveT: ++ /* Stick with HP ( 0x01 = LP ) */ ++ writeregt(state, 0x10, 0x67, 0x00); ++ BandSettingT(state, iffreq); ++ state->BERScaleMax = 18; ++ break; ++ case ActiveT2: ++ T2_SetParameters(state); ++ BandSettingT2(state, iffreq); ++ state->BERScaleMax = 12; ++ break; ++ case ActiveC: ++ BandSettingC(state, iffreq); ++ state->BERScaleMax = 19; ++ break; ++ case ActiveC2: ++ BandSettingC2(state, iffreq); ++ C2_ReleasePreset(state); ++ C2_DemodSetting2(state); ++ break; ++ case ActiveIT: ++ BandSettingIT(state, iffreq); ++ break; ++ default: ++ break; ++ } ++ } else { ++ if (state->state > Sleep) { ++ switch (state->state) { ++ case ActiveT2: ++ ActiveT2_to_Sleep(state); ++ break; ++ case ActiveC2: ++ ActiveC2_to_Sleep(state); ++ break; ++ default: ++ Active_to_Sleep(state); ++ break; ++ } ++ } ++ switch (newDemodState) { ++ case ActiveT: ++ /* Stick with HP ( 0x01 = LP ) */ ++ writeregt(state, 0x10, 0x67, 0x00); ++ Sleep_to_ActiveT(state, iffreq); ++ state->BERScaleMax = 18; ++ break; ++ case ActiveT2: ++ T2_SetParameters(state); ++ Sleep_to_ActiveT2(state, iffreq); ++ state->BERScaleMax = 12; ++ break; ++ case ActiveC: ++ Sleep_to_ActiveC(state, iffreq); ++ state->BERScaleMax = 19; ++ break; ++ case ActiveC2: ++ Sleep_to_ActiveC2(state, iffreq); ++ C2_ReleasePreset(state); ++ C2_DemodSetting2(state); ++ break; ++ case ActiveIT: ++ Sleep_to_ActiveIT(state, iffreq); ++ break; ++ default: ++ break; ++ } ++ } ++ state->state = newDemodState; ++ writeregt(state, 0x00, 0xFE, 0x01); /* SW Reset */ ++ writeregt(state, 0x00, 0xC3, 0x00); /* Enable TS Output */ ++ ++ return 0; ++} ++ ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ int stat; ++ struct cxd_state *state = fe->demodulator_priv; ++ u32 IF; ++ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ state->omode = OM_DVBC; ++ break; ++ case SYS_DVBT: ++ state->omode = OM_DVBT; ++ break; ++ case SYS_DVBT2: ++ state->omode = OM_DVBT2; ++ break; ++ case SYS_ISDBT: ++ state->omode = OM_ISDBT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; ++ state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000; ++ if (fe->dtv_property_cache.stream_id == 0xffffffff) { ++ state->DataSliceID = 0xffffffff; ++ state->plp = 0xffffffff; ++ } else { ++ state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8) ++ & 0xff; ++ state->plp = fe->dtv_property_cache.stream_id & 0xff; ++ } ++ /* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */ ++ fe->ops.tuner_ops.get_if_frequency(fe, &IF); ++ stat = Start(state, IF); ++ return stat; ++} ++ ++ ++static void init(struct cxd_state *state) ++{ ++ u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */ ++ ++ state->omode = OM_NONE; ++ state->state = Unknown; ++ ++ writeregx(state, 0xFF, 0x02, 0x00); ++ usleep_range(4000, 5000); ++ writeregx(state, 0x00, 0x15, 0x01); ++ if (state->type != CXD2838) ++ writeregx(state, 0x00, 0x17, 0x01); ++ usleep_range(4000, 5000); ++ ++ writeregx(state, 0x00, 0x10, 0x01); ++ ++ writeregsx(state, 0x00, 0x13, data, 2); ++ writeregx(state, 0x00, 0x15, 0x00); ++ usleep_range(3000, 4000); ++ writeregx(state, 0x00, 0x10, 0x00); ++ usleep_range(2000, 3000); ++ ++ state->curbankx = 0xFF; ++ state->curbankt = 0xFF; ++ ++ writeregt(state, 0x00, 0x43, 0x0A); ++ writeregt(state, 0x00, 0x41, 0x0A); ++ if (state->type == CXD2838) ++ writeregt(state, 0x60, 0x5A, 0x00); ++ ++ writebitst(state, 0x10, 0xCB, 0x00, 0x40); ++ writeregt(state, 0x10, 0xCD, state->IF_FS); ++ ++ writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98); ++ writebitst(state, 0x00, 0xC5, 0x01, 0x07); ++ writebitst(state, 0x00, 0xCB, 0x00, 0x01); ++ writebitst(state, 0x00, 0xC6, 0x00, 0x1D); ++ writebitst(state, 0x00, 0xC8, 0x01, 0x1D); ++ writebitst(state, 0x00, 0xC9, 0x00, 0x1D); ++ writebitst(state, 0x00, 0x83, 0x00, 0x07); ++ writeregt(state, 0x00, 0x84, 0x00); ++ writebitst(state, 0x00, 0xD3, ++ (state->type == CXD2838) ? 0x01 : 0x00, 0x01); ++ writebitst(state, 0x00, 0xDE, 0x00, 0x01); ++ ++ state->state = Sleep; ++} ++ ++ ++static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) ++{ ++ state->adrt = cfg->adr; ++ state->adrx = cfg->adr + 0x02; ++ state->curbankt = 0xff; ++ state->curbankx = 0xff; ++ mutex_init(&state->mutex); ++ ++ state->SerialMode = cfg->parallel ? 0 : 1; ++ state->ContinuousClock = 1; ++ state->SerialClockFrequency = ++ (cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ? ++ cfg->ts_clock : 1; /* 1 = fastest (82 MBit/s), 5 = slowest */ ++ state->SerialClockFrequency = 1; ++ /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ ++ state->IF_FS = 0x50; ++} ++ ++static int get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *sets) ++{ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: ++ /*return c_get_tune_settings(fe, sets);*/ ++ default: ++ /* DVB-T: Use info.frequency_stepsize. */ ++ return -EINVAL; ++ } ++} ++ ++static int read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ u8 rdata; ++ ++ *status = 0; ++ switch (state->state) { ++ case ActiveC: ++ readregst(state, 0x40, 0x88, &rdata, 1); ++ if (rdata & 0x02) ++ break; ++ if (rdata & 0x01) { ++ *status |= 0x07; ++ readregst(state, 0x40, 0x10, &rdata, 1); ++ if (rdata & 0x20) ++ *status |= 0x1f; ++ } ++ break; ++ case ActiveT: ++ readregst(state, 0x10, 0x10, &rdata, 1); ++ if (rdata & 0x10) ++ break; ++ if ((rdata & 0x07) == 0x06) { ++ *status |= 0x07; ++ if (rdata & 0x20) ++ *status |= 0x1f; ++ } ++ break; ++ case ActiveT2: ++ readregst(state, 0x20, 0x10, &rdata, 1); ++ if (rdata & 0x10) ++ break; ++ if ((rdata & 0x07) == 0x06) { ++ *status |= 0x07; ++ if (rdata & 0x20) ++ *status |= 0x08; ++ } ++ if (*status & 0x08) { ++ readregst(state, 0x22, 0x12, &rdata, 1); ++ if (rdata & 0x01) ++ *status |= 0x10; ++ } ++ break; ++ case ActiveC2: ++ readregst(state, 0x20, 0x10, &rdata, 1); ++ if (rdata & 0x10) ++ break; ++ if ((rdata & 0x07) == 0x06) { ++ *status |= 0x07; ++ if (rdata & 0x20) ++ *status |= 0x18; ++ } ++ if ((*status & 0x10) && state->FirstTimeLock) { ++ u8 data; ++ ++ /* Change1stTrial */ ++ readregst(state, 0x28, 0xE6, &rdata, 1); ++ data = rdata & 1; ++ readregst(state, 0x50, 0x15, &rdata, 1); ++ data |= ((rdata & 0x18) >> 2); ++ /*writebitst(state, 0x50,0x6F,rdata,0x07);*/ ++ state->FirstTimeLock = 0; ++ } ++ break; ++ case ActiveIT: ++ readregst(state, 0x60, 0x10, &rdata, 1); ++ if (rdata & 0x10) ++ break; ++ if (rdata & 0x02) { ++ *status |= 0x07; ++ if (rdata & 0x01) ++ *status |= 0x18; ++ } ++ break; ++ default: ++ break; ++ } ++ state->last_status = *status; ++ return 0; ++} ++ ++static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) ++{ ++ u8 BERRegs[3]; ++ u8 Scale; ++ ++ *n = 0; ++ *d = 1; ++ ++ readregst(state, 0x10, 0x62, BERRegs, 3); ++ readregst(state, 0x10, 0x60, &Scale, 1); ++ Scale &= 0x1F; ++ ++ if (BERRegs[0] & 0x80) { ++ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | ++ (((u32) BERRegs[1]) << 8) | BERRegs[2]; ++ state->LastBERDenominator = 1632 << Scale; ++ if (state->LastBERNominator < 256 && ++ Scale < state->BERScaleMax) { ++ writebitst(state, 0x10, 0x60, Scale + 1, 0x1F); ++ } else if (state->LastBERNominator > 512 && Scale > 11) ++ writebitst(state, 0x10, 0x60, Scale - 1, 0x1F); ++ } ++ *n = state->LastBERNominator; ++ *d = state->LastBERDenominator; ++ ++ return 0; ++} ++ ++static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) ++{ ++ *n = 0; ++ *d = 1; ++ return 0; ++} ++ ++static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d) ++{ ++ u8 BERRegs[3]; ++ u8 Scale; ++ ++ *n = 0; ++ *d = 1; ++ ++ readregst(state, 0x40, 0x62, BERRegs, 3); ++ readregst(state, 0x40, 0x60, &Scale, 1); ++ Scale &= 0x1F; ++ ++ if (BERRegs[0] & 0x80) { ++ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | ++ (((u32) BERRegs[1]) << 8) | BERRegs[2]; ++ state->LastBERDenominator = 1632 << Scale; ++ if (state->LastBERNominator < 256 && ++ Scale < state->BERScaleMax) { ++ writebitst(state, 0x40, 0x60, Scale + 1, 0x1F); ++ } else if (state->LastBERNominator > 512 && Scale > 11) ++ writebitst(state, 0x40, 0x60, Scale - 1, 0x1F); ++ } ++ *n = state->LastBERNominator; ++ *d = state->LastBERDenominator; ++ ++ return 0; ++} ++ ++static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d) ++{ ++ *n = 0; ++ *d = 1; ++ return 0; ++} ++ ++static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) ++{ ++ *n = 0; ++ *d = 1; ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ u32 n, d; ++ int s = 0; ++ ++ *ber = 0; ++ switch (state->state) { ++ case ActiveT: ++ s = get_ber_t(state, &n, &d); ++ break; ++ case ActiveT2: ++ s = get_ber_t2(state, &n, &d); ++ break; ++ case ActiveC: ++ s = get_ber_c(state, &n, &d); ++ break; ++ case ActiveC2: ++ s = get_ber_c2(state, &n, &d); ++ break; ++ case ActiveIT: ++ s = get_ber_it(state, &n, &d); ++ break; ++ default: ++ break; ++ } ++ if (s) ++ return s; ++ ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ if (fe->ops.tuner_ops.get_rf_strength) ++ fe->ops.tuner_ops.get_rf_strength(fe, strength); ++ else ++ *strength = 0; ++ return 0; ++} ++ ++static s32 Log10x100(u32 x) ++{ ++ static u32 LookupTable[100] = { ++ 101157945, 103514217, 105925373, 108392691, 110917482, ++ 113501082, 116144861, 118850223, 121618600, 124451461, ++ 127350308, 130316678, 133352143, 136458314, 139636836, ++ 142889396, 146217717, 149623566, 153108746, 156675107, ++ 160324539, 164058977, 167880402, 171790839, 175792361, ++ 179887092, 184077200, 188364909, 192752491, 197242274, ++ 201836636, 206538016, 211348904, 216271852, 221309471, ++ 226464431, 231739465, 237137371, 242661010, 248313311, ++ 254097271, 260015956, 266072506, 272270131, 278612117, ++ 285101827, 291742701, 298538262, 305492111, 312607937, ++ 319889511, 327340695, 334965439, 342767787, 350751874, ++ 358921935, 367282300, 375837404, 384591782, 393550075, ++ 402717034, 412097519, 421696503, 431519077, 441570447, ++ 451855944, 462381021, 473151259, 484172368, 495450191, ++ 506990708, 518800039, 530884444, 543250331, 555904257, ++ 568852931, 582103218, 595662144, 609536897, 623734835, ++ 638263486, 653130553, 668343918, 683911647, 699841996, ++ 716143410, 732824533, 749894209, 767361489, 785235635, ++ 803526122, 822242650, 841395142, 860993752, 881048873, ++ 901571138, 922571427, 944060876, 966050879, 988553095, ++ }; ++ s32 y; ++ int i; ++ ++ if (x == 0) ++ return 0; ++ y = 800; ++ if (x >= 1000000000) { ++ x /= 10; ++ y += 100; ++ } ++ ++ while (x < 100000000) { ++ x *= 10; ++ y -= 100; ++ } ++ i = 0; ++ while (i < 100 && x > LookupTable[i]) ++ i += 1; ++ y += i; ++ return y; ++} ++ ++#if 0 ++static void GetPLPIds(struct cxd_state *state, u32 nValues, ++ u8 *Values, u32 *Returned) ++{ ++ u8 nPids = 0; ++ ++ *Returned = 0; ++ if (state->state != ActiveT2) ++ return; ++ if (state->last_status != 0x1f) ++ return; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x22, 0x7F, &nPids, 1); ++ ++ Values[0] = nPids; ++ if (nPids >= nValues) ++ nPids = nValues - 1; ++ ++ readregst_unlocked(state, 0x22, 0x80, &Values[1], ++ nPids > 128 ? 128 : nPids); ++ ++ if (nPids > 128) ++ readregst_unlocked(state, 0x23, 0x10, &Values[129], ++ nPids - 128); ++ ++ *Returned = nPids + 1; ++ ++ unfreeze_regst(state); ++} ++#endif ++ ++static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise) ++{ ++ u8 Data[2]; ++ u32 reg; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data)); ++ unfreeze_regst(state); ++ ++ reg = (Data[0] << 8) | Data[1]; ++ if (reg > 51441) ++ reg = 51441; ++ ++ if (state->bw == 8) { ++ if (reg > 1143) ++ reg = 1143; ++ *SignalToNoise = (Log10x100(reg) - ++ Log10x100(1200 - reg)) + 220; ++ } else ++ *SignalToNoise = Log10x100(reg) - 90; ++} ++ ++static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise) ++{ ++ u8 Data[2]; ++ u32 reg; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); ++ unfreeze_regst(state); ++ ++ reg = (Data[0] << 8) | Data[1]; ++ if (reg > 51441) ++ reg = 51441; ++ ++ *SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384; ++} ++ ++ ++static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise) ++{ ++ u8 Data[2]; ++ u32 reg; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); ++ unfreeze_regst(state); ++ ++ reg = (Data[0] << 8) | Data[1]; ++ if (reg > 10876) ++ reg = 10876; ++ ++ *SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320; ++} ++ ++static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise) ++{ ++ u8 Data[2]; ++ u32 reg; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data)); ++ unfreeze_regst(state); ++ ++ reg = (Data[0] << 8) | Data[1]; ++ if (reg > 4996) ++ reg = 4996; ++ ++ *SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285; ++} ++ ++static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise) ++{ ++ u8 Data[2]; ++ u8 Constellation = 0; ++ u32 reg; ++ ++ *SignalToNoise = 0; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x40, 0x19, &Constellation, 1); ++ readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data)); ++ unfreeze_regst(state); ++ ++ reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]); ++ if (reg == 0) ++ return; ++ ++ switch (Constellation & 0x07) { ++ case 0: /* QAM 16 */ ++ case 2: /* QAM 64 */ ++ case 4: /* QAM 256 */ ++ if (reg < 126) ++ reg = 126; ++ *SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000; ++ break; ++ case 1: /* QAM 32 */ ++ case 3: /* QAM 128 */ ++ if (reg < 69) ++ reg = 69; ++ *SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000; ++ break; ++ } ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ u32 SNR = 0; ++ ++ *snr = 0; ++ if (state->last_status != 0x1f) ++ return 0; ++ ++ switch (state->state) { ++ case ActiveC: ++ GetSignalToNoiseC(state, &SNR); ++ break; ++ case ActiveC2: ++ GetSignalToNoiseC2(state, &SNR); ++ break; ++ case ActiveT: ++ GetSignalToNoiseT(state, &SNR); ++ break; ++ case ActiveT2: ++ GetSignalToNoiseT2(state, &SNR); ++ break; ++ case ActiveIT: ++ GetSignalToNoiseIT(state, &SNR); ++ break; ++ default: ++ break; ++ } ++ *snr = SNR; ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, fe_status_t *status) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ int r; ++ ++ if (re_tune) { ++ r = set_parameters(fe); ++ if (r) ++ return r; ++ state->tune_time = jiffies; ++ ++ } ++ if (*status & FE_HAS_LOCK) ++ return 0; ++ /* *delay = 50; */ ++ r = read_status(fe, status); ++ if (r) ++ return r; ++ return 0; ++} ++ ++static enum dvbfe_search search(struct dvb_frontend *fe) ++{ ++ int r; ++ u32 loops = 20, i; ++ fe_status_t status; ++ ++ r = set_parameters(fe); ++ ++ for (i = 0; i < loops; i++) { ++ msleep(50); ++ r = read_status(fe, &status); ++ if (r) ++ return DVBFE_ALGO_SEARCH_ERROR; ++ if (status & FE_HAS_LOCK) ++ break; ++ } ++ ++ if (status & FE_HAS_LOCK) ++ return DVBFE_ALGO_SEARCH_SUCCESS; ++ else ++ return DVBFE_ALGO_SEARCH_AGAIN; ++} ++ ++static int get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int get_fe_t(struct cxd_state *state) ++{ ++ struct dvb_frontend *fe = &state->frontend; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ u8 tps[7]; ++ ++ read_tps(state, tps); ++ ++/* TPSData[0] [7:6] CNST[1:0] ++ TPSData[0] [5:3] HIER[2:0] ++ TPSData[0] [2:0] HRATE[2:0] ++*/ ++ switch ((tps[0] >> 6) & 0x03) { ++ case 0: ++ p->modulation = QPSK; ++ break; ++ case 1: ++ p->modulation = QAM_16; ++ break; ++ case 2: ++ p->modulation = QAM_64; ++ break; ++ } ++ switch ((tps[0] >> 3) & 0x07) { ++ case 0: ++ p->hierarchy = HIERARCHY_NONE; ++ break; ++ case 1: ++ p->hierarchy = HIERARCHY_1; ++ break; ++ case 2: ++ p->hierarchy = HIERARCHY_2; ++ break; ++ case 3: ++ p->hierarchy = HIERARCHY_4; ++ break; ++ } ++ switch ((tps[0] >> 0) & 0x07) { ++ case 0: ++ p->code_rate_HP = FEC_1_2; ++ break; ++ case 1: ++ p->code_rate_HP = FEC_2_3; ++ break; ++ case 2: ++ p->code_rate_HP = FEC_3_4; ++ break; ++ case 3: ++ p->code_rate_HP = FEC_5_6; ++ break; ++ case 4: ++ p->code_rate_HP = FEC_7_8; ++ break; ++ } ++ ++/* TPSData[1] [7:5] LRATE[2:0] ++ TPSData[1] [4:3] GI[1:0] ++ TPSData[1] [2:1] MODE[1:0] ++*/ ++ switch ((tps[1] >> 5) & 0x07) { ++ case 0: ++ p->code_rate_LP = FEC_1_2; ++ break; ++ case 1: ++ p->code_rate_LP = FEC_2_3; ++ break; ++ case 2: ++ p->code_rate_LP = FEC_3_4; ++ break; ++ case 3: ++ p->code_rate_LP = FEC_5_6; ++ break; ++ case 4: ++ p->code_rate_LP = FEC_7_8; ++ break; ++ } ++ switch ((tps[1] >> 3) & 0x03) { ++ case 0: ++ p->guard_interval = GUARD_INTERVAL_1_32; ++ break; ++ case 1: ++ p->guard_interval = GUARD_INTERVAL_1_16; ++ break; ++ case 2: ++ p->guard_interval = GUARD_INTERVAL_1_8; ++ break; ++ case 3: ++ p->guard_interval = GUARD_INTERVAL_1_4; ++ break; ++ } ++ switch ((tps[1] >> 1) & 0x03) { ++ case 0: ++ p->transmission_mode = TRANSMISSION_MODE_2K; ++ break; ++ case 1: ++ p->transmission_mode = TRANSMISSION_MODE_8K; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int get_fe_c(struct cxd_state *state) ++{ ++ struct dvb_frontend *fe = &state->frontend; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ u8 qam; ++ ++ freeze_regst(state); ++ readregst_unlocked(state, 0x40, 0x19, &qam, 1); ++ unfreeze_regst(state); ++ p->modulation = qam & 0x07; ++ return 0; ++} ++ ++static int get_frontend(struct dvb_frontend *fe) ++{ ++ struct cxd_state *state = fe->demodulator_priv; ++ ++ if (state->last_status != 0x1f) ++ return 0; ++ ++ switch (state->state) { ++ case ActiveT: ++ get_fe_t(state); ++ break; ++ case ActiveT2: ++ break; ++ case ActiveC: ++ get_fe_c(state); ++ break; ++ case ActiveC2: ++ break; ++ case ActiveIT: ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static struct dvb_frontend_ops common_ops_2843 = { ++ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, ++ .info = { ++ .name = "CXD2843 DVB-C/C2 DVB-T/T2", ++ .frequency_stepsize = 166667, /* DVB-T only */ ++ .frequency_min = 47000000, /* DVB-T: 47125000 */ ++ .frequency_max = 865000000, /* DVB-C: 862000000 */ ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = /* DVB-C */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | ++ FE_CAN_FEC_AUTO | ++ /* DVB-T */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | FE_CAN_MUTE_TS ++ }, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ .set_frontend = set_parameters, ++ ++ .get_tune_settings = get_tune_settings, ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++ .get_frontend = get_frontend, ++#ifdef USE_ALGO ++ .get_frontend_algo = get_algo, ++ .search = search, ++ .tune = tune, ++#endif ++}; ++ ++static struct dvb_frontend_ops common_ops_2837 = { ++ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, ++ .info = { ++ .name = "CXD2837 DVB-C DVB-T/T2", ++ .frequency_stepsize = 166667, /* DVB-T only */ ++ .frequency_min = 47000000, /* DVB-T: 47125000 */ ++ .frequency_max = 865000000, /* DVB-C: 862000000 */ ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = /* DVB-C */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | ++ FE_CAN_FEC_AUTO | ++ /* DVB-T */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | FE_CAN_MUTE_TS ++ }, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ .set_frontend = set_parameters, ++ ++ .get_tune_settings = get_tune_settings, ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++ .get_frontend = get_frontend, ++#ifdef USE_ALGO ++ .get_frontend_algo = get_algo, ++ .search = search, ++ .tune = tune, ++#endif ++}; ++ ++static struct dvb_frontend_ops common_ops_2838 = { ++ .delsys = { SYS_ISDBT }, ++ .info = { ++ .name = "CXD2838 ISDB-T", ++ .frequency_stepsize = 166667, ++ .frequency_min = 47000000, ++ .frequency_max = 865000000, ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | FE_CAN_MUTE_TS ++ }, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ .set_frontend = set_parameters, ++ ++ .get_tune_settings = get_tune_settings, ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++#ifdef USE_ALGO ++ .get_frontend_algo = get_algo, ++ .search = search, ++ .tune = tune, ++#endif ++}; ++ ++static int probe(struct cxd_state *state) ++{ ++ u8 ChipID = 0x00; ++ int status; ++ ++ status = readregst(state, 0x00, 0xFD, &ChipID, 1); ++ ++ if (status) ++ status = readregsx(state, 0x00, 0xFD, &ChipID, 1); ++ if (status) ++ return status; ++ ++ /*printk("ChipID = %02X\n", ChipID);*/ ++ switch (ChipID) { ++ case 0xa4: ++ state->type = CXD2843; ++ memcpy(&state->frontend.ops, &common_ops_2843, ++ sizeof(struct dvb_frontend_ops)); ++ break; ++ case 0xb1: ++ state->type = CXD2837; ++ memcpy(&state->frontend.ops, &common_ops_2837, ++ sizeof(struct dvb_frontend_ops)); ++ break; ++ case 0xb0: ++ state->type = CXD2838; ++ memcpy(&state->frontend.ops, &common_ops_2838, ++ sizeof(struct dvb_frontend_ops)); ++ break; ++ default: ++ return -1; ++ } ++ state->frontend.demodulator_priv = state; ++ return 0; ++} ++ ++struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, ++ struct cxd2843_cfg *cfg) ++{ ++ struct cxd_state *state = NULL; ++ ++ state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->i2c = i2c; ++ init_state(state, cfg); ++ if (probe(state) == 0) { ++ init(state); ++ return &state->frontend; ++ } ++ pr_err("cxd2843: not found\n"); ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(cxd2843_attach); ++ ++MODULE_DESCRIPTION("CXD2843/37/38 driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h +new file mode 100644 +index 0000000..f3e355b +--- /dev/null ++++ b/drivers/media/dvb-frontends/cxd2843.h +@@ -0,0 +1,30 @@ ++#ifndef _CXD2843_H_ ++#define _CXD2843_H_ ++ ++#include ++#include ++ ++struct cxd2843_cfg { ++ u8 adr; ++ u32 ts_clock; ++ u8 parallel; ++}; ++ ++#if defined(CONFIG_DVB_CXD2843) || \ ++ (defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE)) ++ ++extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, ++ struct cxd2843_cfg *cfg); ++ ++#else ++ ++static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, ++ struct cxd2843_cfg *cfg) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c +index d46cf5f..91a7f9f 100644 +--- a/drivers/media/dvb-frontends/drxk_hard.c ++++ b/drivers/media/dvb-frontends/drxk_hard.c +@@ -21,8 +21,6 @@ + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- + #include + #include + #include +@@ -30,42 +28,50 @@ + #include + #include + #include +-#include + #include + + #include "dvb_frontend.h" + #include "drxk.h" + #include "drxk_hard.h" +-#include "dvb_math.h" +- +-static int power_down_dvbt(struct drxk_state *state, bool set_power_mode); +-static int power_down_qam(struct drxk_state *state); +-static int set_dvbt_standard(struct drxk_state *state, +- enum operation_mode o_mode); +-static int set_qam_standard(struct drxk_state *state, +- enum operation_mode o_mode); +-static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, +- s32 tuner_freq_offset); +-static int set_dvbt_standard(struct drxk_state *state, +- enum operation_mode o_mode); +-static int dvbt_start(struct drxk_state *state); +-static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, +- s32 tuner_freq_offset); +-static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status); +-static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status); +-static int switch_antenna_to_qam(struct drxk_state *state); +-static int switch_antenna_to_dvbt(struct drxk_state *state); +- +-static bool is_dvbt(struct drxk_state *state) ++ ++static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode); ++static int PowerDownQAM(struct drxk_state *state); ++static int SetDVBTStandard(struct drxk_state *state, ++ enum OperationMode oMode); ++static int SetQAMStandard(struct drxk_state *state, ++ enum OperationMode oMode); ++static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, ++ s32 tunerFreqOffset); ++static int SetDVBTStandard(struct drxk_state *state, ++ enum OperationMode oMode); ++static int DVBTStart(struct drxk_state *state); ++static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, ++ s32 tunerFreqOffset); ++static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus); ++static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus); ++static int SwitchAntennaToQAM(struct drxk_state *state); ++static int SwitchAntennaToDVBT(struct drxk_state *state); ++ ++static bool IsDVBT(struct drxk_state *state) ++{ ++ return state->m_OperationMode == OM_DVBT; ++} ++ ++static bool IsQAM(struct drxk_state *state) ++{ ++ return state->m_OperationMode == OM_QAM_ITU_A || ++ state->m_OperationMode == OM_QAM_ITU_B || ++ state->m_OperationMode == OM_QAM_ITU_C; ++} ++ ++bool IsA1WithPatchCode(struct drxk_state *state) + { +- return state->m_operation_mode == OM_DVBT; ++ return state->m_DRXK_A1_PATCH_CODE; + } + +-static bool is_qam(struct drxk_state *state) ++bool IsA1WithRomCode(struct drxk_state *state) + { +- return state->m_operation_mode == OM_QAM_ITU_A || +- state->m_operation_mode == OM_QAM_ITU_B || +- state->m_operation_mode == OM_QAM_ITU_C; ++ return state->m_DRXK_A1_ROM_CODE; + } + + #define NOA1ROM 0 +@@ -166,9 +172,9 @@ static unsigned int debug; + module_param(debug, int, 0644); + MODULE_PARM_DESC(debug, "enable debug messages"); + +-#define dprintk(level, fmt, arg...) do { \ +-if (debug >= level) \ +- printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg); \ ++#define dprintk(level, fmt, arg...) do { \ ++if (debug >= level) \ ++ printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg); \ + } while (0) + + +@@ -182,17 +188,15 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c) + return (u32) tmp64; + } + +-static inline u32 Frac28a(u32 a, u32 c) ++inline u32 Frac28a(u32 a, u32 c) + { + int i = 0; + u32 Q1 = 0; + u32 R0 = 0; + + R0 = (a % c) << 4; /* 32-28 == 4 shifts possible at max */ +- Q1 = a / c; /* +- * integer part, only the 4 least significant +- * bits will be visible in the result +- */ ++ Q1 = a / c; /* integer part, only the 4 least significant bits ++ will be visible in the result */ + + /* division using radix 16, 7 nibbles in the result */ + for (i = 0; i < 7; i++) { +@@ -206,51 +210,114 @@ static inline u32 Frac28a(u32 a, u32 c) + return Q1; + } + +-static inline u32 log10times100(u32 value) ++static u32 Log10Times100(u32 x) + { +- return (100L * intlog10(value)) >> 24; +-} +- +-/****************************************************************************/ +-/* I2C **********************************************************************/ +-/****************************************************************************/ ++ static const u8 scale = 15; ++ static const u8 indexWidth = 5; ++ u8 i = 0; ++ u32 y = 0; ++ u32 d = 0; ++ u32 k = 0; ++ u32 r = 0; ++ /* ++ log2lut[n] = (1<i2c); +- state->drxk_i2c_exclusive_lock = true; ++ static const u32 log2lut[] = { ++ 0, /* 0.000000 */ ++ 290941, /* 290941.300628 */ ++ 573196, /* 573196.476418 */ ++ 847269, /* 847269.179851 */ ++ 1113620, /* 1113620.489452 */ ++ 1372674, /* 1372673.576986 */ ++ 1624818, /* 1624817.752104 */ ++ 1870412, /* 1870411.981536 */ ++ 2109788, /* 2109787.962654 */ ++ 2343253, /* 2343252.817465 */ ++ 2571091, /* 2571091.461923 */ ++ 2793569, /* 2793568.696416 */ ++ 3010931, /* 3010931.055901 */ ++ 3223408, /* 3223408.452106 */ ++ 3431216, /* 3431215.635215 */ ++ 3634553, /* 3634553.498355 */ ++ 3833610, /* 3833610.244726 */ ++ 4028562, /* 4028562.434393 */ ++ 4219576, /* 4219575.925308 */ ++ 4406807, /* 4406806.721144 */ ++ 4590402, /* 4590401.736809 */ ++ 4770499, /* 4770499.491025 */ ++ 4947231, /* 4947230.734179 */ ++ 5120719, /* 5120719.018555 */ ++ 5291081, /* 5291081.217197 */ ++ 5458428, /* 5458427.996830 */ ++ 5622864, /* 5622864.249668 */ ++ 5784489, /* 5784489.488298 */ ++ 5943398, /* 5943398.207380 */ ++ 6099680, /* 6099680.215452 */ ++ 6253421, /* 6253420.939751 */ ++ 6404702, /* 6404701.706649 */ ++ 6553600, /* 6553600.000000 */ ++ }; + +- return 0; +-} + +-static void drxk_i2c_unlock(struct drxk_state *state) +-{ +- if (!state->drxk_i2c_exclusive_lock) +- return; ++ if (x == 0) ++ return 0; + +- i2c_unlock_adapter(state->i2c); +- state->drxk_i2c_exclusive_lock = false; ++ /* Scale x (normalize) */ ++ /* computing y in log(x/y) = log(x) - log(y) */ ++ if ((x & ((0xffffffff) << (scale + 1))) == 0) { ++ for (k = scale; k > 0; k--) { ++ if (x & (((u32) 1) << scale)) ++ break; ++ x <<= 1; ++ } ++ } else { ++ for (k = scale; k < 31; k++) { ++ if ((x & (((u32) (-1)) << (scale + 1))) == 0) ++ break; ++ x >>= 1; ++ } ++ } ++ /* ++ Now x has binary point between bit[scale] and bit[scale-1] ++ and 1.0 <= x < 2.0 */ ++ ++ /* correction for divison: log(x) = log(x/y)+log(y) */ ++ y = k * ((((u32) 1) << scale) * 200); ++ ++ /* remove integer part */ ++ x &= ((((u32) 1) << scale) - 1); ++ /* get index */ ++ i = (u8) (x >> (scale - indexWidth)); ++ /* compute delta (x - a) */ ++ d = x & ((((u32) 1) << (scale - indexWidth)) - 1); ++ /* compute log, multiplication (d* (..)) must be within range ! */ ++ y += log2lut[i] + ++ ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth)); ++ /* Conver to log10() */ ++ y /= 108853; /* (log2(10) << scale) */ ++ r = (y >> 1); ++ /* rounding */ ++ if (y & ((u32) 1)) ++ r++; ++ return r; + } + +-static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs, +- unsigned len) +-{ +- if (state->drxk_i2c_exclusive_lock) +- return __i2c_transfer(state->i2c, msgs, len); +- else +- return i2c_transfer(state->i2c, msgs, len); +-} ++/****************************************************************************/ ++/* I2C **********************************************************************/ ++/****************************************************************************/ + +-static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val) ++static int i2c_read1(struct i2c_adapter *adapter, u8 adr, u8 *val) + { + struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD, + .buf = val, .len = 1} + }; + +- return drxk_i2c_transfer(state, msgs, 1); ++ return i2c_transfer(adapter, msgs, 1); + } + +-static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) + { + int status; + struct i2c_msg msg = { +@@ -260,20 +327,20 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) + if (debug > 2) { + int i; + for (i = 0; i < len; i++) +- pr_cont(" %02x", data[i]); +- pr_cont("\n"); ++ printk(KERN_CONT " %02x", data[i]); ++ printk(KERN_CONT "\n"); + } +- status = drxk_i2c_transfer(state, &msg, 1); ++ status = i2c_transfer(adap, &msg, 1); + if (status >= 0 && status != 1) + status = -EIO; + + if (status < 0) +- pr_err("i2c write error at addr 0x%02x\n", adr); ++ printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr); + + return status; + } + +-static int i2c_read(struct drxk_state *state, ++static int i2c_read(struct i2c_adapter *adap, + u8 adr, u8 *msg, int len, u8 *answ, int alen) + { + int status; +@@ -284,25 +351,25 @@ static int i2c_read(struct drxk_state *state, + .buf = answ, .len = alen} + }; + +- status = drxk_i2c_transfer(state, msgs, 2); ++ status = i2c_transfer(adap, msgs, 2); + if (status != 2) { + if (debug > 2) +- pr_cont(": ERROR!\n"); ++ printk(KERN_CONT ": ERROR!\n"); + if (status >= 0) + status = -EIO; + +- pr_err("i2c read error at addr 0x%02x\n", adr); ++ printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr); + return status; + } + if (debug > 2) { + int i; + dprintk(2, ": read from"); + for (i = 0; i < len; i++) +- pr_cont(" %02x", msg[i]); +- pr_cont(", value = "); ++ printk(KERN_CONT " %02x", msg[i]); ++ printk(KERN_CONT ", value = "); + for (i = 0; i < alen; i++) +- pr_cont(" %02x", answ[i]); +- pr_cont("\n"); ++ printk(KERN_CONT " %02x", answ[i]); ++ printk(KERN_CONT "\n"); + } + return 0; + } +@@ -327,7 +394,7 @@ static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags) + len = 2; + } + dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); +- status = i2c_read(state, adr, mm1, len, mm2, 2); ++ status = i2c_read(state->i2c, adr, mm1, len, mm2, 2); + if (status < 0) + return status; + if (data) +@@ -361,7 +428,7 @@ static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags) + len = 2; + } + dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); +- status = i2c_read(state, adr, mm1, len, mm2, 4); ++ status = i2c_read(state->i2c, adr, mm1, len, mm2, 4); + if (status < 0) + return status; + if (data) +@@ -397,7 +464,7 @@ static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags) + mm[len + 1] = (data >> 8) & 0xff; + + dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags); +- return i2c_write(state, adr, mm, len + 2); ++ return i2c_write(state->i2c, adr, mm, len + 2); + } + + static int write16(struct drxk_state *state, u32 reg, u16 data) +@@ -428,7 +495,7 @@ static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags) + mm[len + 3] = (data >> 24) & 0xff; + dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags); + +- return i2c_write(state, adr, mm, len + 4); ++ return i2c_write(state->i2c, adr, mm, len + 4); + } + + static int write32(struct drxk_state *state, u32 reg, u32 data) +@@ -436,55 +503,55 @@ static int write32(struct drxk_state *state, u32 reg, u32 data) + return write32_flags(state, reg, data, 0); + } + +-static int write_block(struct drxk_state *state, u32 address, +- const int block_size, const u8 p_block[]) ++static int write_block(struct drxk_state *state, u32 Address, ++ const int BlockSize, const u8 pBlock[]) + { +- int status = 0, blk_size = block_size; +- u8 flags = 0; ++ int status = 0, BlkSize = BlockSize; ++ u8 Flags = 0; + + if (state->single_master) +- flags |= 0xC0; +- +- while (blk_size > 0) { +- int chunk = blk_size > state->m_chunk_size ? +- state->m_chunk_size : blk_size; +- u8 *adr_buf = &state->chunk[0]; +- u32 adr_length = 0; +- +- if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) { +- adr_buf[0] = (((address << 1) & 0xFF) | 0x01); +- adr_buf[1] = ((address >> 16) & 0xFF); +- adr_buf[2] = ((address >> 24) & 0xFF); +- adr_buf[3] = ((address >> 7) & 0xFF); +- adr_buf[2] |= flags; +- adr_length = 4; +- if (chunk == state->m_chunk_size) +- chunk -= 2; ++ Flags |= 0xC0; ++ ++ while (BlkSize > 0) { ++ int Chunk = BlkSize > state->m_ChunkSize ? ++ state->m_ChunkSize : BlkSize; ++ u8 *AdrBuf = &state->Chunk[0]; ++ u32 AdrLength = 0; ++ ++ if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) { ++ AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01); ++ AdrBuf[1] = ((Address >> 16) & 0xFF); ++ AdrBuf[2] = ((Address >> 24) & 0xFF); ++ AdrBuf[3] = ((Address >> 7) & 0xFF); ++ AdrBuf[2] |= Flags; ++ AdrLength = 4; ++ if (Chunk == state->m_ChunkSize) ++ Chunk -= 2; + } else { +- adr_buf[0] = ((address << 1) & 0xFF); +- adr_buf[1] = (((address >> 16) & 0x0F) | +- ((address >> 18) & 0xF0)); +- adr_length = 2; ++ AdrBuf[0] = ((Address << 1) & 0xFF); ++ AdrBuf[1] = (((Address >> 16) & 0x0F) | ++ ((Address >> 18) & 0xF0)); ++ AdrLength = 2; + } +- memcpy(&state->chunk[adr_length], p_block, chunk); +- dprintk(2, "(0x%08x, 0x%02x)\n", address, flags); ++ memcpy(&state->Chunk[AdrLength], pBlock, Chunk); ++ dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags); + if (debug > 1) { + int i; +- if (p_block) +- for (i = 0; i < chunk; i++) +- pr_cont(" %02x", p_block[i]); +- pr_cont("\n"); ++ if (pBlock) ++ for (i = 0; i < Chunk; i++) ++ printk(KERN_CONT " %02x", pBlock[i]); ++ printk(KERN_CONT "\n"); + } +- status = i2c_write(state, state->demod_address, +- &state->chunk[0], chunk + adr_length); ++ status = i2c_write(state->i2c, state->demod_address, ++ &state->Chunk[0], Chunk + AdrLength); + if (status < 0) { +- pr_err("%s: i2c write error at addr 0x%02x\n", +- __func__, address); ++ printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", ++ __func__, Address); + break; + } +- p_block += chunk; +- address += (chunk >> 1); +- blk_size -= chunk; ++ pBlock += Chunk; ++ Address += (Chunk >> 1); ++ BlkSize -= Chunk; + } + return status; + } +@@ -493,29 +560,29 @@ static int write_block(struct drxk_state *state, u32 address, + #define DRXK_MAX_RETRIES_POWERUP 20 + #endif + +-static int power_up_device(struct drxk_state *state) ++int PowerUpDevice(struct drxk_state *state) + { + int status; + u8 data = 0; +- u16 retry_count = 0; ++ u16 retryCount = 0; + + dprintk(1, "\n"); + +- status = i2c_read1(state, state->demod_address, &data); ++ status = i2c_read1(state->i2c, state->demod_address, &data); + if (status < 0) { + do { + data = 0; +- status = i2c_write(state, state->demod_address, ++ status = i2c_write(state->i2c, state->demod_address, + &data, 1); +- usleep_range(10000, 11000); +- retry_count++; ++ msleep(10); ++ retryCount++; + if (status < 0) + continue; +- status = i2c_read1(state, state->demod_address, ++ status = i2c_read1(state->i2c, state->demod_address, + &data); + } while (status < 0 && +- (retry_count < DRXK_MAX_RETRIES_POWERUP)); +- if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP) ++ (retryCount < DRXK_MAX_RETRIES_POWERUP)); ++ if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP) + goto error; + } + +@@ -531,11 +598,11 @@ static int power_up_device(struct drxk_state *state) + if (status < 0) + goto error; + +- state->m_current_power_mode = DRX_POWER_UP; ++ state->m_currentPowerMode = DRX_POWER_UP; + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } +@@ -547,106 +614,111 @@ static int init_state(struct drxk_state *state) + * FIXME: most (all?) of the values bellow should be moved into + * struct drxk_config, as they are probably board-specific + */ +- u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO; +- u32 ul_vsb_if_agc_output_level = 0; +- u32 ul_vsb_if_agc_min_level = 0; +- u32 ul_vsb_if_agc_max_level = 0x7FFF; +- u32 ul_vsb_if_agc_speed = 3; +- +- u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO; +- u32 ul_vsb_rf_agc_output_level = 0; +- u32 ul_vsb_rf_agc_min_level = 0; +- u32 ul_vsb_rf_agc_max_level = 0x7FFF; +- u32 ul_vsb_rf_agc_speed = 3; +- u32 ul_vsb_rf_agc_top = 9500; +- u32 ul_vsb_rf_agc_cut_off_current = 4000; +- +- u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO; +- u32 ul_atv_if_agc_output_level = 0; +- u32 ul_atv_if_agc_min_level = 0; +- u32 ul_atv_if_agc_max_level = 0; +- u32 ul_atv_if_agc_speed = 3; +- +- u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF; +- u32 ul_atv_rf_agc_output_level = 0; +- u32 ul_atv_rf_agc_min_level = 0; +- u32 ul_atv_rf_agc_max_level = 0; +- u32 ul_atv_rf_agc_top = 9500; +- u32 ul_atv_rf_agc_cut_off_current = 4000; +- u32 ul_atv_rf_agc_speed = 3; ++ u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO; ++ u32 ulVSBIfAgcOutputLevel = 0; ++ u32 ulVSBIfAgcMinLevel = 0; ++ u32 ulVSBIfAgcMaxLevel = 0x7FFF; ++ u32 ulVSBIfAgcSpeed = 3; ++ ++ u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO; ++ u32 ulVSBRfAgcOutputLevel = 0; ++ u32 ulVSBRfAgcMinLevel = 0; ++ u32 ulVSBRfAgcMaxLevel = 0x7FFF; ++ u32 ulVSBRfAgcSpeed = 3; ++ u32 ulVSBRfAgcTop = 9500; ++ u32 ulVSBRfAgcCutOffCurrent = 4000; ++ ++ u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO; ++ u32 ulATVIfAgcOutputLevel = 0; ++ u32 ulATVIfAgcMinLevel = 0; ++ u32 ulATVIfAgcMaxLevel = 0; ++ u32 ulATVIfAgcSpeed = 3; ++ ++ u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF; ++ u32 ulATVRfAgcOutputLevel = 0; ++ u32 ulATVRfAgcMinLevel = 0; ++ u32 ulATVRfAgcMaxLevel = 0; ++ u32 ulATVRfAgcTop = 9500; ++ u32 ulATVRfAgcCutOffCurrent = 4000; ++ u32 ulATVRfAgcSpeed = 3; + + u32 ulQual83 = DEFAULT_MER_83; + u32 ulQual93 = DEFAULT_MER_93; + +- u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; +- u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; ++ u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; ++ u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ +- u32 ul_gpio_cfg = 0x0113; +- u32 ul_invert_ts_clock = 0; +- u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; +- u32 ul_dvbt_bitrate = 50000000; +- u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; ++ u32 ulGPIOCfg = 0x0113; ++ u32 ulInvertTSClock = 0; ++ u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; ++ u32 ulDVBTBitrate = 50000000; ++ u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; + +- u32 ul_insert_rs_byte = 0; ++ u32 ulInsertRSByte = 0; + +- u32 ul_rf_mirror = 1; +- u32 ul_power_down = 0; ++ u32 ulRfMirror = 1; ++ u32 ulPowerDown = 0; + + dprintk(1, "\n"); + +- state->m_has_lna = false; +- state->m_has_dvbt = false; +- state->m_has_dvbc = false; +- state->m_has_atv = false; +- state->m_has_oob = false; +- state->m_has_audio = false; ++ state->m_hasLNA = false; ++ state->m_hasDVBT = false; ++ state->m_hasDVBC = false; ++ state->m_hasATV = false; ++ state->m_hasOOB = false; ++ state->m_hasAudio = false; + +- if (!state->m_chunk_size) +- state->m_chunk_size = 124; ++ if (!state->m_ChunkSize) ++ state->m_ChunkSize = 124; + +- state->m_osc_clock_freq = 0; +- state->m_smart_ant_inverted = false; +- state->m_b_p_down_open_bridge = false; ++ state->m_oscClockFreq = 0; ++ state->m_smartAntInverted = false; ++ state->m_bPDownOpenBridge = false; + + /* real system clock frequency in kHz */ +- state->m_sys_clock_freq = 151875; ++ state->m_sysClockFreq = 151875; + /* Timing div, 250ns/Psys */ + /* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */ +- state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) * ++ state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) * + HI_I2C_DELAY) / 1000; + /* Clipping */ +- if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) +- state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; +- state->m_hi_cfg_wake_up_key = (state->demod_address << 1); ++ if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) ++ state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; ++ state->m_HICfgWakeUpKey = (state->demod_address << 1); + /* port/bridge/power down ctrl */ +- state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; ++ state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + +- state->m_b_power_down = (ul_power_down != 0); ++ state->m_bPowerDown = (ulPowerDown != 0); + +- state->m_drxk_a3_patch_code = false; ++ state->m_DRXK_A1_PATCH_CODE = false; ++ state->m_DRXK_A1_ROM_CODE = false; ++ state->m_DRXK_A2_ROM_CODE = false; ++ state->m_DRXK_A3_ROM_CODE = false; ++ state->m_DRXK_A2_PATCH_CODE = false; ++ state->m_DRXK_A3_PATCH_CODE = false; + + /* Init AGC and PGA parameters */ + /* VSB IF */ +- state->m_vsb_if_agc_cfg.ctrl_mode = ul_vsb_if_agc_mode; +- state->m_vsb_if_agc_cfg.output_level = ul_vsb_if_agc_output_level; +- state->m_vsb_if_agc_cfg.min_output_level = ul_vsb_if_agc_min_level; +- state->m_vsb_if_agc_cfg.max_output_level = ul_vsb_if_agc_max_level; +- state->m_vsb_if_agc_cfg.speed = ul_vsb_if_agc_speed; +- state->m_vsb_pga_cfg = 140; ++ state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode); ++ state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel); ++ state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel); ++ state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel); ++ state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed); ++ state->m_vsbPgaCfg = 140; + + /* VSB RF */ +- state->m_vsb_rf_agc_cfg.ctrl_mode = ul_vsb_rf_agc_mode; +- state->m_vsb_rf_agc_cfg.output_level = ul_vsb_rf_agc_output_level; +- state->m_vsb_rf_agc_cfg.min_output_level = ul_vsb_rf_agc_min_level; +- state->m_vsb_rf_agc_cfg.max_output_level = ul_vsb_rf_agc_max_level; +- state->m_vsb_rf_agc_cfg.speed = ul_vsb_rf_agc_speed; +- state->m_vsb_rf_agc_cfg.top = ul_vsb_rf_agc_top; +- state->m_vsb_rf_agc_cfg.cut_off_current = ul_vsb_rf_agc_cut_off_current; +- state->m_vsb_pre_saw_cfg.reference = 0x07; +- state->m_vsb_pre_saw_cfg.use_pre_saw = true; ++ state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode); ++ state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel); ++ state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel); ++ state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel); ++ state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed); ++ state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop); ++ state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent); ++ state->m_vsbPreSawCfg.reference = 0x07; ++ state->m_vsbPreSawCfg.usePreSaw = true; + + state->m_Quality83percent = DEFAULT_MER_83; + state->m_Quality93percent = DEFAULT_MER_93; +@@ -656,127 +728,127 @@ static int init_state(struct drxk_state *state) + } + + /* ATV IF */ +- state->m_atv_if_agc_cfg.ctrl_mode = ul_atv_if_agc_mode; +- state->m_atv_if_agc_cfg.output_level = ul_atv_if_agc_output_level; +- state->m_atv_if_agc_cfg.min_output_level = ul_atv_if_agc_min_level; +- state->m_atv_if_agc_cfg.max_output_level = ul_atv_if_agc_max_level; +- state->m_atv_if_agc_cfg.speed = ul_atv_if_agc_speed; ++ state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode); ++ state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel); ++ state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel); ++ state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel); ++ state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed); + + /* ATV RF */ +- state->m_atv_rf_agc_cfg.ctrl_mode = ul_atv_rf_agc_mode; +- state->m_atv_rf_agc_cfg.output_level = ul_atv_rf_agc_output_level; +- state->m_atv_rf_agc_cfg.min_output_level = ul_atv_rf_agc_min_level; +- state->m_atv_rf_agc_cfg.max_output_level = ul_atv_rf_agc_max_level; +- state->m_atv_rf_agc_cfg.speed = ul_atv_rf_agc_speed; +- state->m_atv_rf_agc_cfg.top = ul_atv_rf_agc_top; +- state->m_atv_rf_agc_cfg.cut_off_current = ul_atv_rf_agc_cut_off_current; +- state->m_atv_pre_saw_cfg.reference = 0x04; +- state->m_atv_pre_saw_cfg.use_pre_saw = true; ++ state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode); ++ state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel); ++ state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel); ++ state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel); ++ state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed); ++ state->m_atvRfAgcCfg.top = (ulATVRfAgcTop); ++ state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent); ++ state->m_atvPreSawCfg.reference = 0x04; ++ state->m_atvPreSawCfg.usePreSaw = true; + + + /* DVBT RF */ +- state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; +- state->m_dvbt_rf_agc_cfg.output_level = 0; +- state->m_dvbt_rf_agc_cfg.min_output_level = 0; +- state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF; +- state->m_dvbt_rf_agc_cfg.top = 0x2100; +- state->m_dvbt_rf_agc_cfg.cut_off_current = 4000; +- state->m_dvbt_rf_agc_cfg.speed = 1; ++ state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; ++ state->m_dvbtRfAgcCfg.outputLevel = 0; ++ state->m_dvbtRfAgcCfg.minOutputLevel = 0; ++ state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF; ++ state->m_dvbtRfAgcCfg.top = 0x2100; ++ state->m_dvbtRfAgcCfg.cutOffCurrent = 4000; ++ state->m_dvbtRfAgcCfg.speed = 1; + + + /* DVBT IF */ +- state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; +- state->m_dvbt_if_agc_cfg.output_level = 0; +- state->m_dvbt_if_agc_cfg.min_output_level = 0; +- state->m_dvbt_if_agc_cfg.max_output_level = 9000; +- state->m_dvbt_if_agc_cfg.top = 13424; +- state->m_dvbt_if_agc_cfg.cut_off_current = 0; +- state->m_dvbt_if_agc_cfg.speed = 3; +- state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30; +- state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000; ++ state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; ++ state->m_dvbtIfAgcCfg.outputLevel = 0; ++ state->m_dvbtIfAgcCfg.minOutputLevel = 0; ++ state->m_dvbtIfAgcCfg.maxOutputLevel = 9000; ++ state->m_dvbtIfAgcCfg.top = 13424; ++ state->m_dvbtIfAgcCfg.cutOffCurrent = 0; ++ state->m_dvbtIfAgcCfg.speed = 3; ++ state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30; ++ state->m_dvbtIfAgcCfg.IngainTgtMax = 30000; + /* state->m_dvbtPgaCfg = 140; */ + +- state->m_dvbt_pre_saw_cfg.reference = 4; +- state->m_dvbt_pre_saw_cfg.use_pre_saw = false; ++ state->m_dvbtPreSawCfg.reference = 4; ++ state->m_dvbtPreSawCfg.usePreSaw = false; + + /* QAM RF */ +- state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; +- state->m_qam_rf_agc_cfg.output_level = 0; +- state->m_qam_rf_agc_cfg.min_output_level = 6023; +- state->m_qam_rf_agc_cfg.max_output_level = 27000; +- state->m_qam_rf_agc_cfg.top = 0x2380; +- state->m_qam_rf_agc_cfg.cut_off_current = 4000; +- state->m_qam_rf_agc_cfg.speed = 3; ++ state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; ++ state->m_qamRfAgcCfg.outputLevel = 0; ++ state->m_qamRfAgcCfg.minOutputLevel = 6023; ++ state->m_qamRfAgcCfg.maxOutputLevel = 27000; ++ state->m_qamRfAgcCfg.top = 0x2380; ++ state->m_qamRfAgcCfg.cutOffCurrent = 4000; ++ state->m_qamRfAgcCfg.speed = 3; + + /* QAM IF */ +- state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; +- state->m_qam_if_agc_cfg.output_level = 0; +- state->m_qam_if_agc_cfg.min_output_level = 0; +- state->m_qam_if_agc_cfg.max_output_level = 9000; +- state->m_qam_if_agc_cfg.top = 0x0511; +- state->m_qam_if_agc_cfg.cut_off_current = 0; +- state->m_qam_if_agc_cfg.speed = 3; +- state->m_qam_if_agc_cfg.ingain_tgt_max = 5119; +- state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50; +- +- state->m_qam_pga_cfg = 140; +- state->m_qam_pre_saw_cfg.reference = 4; +- state->m_qam_pre_saw_cfg.use_pre_saw = false; +- +- state->m_operation_mode = OM_NONE; +- state->m_drxk_state = DRXK_UNINITIALIZED; ++ state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; ++ state->m_qamIfAgcCfg.outputLevel = 0; ++ state->m_qamIfAgcCfg.minOutputLevel = 0; ++ state->m_qamIfAgcCfg.maxOutputLevel = 9000; ++ state->m_qamIfAgcCfg.top = 0x0511; ++ state->m_qamIfAgcCfg.cutOffCurrent = 0; ++ state->m_qamIfAgcCfg.speed = 3; ++ state->m_qamIfAgcCfg.IngainTgtMax = 5119; ++ state->m_qamIfAgcCfg.FastClipCtrlDelay = 50; ++ ++ state->m_qamPgaCfg = 140; ++ state->m_qamPreSawCfg.reference = 4; ++ state->m_qamPreSawCfg.usePreSaw = false; ++ ++ state->m_OperationMode = OM_NONE; ++ state->m_DrxkState = DRXK_UNINITIALIZED; + + /* MPEG output configuration */ +- state->m_enable_mpeg_output = true; /* If TRUE; enable MPEG ouput */ +- state->m_insert_rs_byte = false; /* If TRUE; insert RS byte */ +- state->m_invert_data = false; /* If TRUE; invert DATA signals */ +- state->m_invert_err = false; /* If TRUE; invert ERR signal */ +- state->m_invert_str = false; /* If TRUE; invert STR signals */ +- state->m_invert_val = false; /* If TRUE; invert VAL signals */ +- state->m_invert_clk = (ul_invert_ts_clock != 0); /* If TRUE; invert CLK signals */ ++ state->m_enableMPEGOutput = true; /* If TRUE; enable MPEG ouput */ ++ state->m_insertRSByte = false; /* If TRUE; insert RS byte */ ++ state->m_invertDATA = false; /* If TRUE; invert DATA signals */ ++ state->m_invertERR = false; /* If TRUE; invert ERR signal */ ++ state->m_invertSTR = false; /* If TRUE; invert STR signals */ ++ state->m_invertVAL = false; /* If TRUE; invert VAL signals */ ++ state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ + + /* If TRUE; static MPEG clockrate will be used; + otherwise clockrate will adapt to the bitrate of the TS */ + +- state->m_dvbt_bitrate = ul_dvbt_bitrate; +- state->m_dvbc_bitrate = ul_dvbc_bitrate; ++ state->m_DVBTBitrate = ulDVBTBitrate; ++ state->m_DVBCBitrate = ulDVBCBitrate; + +- state->m_ts_data_strength = (ul_ts_data_strength & 0x07); ++ state->m_TSDataStrength = (ulTSDataStrength & 0x07); + + /* Maximum bitrate in b/s in case static clockrate is selected */ +- state->m_mpeg_ts_static_bitrate = 19392658; +- state->m_disable_te_ihandling = false; ++ state->m_mpegTsStaticBitrate = 19392658; ++ state->m_disableTEIhandling = false; + +- if (ul_insert_rs_byte) +- state->m_insert_rs_byte = true; ++ if (ulInsertRSByte) ++ state->m_insertRSByte = true; + +- state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; +- if (ul_mpeg_lock_time_out < 10000) +- state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out; +- state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; +- if (ul_demod_lock_time_out < 10000) +- state->m_demod_lock_time_out = ul_demod_lock_time_out; ++ state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; ++ if (ulMpegLockTimeOut < 10000) ++ state->m_MpegLockTimeOut = ulMpegLockTimeOut; ++ state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; ++ if (ulDemodLockTimeOut < 10000) ++ state->m_DemodLockTimeOut = ulDemodLockTimeOut; + + /* QAM defaults */ +- state->m_constellation = DRX_CONSTELLATION_AUTO; +- state->m_qam_interleave_mode = DRXK_QAM_I12_J17; +- state->m_fec_rs_plen = 204 * 8; /* fecRsPlen annex A */ +- state->m_fec_rs_prescale = 1; ++ state->m_Constellation = DRX_CONSTELLATION_AUTO; ++ state->m_qamInterleaveMode = DRXK_QAM_I12_J17; ++ state->m_fecRsPlen = 204 * 8; /* fecRsPlen annex A */ ++ state->m_fecRsPrescale = 1; + +- state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM; +- state->m_agcfast_clip_ctrl_delay = 0; ++ state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM; ++ state->m_agcFastClipCtrlDelay = 0; + +- state->m_gpio_cfg = ul_gpio_cfg; ++ state->m_GPIOCfg = (ulGPIOCfg); + +- state->m_b_power_down = false; +- state->m_current_power_mode = DRX_POWER_DOWN; ++ state->m_bPowerDown = false; ++ state->m_currentPowerMode = DRX_POWER_DOWN; + +- state->m_rfmirror = (ul_rf_mirror == 0); +- state->m_if_agc_pol = false; ++ state->m_rfmirror = (ulRfMirror == 0); ++ state->m_IfAgcPol = false; + return 0; + } + +-static int drxx_open(struct drxk_state *state) ++static int DRXX_Open(struct drxk_state *state) + { + int status = 0; + u32 jtag = 0; +@@ -785,8 +857,7 @@ static int drxx_open(struct drxk_state *state) + + dprintk(1, "\n"); + /* stop lock indicator process */ +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; + /* Check device id */ +@@ -805,14 +876,14 @@ static int drxx_open(struct drxk_state *state) + status = write16(state, SIO_TOP_COMM_KEY__A, key); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int get_device_capabilities(struct drxk_state *state) ++static int GetDeviceCapabilities(struct drxk_state *state) + { +- u16 sio_pdr_ohw_cfg = 0; +- u32 sio_top_jtagid_lo = 0; ++ u16 sioPdrOhwCfg = 0; ++ u32 sioTopJtagidLo = 0; + int status; + const char *spin = ""; + +@@ -820,196 +891,197 @@ static int get_device_capabilities(struct drxk_state *state) + + /* driver 0.9.0 */ + /* stop lock indicator process */ +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; +- status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); ++ status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA); + if (status < 0) + goto error; +- status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg); ++ status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg); + if (status < 0) + goto error; + status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); + if (status < 0) + goto error; + +- switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { ++ switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { + case 0: + /* ignore (bypass ?) */ + break; + case 1: + /* 27 MHz */ +- state->m_osc_clock_freq = 27000; ++ state->m_oscClockFreq = 27000; + break; + case 2: + /* 20.25 MHz */ +- state->m_osc_clock_freq = 20250; ++ state->m_oscClockFreq = 20250; + break; + case 3: + /* 4 MHz */ +- state->m_osc_clock_freq = 20250; ++ state->m_oscClockFreq = 20250; + break; + default: +- pr_err("Clock Frequency is unknown\n"); ++ printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n"); + return -EINVAL; + } + /* + Determine device capabilities + Based on pinning v14 + */ +- status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo); ++ status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo); + if (status < 0) + goto error; + +- pr_info("status = 0x%08x\n", sio_top_jtagid_lo); ++printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo); + + /* driver 0.9.0 */ +- switch ((sio_top_jtagid_lo >> 29) & 0xF) { ++ switch ((sioTopJtagidLo >> 29) & 0xF) { + case 0: +- state->m_device_spin = DRXK_SPIN_A1; ++ state->m_deviceSpin = DRXK_SPIN_A1; + spin = "A1"; + break; + case 2: +- state->m_device_spin = DRXK_SPIN_A2; ++ state->m_deviceSpin = DRXK_SPIN_A2; + spin = "A2"; + break; + case 3: +- state->m_device_spin = DRXK_SPIN_A3; ++ state->m_deviceSpin = DRXK_SPIN_A3; + spin = "A3"; + break; + default: +- state->m_device_spin = DRXK_SPIN_UNKNOWN; ++ state->m_deviceSpin = DRXK_SPIN_UNKNOWN; + status = -EINVAL; +- pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF); ++ printk(KERN_ERR "drxk: Spin %d unknown\n", ++ (sioTopJtagidLo >> 29) & 0xF); + goto error2; + } +- switch ((sio_top_jtagid_lo >> 12) & 0xFF) { ++ switch ((sioTopJtagidLo >> 12) & 0xFF) { + case 0x13: + /* typeId = DRX3913K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = false; +- state->m_has_audio = false; +- state->m_has_dvbt = true; +- state->m_has_dvbc = true; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = false; +- state->m_has_gpio1 = false; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = false; ++ state->m_hasAudio = false; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = true; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = false; ++ state->m_hasGPIO1 = false; ++ state->m_hasIRQN = false; + break; + case 0x15: + /* typeId = DRX3915K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = false; +- state->m_has_dvbt = true; +- state->m_has_dvbc = false; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = false; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = false; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x16: + /* typeId = DRX3916K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = false; +- state->m_has_dvbt = true; +- state->m_has_dvbc = false; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = false; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = false; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x18: + /* typeId = DRX3918K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = true; +- state->m_has_dvbt = true; +- state->m_has_dvbc = false; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = true; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = false; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x21: + /* typeId = DRX3921K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = true; +- state->m_has_dvbt = true; +- state->m_has_dvbc = true; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = true; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = true; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x23: + /* typeId = DRX3923K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = true; +- state->m_has_dvbt = true; +- state->m_has_dvbc = true; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = true; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = true; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x25: + /* typeId = DRX3925K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = true; +- state->m_has_dvbt = true; +- state->m_has_dvbc = true; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = true; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = true; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + case 0x26: + /* typeId = DRX3926K_TYPE_ID */ +- state->m_has_lna = false; +- state->m_has_oob = false; +- state->m_has_atv = true; +- state->m_has_audio = false; +- state->m_has_dvbt = true; +- state->m_has_dvbc = true; +- state->m_has_sawsw = true; +- state->m_has_gpio2 = true; +- state->m_has_gpio1 = true; +- state->m_has_irqn = false; ++ state->m_hasLNA = false; ++ state->m_hasOOB = false; ++ state->m_hasATV = true; ++ state->m_hasAudio = false; ++ state->m_hasDVBT = true; ++ state->m_hasDVBC = true; ++ state->m_hasSAWSW = true; ++ state->m_hasGPIO2 = true; ++ state->m_hasGPIO1 = true; ++ state->m_hasIRQN = false; + break; + default: +- pr_err("DeviceID 0x%02x not supported\n", +- ((sio_top_jtagid_lo >> 12) & 0xFF)); ++ printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n", ++ ((sioTopJtagidLo >> 12) & 0xFF)); + status = -EINVAL; + goto error2; + } + +- pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", +- ((sio_top_jtagid_lo >> 12) & 0xFF), spin, +- state->m_osc_clock_freq / 1000, +- state->m_osc_clock_freq % 1000); ++ printk(KERN_INFO ++ "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", ++ ((sioTopJtagidLo >> 12) & 0xFF), spin, ++ state->m_oscClockFreq / 1000, ++ state->m_oscClockFreq % 1000); + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + error2: + return status; + } + +-static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) ++static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) + { + int status; + bool powerdown_cmd; +@@ -1021,37 +1093,37 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) + if (status < 0) + goto error; + if (cmd == SIO_HI_RA_RAM_CMD_RESET) +- usleep_range(1000, 2000); ++ msleep(1); + + powerdown_cmd = + (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) && +- ((state->m_hi_cfg_ctrl) & ++ ((state->m_HICfgCtrl) & + SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == + SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); +- if (!powerdown_cmd) { ++ if (powerdown_cmd == false) { + /* Wait until command rdy */ +- u32 retry_count = 0; +- u16 wait_cmd; ++ u32 retryCount = 0; ++ u16 waitCmd; + + do { +- usleep_range(1000, 2000); +- retry_count += 1; ++ msleep(1); ++ retryCount += 1; + status = read16(state, SIO_HI_RA_RAM_CMD__A, +- &wait_cmd); +- } while ((status < 0) && (retry_count < DRXK_MAX_RETRIES) +- && (wait_cmd != 0)); ++ &waitCmd); ++ } while ((status < 0) && (retryCount < DRXK_MAX_RETRIES) ++ && (waitCmd != 0)); + if (status < 0) + goto error; +- status = read16(state, SIO_HI_RA_RAM_RES__A, p_result); ++ status = read16(state, SIO_HI_RA_RAM_RES__A, pResult); + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static int hi_cfg_command(struct drxk_state *state) ++static int HI_CfgCommand(struct drxk_state *state) + { + int status; + +@@ -1059,77 +1131,70 @@ static int hi_cfg_command(struct drxk_state *state) + + mutex_lock(&state->mutex); + +- status = write16(state, SIO_HI_RA_RAM_PAR_6__A, +- state->m_hi_cfg_timeout); ++ status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout); + if (status < 0) + goto error; +- status = write16(state, SIO_HI_RA_RAM_PAR_5__A, +- state->m_hi_cfg_ctrl); ++ status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl); + if (status < 0) + goto error; +- status = write16(state, SIO_HI_RA_RAM_PAR_4__A, +- state->m_hi_cfg_wake_up_key); ++ status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey); + if (status < 0) + goto error; +- status = write16(state, SIO_HI_RA_RAM_PAR_3__A, +- state->m_hi_cfg_bridge_delay); ++ status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay); + if (status < 0) + goto error; +- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, +- state->m_hi_cfg_timing_div); ++ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv); + if (status < 0) + goto error; +- status = write16(state, SIO_HI_RA_RAM_PAR_1__A, +- SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); ++ status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + if (status < 0) + goto error; +- status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, NULL); ++ status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); + if (status < 0) + goto error; + +- state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; ++ state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + error: + mutex_unlock(&state->mutex); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int init_hi(struct drxk_state *state) ++static int InitHI(struct drxk_state *state) + { + dprintk(1, "\n"); + +- state->m_hi_cfg_wake_up_key = (state->demod_address << 1); +- state->m_hi_cfg_timeout = 0x96FF; ++ state->m_HICfgWakeUpKey = (state->demod_address << 1); ++ state->m_HICfgTimeout = 0x96FF; + /* port/bridge/power down ctrl */ +- state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; ++ state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + +- return hi_cfg_command(state); ++ return HI_CfgCommand(state); + } + +-static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) ++static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) + { + int status = -1; +- u16 sio_pdr_mclk_cfg = 0; +- u16 sio_pdr_mdx_cfg = 0; ++ u16 sioPdrMclkCfg = 0; ++ u16 sioPdrMdxCfg = 0; + u16 err_cfg = 0; + + dprintk(1, ": mpeg %s, %s mode\n", +- mpeg_enable ? "enable" : "disable", +- state->m_enable_parallel ? "parallel" : "serial"); ++ mpegEnable ? "enable" : "disable", ++ state->m_enableParallel ? "parallel" : "serial"); + + /* stop lock indicator process */ +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; + + /* MPEG TS pad configuration */ +- status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); ++ status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA); + if (status < 0) + goto error; + +- if (!mpeg_enable) { ++ if (mpegEnable == false) { + /* Set MPEG TS pads to inputmode */ + status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); + if (status < 0) +@@ -1169,19 +1234,19 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) + goto error; + } else { + /* Enable MPEG output */ +- sio_pdr_mdx_cfg = +- ((state->m_ts_data_strength << ++ sioPdrMdxCfg = ++ ((state->m_TSDataStrength << + SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); +- sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength << ++ sioPdrMclkCfg = ((state->m_TSClockkStrength << + SIO_PDR_MCLK_CFG_DRIVE__B) | + 0x0003); + +- status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; + + if (state->enable_merr_cfg) +- err_cfg = sio_pdr_mdx_cfg; ++ err_cfg = sioPdrMdxCfg; + + status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); + if (status < 0) +@@ -1190,38 +1255,31 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) + if (status < 0) + goto error; + +- if (state->m_enable_parallel) { +- /* parallel -> enable MD1 to MD7 */ +- status = write16(state, SIO_PDR_MD1_CFG__A, +- sio_pdr_mdx_cfg); ++ if (state->m_enableParallel == true) { ++ /* paralel -> enable MD1 to MD7 */ ++ status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD2_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD3_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD4_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD5_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD6_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD7_CFG__A, +- sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; + } else { +- sio_pdr_mdx_cfg = ((state->m_ts_data_strength << ++ sioPdrMdxCfg = ((state->m_TSDataStrength << + SIO_PDR_MD0_CFG_DRIVE__B) + | 0x0003); + /* serial -> disable MD1 to MD7 */ +@@ -1247,10 +1305,10 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) + if (status < 0) + goto error; + } +- status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg); ++ status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg); ++ status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; + } +@@ -1262,21 +1320,21 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) + status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int mpegts_disable(struct drxk_state *state) ++static int MPEGTSDisable(struct drxk_state *state) + { + dprintk(1, "\n"); + +- return mpegts_configure_pins(state, false); ++ return MPEGTSConfigurePins(state, false); + } + +-static int bl_chain_cmd(struct drxk_state *state, +- u16 rom_offset, u16 nr_of_elements, u32 time_out) ++static int BLChainCmd(struct drxk_state *state, ++ u16 romOffset, u16 nrOfElements, u32 timeOut) + { +- u16 bl_status = 0; ++ u16 blStatus = 0; + int status; + unsigned long end; + +@@ -1285,46 +1343,46 @@ static int bl_chain_cmd(struct drxk_state *state, + status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN); + if (status < 0) + goto error; +- status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset); ++ status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset); + if (status < 0) + goto error; +- status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements); ++ status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements); + if (status < 0) + goto error; + status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); + if (status < 0) + goto error; + +- end = jiffies + msecs_to_jiffies(time_out); ++ end = jiffies + msecs_to_jiffies(timeOut); + do { +- usleep_range(1000, 2000); +- status = read16(state, SIO_BL_STATUS__A, &bl_status); ++ msleep(1); ++ status = read16(state, SIO_BL_STATUS__A, &blStatus); + if (status < 0) + goto error; +- } while ((bl_status == 0x1) && ++ } while ((blStatus == 0x1) && + ((time_is_after_jiffies(end)))); + +- if (bl_status == 0x1) { +- pr_err("SIO not ready\n"); ++ if (blStatus == 0x1) { ++ printk(KERN_ERR "drxk: SIO not ready\n"); + status = -EINVAL; + goto error2; + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + error2: + mutex_unlock(&state->mutex); + return status; + } + + +-static int download_microcode(struct drxk_state *state, +- const u8 p_mc_image[], u32 length) ++static int DownloadMicrocode(struct drxk_state *state, ++ const u8 pMCImage[], u32 Length) + { +- const u8 *p_src = p_mc_image; +- u32 address; +- u16 n_blocks; +- u16 block_size; ++ const u8 *pSrc = pMCImage; ++ u32 Address; ++ u16 nBlocks; ++ u16 BlockSize; + u32 offset = 0; + u32 i; + int status = 0; +@@ -1334,131 +1392,130 @@ static int download_microcode(struct drxk_state *state, + /* down the drain (we don't care about MAGIC_WORD) */ + #if 0 + /* For future reference */ +- drain = (p_src[0] << 8) | p_src[1]; ++ Drain = (pSrc[0] << 8) | pSrc[1]; + #endif +- p_src += sizeof(u16); ++ pSrc += sizeof(u16); + offset += sizeof(u16); +- n_blocks = (p_src[0] << 8) | p_src[1]; +- p_src += sizeof(u16); ++ nBlocks = (pSrc[0] << 8) | pSrc[1]; ++ pSrc += sizeof(u16); + offset += sizeof(u16); + +- for (i = 0; i < n_blocks; i += 1) { +- address = (p_src[0] << 24) | (p_src[1] << 16) | +- (p_src[2] << 8) | p_src[3]; +- p_src += sizeof(u32); ++ for (i = 0; i < nBlocks; i += 1) { ++ Address = (pSrc[0] << 24) | (pSrc[1] << 16) | ++ (pSrc[2] << 8) | pSrc[3]; ++ pSrc += sizeof(u32); + offset += sizeof(u32); + +- block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16); +- p_src += sizeof(u16); ++ BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); ++ pSrc += sizeof(u16); + offset += sizeof(u16); + + #if 0 + /* For future reference */ +- flags = (p_src[0] << 8) | p_src[1]; ++ Flags = (pSrc[0] << 8) | pSrc[1]; + #endif +- p_src += sizeof(u16); ++ pSrc += sizeof(u16); + offset += sizeof(u16); + + #if 0 + /* For future reference */ +- block_crc = (p_src[0] << 8) | p_src[1]; ++ BlockCRC = (pSrc[0] << 8) | pSrc[1]; + #endif +- p_src += sizeof(u16); ++ pSrc += sizeof(u16); + offset += sizeof(u16); + +- if (offset + block_size > length) { +- pr_err("Firmware is corrupted.\n"); ++ if (offset + BlockSize > Length) { ++ printk(KERN_ERR "drxk: Firmware is corrupted.\n"); + return -EINVAL; + } + +- status = write_block(state, address, block_size, p_src); ++ status = write_block(state, Address, BlockSize, pSrc); + if (status < 0) { +- pr_err("Error %d while loading firmware\n", status); ++ printk(KERN_ERR "drxk: Error %d while loading firmware\n", status); + break; + } +- p_src += block_size; +- offset += block_size; ++ pSrc += BlockSize; ++ offset += BlockSize; + } + return status; + } + +-static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) ++static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable) + { + int status; + u16 data = 0; +- u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; +- u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; ++ u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; ++ u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; + unsigned long end; + + dprintk(1, "\n"); + +- if (!enable) { +- desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; +- desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; ++ if (enable == false) { ++ desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; ++ desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; + } + + status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); +- if (status >= 0 && data == desired_status) { ++ if (status >= 0 && data == desiredStatus) { + /* tokenring already has correct status */ + return status; + } + /* Disable/enable dvbt tokenring bridge */ +- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl); ++ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl); + + end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); + do { + status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); +- if ((status >= 0 && data == desired_status) +- || time_is_after_jiffies(end)) ++ if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end)) + break; +- usleep_range(1000, 2000); ++ msleep(1); + } while (1); +- if (data != desired_status) { +- pr_err("SIO not ready\n"); ++ if (data != desiredStatus) { ++ printk(KERN_ERR "drxk: SIO not ready\n"); + return -EINVAL; + } + return status; + } + +-static int mpegts_stop(struct drxk_state *state) ++static int MPEGTSStop(struct drxk_state *state) + { + int status = 0; +- u16 fec_oc_snc_mode = 0; +- u16 fec_oc_ipr_mode = 0; ++ u16 fecOcSncMode = 0; ++ u16 fecOcIprMode = 0; + + dprintk(1, "\n"); + +- /* Graceful shutdown (byte boundaries) */ +- status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); ++ /* Gracefull shutdown (byte boundaries) */ ++ status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + if (status < 0) + goto error; +- fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M; +- status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); ++ fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M; ++ status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + if (status < 0) + goto error; + + /* Suppress MCLK during absence of data */ +- status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode); ++ status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode); + if (status < 0) + goto error; +- fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; +- status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode); ++ fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; ++ status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode); + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + + static int scu_command(struct drxk_state *state, +- u16 cmd, u8 parameter_len, +- u16 *parameter, u8 result_len, u16 *result) ++ u16 cmd, u8 parameterLen, ++ u16 *parameter, u8 resultLen, u16 *result) + { + #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15 + #error DRXK register mapping no longer compatible with this routine! + #endif +- u16 cur_cmd = 0; ++ u16 curCmd = 0; + int status = -EINVAL; + unsigned long end; + u8 buffer[34]; +@@ -1468,9 +1525,9 @@ static int scu_command(struct drxk_state *state, + + dprintk(1, "\n"); + +- if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) || +- ((result_len > 0) && (result == NULL))) { +- pr_err("Error %d on %s\n", status, __func__); ++ if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) || ++ ((resultLen > 0) && (result == NULL))) { ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -1478,7 +1535,7 @@ static int scu_command(struct drxk_state *state, + + /* assume that the command register is ready + since it is checked afterwards */ +- for (ii = parameter_len - 1; ii >= 0; ii -= 1) { ++ for (ii = parameterLen - 1; ii >= 0; ii -= 1) { + buffer[cnt++] = (parameter[ii] & 0xFF); + buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF); + } +@@ -1486,28 +1543,27 @@ static int scu_command(struct drxk_state *state, + buffer[cnt++] = ((cmd >> 8) & 0xFF); + + write_block(state, SCU_RAM_PARAM_0__A - +- (parameter_len - 1), cnt, buffer); ++ (parameterLen - 1), cnt, buffer); + /* Wait until SCU has processed command */ + end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); + do { +- usleep_range(1000, 2000); +- status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); ++ msleep(1); ++ status = read16(state, SCU_RAM_COMMAND__A, &curCmd); + if (status < 0) + goto error; +- } while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); +- if (cur_cmd != DRX_SCU_READY) { +- pr_err("SCU not ready\n"); ++ } while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); ++ if (curCmd != DRX_SCU_READY) { ++ printk(KERN_ERR "drxk: SCU not ready\n"); + status = -EIO; + goto error2; + } + /* read results */ +- if ((result_len > 0) && (result != NULL)) { ++ if ((resultLen > 0) && (result != NULL)) { + s16 err; + int ii; + +- for (ii = result_len - 1; ii >= 0; ii -= 1) { +- status = read16(state, SCU_RAM_PARAM_0__A - ii, +- &result[ii]); ++ for (ii = resultLen - 1; ii >= 0; ii -= 1) { ++ status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]); + if (status < 0) + goto error; + } +@@ -1535,7 +1591,7 @@ static int scu_command(struct drxk_state *state, + sprintf(errname, "ERROR: %d\n", err); + p = errname; + } +- pr_err("%s while sending cmd 0x%04x with params:", p, cmd); ++ printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd); + print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt); + status = -EINVAL; + goto error2; +@@ -1543,13 +1599,13 @@ static int scu_command(struct drxk_state *state, + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + error2: + mutex_unlock(&state->mutex); + return status; + } + +-static int set_iqm_af(struct drxk_state *state, bool active) ++static int SetIqmAf(struct drxk_state *state, bool active) + { + u16 data = 0; + int status; +@@ -1579,14 +1635,14 @@ static int set_iqm_af(struct drxk_state *state, bool active) + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) ++static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) + { + int status = 0; +- u16 sio_cc_pwd_mode = 0; ++ u16 sioCcPwdMode = 0; + + dprintk(1, "\n"); + +@@ -1596,19 +1652,19 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) + + switch (*mode) { + case DRX_POWER_UP: +- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; ++ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE; + break; + case DRXK_POWER_DOWN_OFDM: +- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM; ++ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM; + break; + case DRXK_POWER_DOWN_CORE: +- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; ++ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK; + break; + case DRXK_POWER_DOWN_PLL: +- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; ++ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL; + break; + case DRX_POWER_DOWN: +- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; ++ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC; + break; + default: + /* Unknow sleep mode */ +@@ -1616,15 +1672,15 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) + } + + /* If already in requested power mode, do nothing */ +- if (state->m_current_power_mode == *mode) ++ if (state->m_currentPowerMode == *mode) + return 0; + + /* For next steps make sure to start from DRX_POWER_UP mode */ +- if (state->m_current_power_mode != DRX_POWER_UP) { +- status = power_up_device(state); ++ if (state->m_currentPowerMode != DRX_POWER_UP) { ++ status = PowerUpDevice(state); + if (status < 0) + goto error; +- status = dvbt_enable_ofdm_token_ring(state, true); ++ status = DVBTEnableOFDMTokenRing(state, true); + if (status < 0) + goto error; + } +@@ -1641,31 +1697,31 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) + /* Power down device */ + /* stop all comm_exec */ + /* Stop and power down previous standard */ +- switch (state->m_operation_mode) { ++ switch (state->m_OperationMode) { + case OM_DVBT: +- status = mpegts_stop(state); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = power_down_dvbt(state, false); ++ status = PowerDownDVBT(state, false); + if (status < 0) + goto error; + break; + case OM_QAM_ITU_A: + case OM_QAM_ITU_C: +- status = mpegts_stop(state); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = power_down_qam(state); ++ status = PowerDownQAM(state); + if (status < 0) + goto error; + break; + default: + break; + } +- status = dvbt_enable_ofdm_token_ring(state, false); ++ status = DVBTEnableOFDMTokenRing(state, false); + if (status < 0) + goto error; +- status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode); ++ status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode); + if (status < 0) + goto error; + status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); +@@ -1673,26 +1729,26 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) + goto error; + + if (*mode != DRXK_POWER_DOWN_OFDM) { +- state->m_hi_cfg_ctrl |= ++ state->m_HICfgCtrl |= + SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; +- status = hi_cfg_command(state); ++ status = HI_CfgCommand(state); + if (status < 0) + goto error; + } + } +- state->m_current_power_mode = *mode; ++ state->m_currentPowerMode = *mode; + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) ++static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) + { +- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; +- u16 cmd_result = 0; ++ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; ++ u16 cmdResult = 0; + u16 data = 0; + int status; + +@@ -1703,17 +1759,11 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) + goto error; + if (data == SCU_COMM_EXEC_ACTIVE) { + /* Send OFDM stop command */ +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + /* Send OFDM reset command */ +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + } +@@ -1730,24 +1780,24 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) + goto error; + + /* powerdown AFE */ +- status = set_iqm_af(state, false); ++ status = SetIqmAf(state, false); + if (status < 0) + goto error; + + /* powerdown to OFDM mode */ +- if (set_power_mode) { +- status = ctrl_power_mode(state, &power_mode); ++ if (setPowerMode) { ++ status = CtrlPowerMode(state, &powerMode); + if (status < 0) + goto error; + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int setoperation_mode(struct drxk_state *state, +- enum operation_mode o_mode) ++static int SetOperationMode(struct drxk_state *state, ++ enum OperationMode oMode) + { + int status = 0; + +@@ -1759,37 +1809,36 @@ static int setoperation_mode(struct drxk_state *state, + */ + + /* disable HW lock indicator */ +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; + + /* Device is already at the required mode */ +- if (state->m_operation_mode == o_mode) ++ if (state->m_OperationMode == oMode) + return 0; + +- switch (state->m_operation_mode) { ++ switch (state->m_OperationMode) { + /* OM_NONE was added for start up */ + case OM_NONE: + break; + case OM_DVBT: +- status = mpegts_stop(state); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = power_down_dvbt(state, true); ++ status = PowerDownDVBT(state, true); + if (status < 0) + goto error; +- state->m_operation_mode = OM_NONE; ++ state->m_OperationMode = OM_NONE; + break; + case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_C: +- status = mpegts_stop(state); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = power_down_qam(state); ++ status = PowerDownQAM(state); + if (status < 0) + goto error; +- state->m_operation_mode = OM_NONE; ++ state->m_OperationMode = OM_NONE; + break; + case OM_QAM_ITU_B: + default: +@@ -1800,20 +1849,20 @@ static int setoperation_mode(struct drxk_state *state, + /* + Power up new standard + */ +- switch (o_mode) { ++ switch (oMode) { + case OM_DVBT: + dprintk(1, ": DVB-T\n"); +- state->m_operation_mode = o_mode; +- status = set_dvbt_standard(state, o_mode); ++ state->m_OperationMode = oMode; ++ status = SetDVBTStandard(state, oMode); + if (status < 0) + goto error; + break; + case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_C: + dprintk(1, ": DVB-C Annex %c\n", +- (state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C'); +- state->m_operation_mode = o_mode; +- status = set_qam_standard(state, o_mode); ++ (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C'); ++ state->m_OperationMode = oMode; ++ status = SetQAMStandard(state, oMode); + if (status < 0) + goto error; + break; +@@ -1823,121 +1872,123 @@ static int setoperation_mode(struct drxk_state *state, + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int start(struct drxk_state *state, s32 offset_freq, +- s32 intermediate_frequency) ++static int Start(struct drxk_state *state, s32 offsetFreq, ++ s32 IntermediateFrequency) + { + int status = -EINVAL; + +- u16 i_freqk_hz; +- s32 offsetk_hz = offset_freq / 1000; ++ u16 IFreqkHz; ++ s32 OffsetkHz = offsetFreq / 1000; + + dprintk(1, "\n"); +- if (state->m_drxk_state != DRXK_STOPPED && +- state->m_drxk_state != DRXK_DTV_STARTED) ++ if (state->m_DrxkState != DRXK_STOPPED && ++ state->m_DrxkState != DRXK_DTV_STARTED) + goto error; + +- state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON); ++ state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON); + +- if (intermediate_frequency < 0) { +- state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect; +- intermediate_frequency = -intermediate_frequency; ++ if (IntermediateFrequency < 0) { ++ state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect; ++ IntermediateFrequency = -IntermediateFrequency; + } + +- switch (state->m_operation_mode) { ++ switch (state->m_OperationMode) { + case OM_QAM_ITU_A: + case OM_QAM_ITU_C: +- i_freqk_hz = (intermediate_frequency / 1000); +- status = set_qam(state, i_freqk_hz, offsetk_hz); ++ IFreqkHz = (IntermediateFrequency / 1000); ++ status = SetQAM(state, IFreqkHz, OffsetkHz); + if (status < 0) + goto error; +- state->m_drxk_state = DRXK_DTV_STARTED; ++ state->m_DrxkState = DRXK_DTV_STARTED; + break; + case OM_DVBT: +- i_freqk_hz = (intermediate_frequency / 1000); +- status = mpegts_stop(state); ++ IFreqkHz = (IntermediateFrequency / 1000); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = set_dvbt(state, i_freqk_hz, offsetk_hz); ++ status = SetDVBT(state, IFreqkHz, OffsetkHz); + if (status < 0) + goto error; +- status = dvbt_start(state); ++ status = DVBTStart(state); + if (status < 0) + goto error; +- state->m_drxk_state = DRXK_DTV_STARTED; ++ state->m_DrxkState = DRXK_DTV_STARTED; + break; + default: + break; + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int shut_down(struct drxk_state *state) ++static int ShutDown(struct drxk_state *state) + { + dprintk(1, "\n"); + +- mpegts_stop(state); ++ MPEGTSStop(state); + return 0; + } + +-static int get_lock_status(struct drxk_state *state, u32 *p_lock_status) ++static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus, ++ u32 Time) + { + int status = -EINVAL; + + dprintk(1, "\n"); + +- if (p_lock_status == NULL) ++ if (pLockStatus == NULL) + goto error; + +- *p_lock_status = NOT_LOCKED; ++ *pLockStatus = NOT_LOCKED; + + /* define the SCU command code */ +- switch (state->m_operation_mode) { ++ switch (state->m_OperationMode) { + case OM_QAM_ITU_A: + case OM_QAM_ITU_B: + case OM_QAM_ITU_C: +- status = get_qam_lock_status(state, p_lock_status); ++ status = GetQAMLockStatus(state, pLockStatus); + break; + case OM_DVBT: +- status = get_dvbt_lock_status(state, p_lock_status); ++ status = GetDVBTLockStatus(state, pLockStatus); + break; + default: ++ status = 0; + break; + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int mpegts_start(struct drxk_state *state) ++static int MPEGTSStart(struct drxk_state *state) + { + int status; + +- u16 fec_oc_snc_mode = 0; ++ u16 fecOcSncMode = 0; + + /* Allow OC to sync again */ +- status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); ++ status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + if (status < 0) + goto error; +- fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; +- status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); ++ fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; ++ status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + if (status < 0) + goto error; + status = write16(state, FEC_OC_SNC_UNLOCK__A, 1); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int mpegts_dto_init(struct drxk_state *state) ++static int MPEGTSDtoInit(struct drxk_state *state) + { + int status; + +@@ -1979,68 +2030,68 @@ static int mpegts_dto_init(struct drxk_state *state) + status = write16(state, FEC_OC_SNC_HWM__A, 12); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static int mpegts_dto_setup(struct drxk_state *state, +- enum operation_mode o_mode) ++static int MPEGTSDtoSetup(struct drxk_state *state, ++ enum OperationMode oMode) + { + int status; + +- u16 fec_oc_reg_mode = 0; /* FEC_OC_MODE register value */ +- u16 fec_oc_reg_ipr_mode = 0; /* FEC_OC_IPR_MODE register value */ +- u16 fec_oc_dto_mode = 0; /* FEC_OC_IPR_INVERT register value */ +- u16 fec_oc_fct_mode = 0; /* FEC_OC_IPR_INVERT register value */ +- u16 fec_oc_dto_period = 2; /* FEC_OC_IPR_INVERT register value */ +- u16 fec_oc_dto_burst_len = 188; /* FEC_OC_IPR_INVERT register value */ +- u32 fec_oc_rcn_ctl_rate = 0; /* FEC_OC_IPR_INVERT register value */ +- u16 fec_oc_tmd_mode = 0; +- u16 fec_oc_tmd_int_upd_rate = 0; +- u32 max_bit_rate = 0; +- bool static_clk = false; ++ u16 fecOcRegMode = 0; /* FEC_OC_MODE register value */ ++ u16 fecOcRegIprMode = 0; /* FEC_OC_IPR_MODE register value */ ++ u16 fecOcDtoMode = 0; /* FEC_OC_IPR_INVERT register value */ ++ u16 fecOcFctMode = 0; /* FEC_OC_IPR_INVERT register value */ ++ u16 fecOcDtoPeriod = 2; /* FEC_OC_IPR_INVERT register value */ ++ u16 fecOcDtoBurstLen = 188; /* FEC_OC_IPR_INVERT register value */ ++ u32 fecOcRcnCtlRate = 0; /* FEC_OC_IPR_INVERT register value */ ++ u16 fecOcTmdMode = 0; ++ u16 fecOcTmdIntUpdRate = 0; ++ u32 maxBitRate = 0; ++ bool staticCLK = false; + + dprintk(1, "\n"); + + /* Check insertion of the Reed-Solomon parity bytes */ +- status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode); ++ status = read16(state, FEC_OC_MODE__A, &fecOcRegMode); + if (status < 0) + goto error; +- status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode); ++ status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode); + if (status < 0) + goto error; +- fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); +- fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); +- if (state->m_insert_rs_byte) { ++ fecOcRegMode &= (~FEC_OC_MODE_PARITY__M); ++ fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); ++ if (state->m_insertRSByte == true) { + /* enable parity symbol forward */ +- fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; ++ fecOcRegMode |= FEC_OC_MODE_PARITY__M; + /* MVAL disable during parity bytes */ +- fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; ++ fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; + /* TS burst length to 204 */ +- fec_oc_dto_burst_len = 204; ++ fecOcDtoBurstLen = 204; + } + +- /* Check serial or parallel output */ +- fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); +- if (!state->m_enable_parallel) { ++ /* Check serial or parrallel output */ ++ fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); ++ if (state->m_enableParallel == false) { + /* MPEG data output is serial -> set ipr_mode[0] */ +- fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; ++ fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M; + } + +- switch (o_mode) { ++ switch (oMode) { + case OM_DVBT: +- max_bit_rate = state->m_dvbt_bitrate; +- fec_oc_tmd_mode = 3; +- fec_oc_rcn_ctl_rate = 0xC00000; +- static_clk = state->m_dvbt_static_clk; ++ maxBitRate = state->m_DVBTBitrate; ++ fecOcTmdMode = 3; ++ fecOcRcnCtlRate = 0xC00000; ++ staticCLK = state->m_DVBTStaticCLK; + break; + case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_C: +- fec_oc_tmd_mode = 0x0004; +- fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */ +- max_bit_rate = state->m_dvbc_bitrate; +- static_clk = state->m_dvbc_static_clk; ++ fecOcTmdMode = 0x0004; ++ fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ ++ maxBitRate = state->m_DVBCBitrate; ++ staticCLK = state->m_DVBCStaticCLK; + break; + default: + status = -EINVAL; +@@ -2049,84 +2100,83 @@ static int mpegts_dto_setup(struct drxk_state *state, + goto error; + + /* Configure DTO's */ +- if (static_clk) { +- u32 bit_rate = 0; ++ if (staticCLK) { ++ u32 bitRate = 0; + + /* Rational DTO for MCLK source (static MCLK rate), + Dynamic DTO for optimal grouping + (avoid intra-packet gaps), + DTO offset enable to sync TS burst with MSTRT */ +- fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M | ++ fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M | + FEC_OC_DTO_MODE_OFFSET_ENABLE__M); +- fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M | ++ fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M | + FEC_OC_FCT_MODE_VIRT_ENA__M); + + /* Check user defined bitrate */ +- bit_rate = max_bit_rate; +- if (bit_rate > 75900000UL) { /* max is 75.9 Mb/s */ +- bit_rate = 75900000UL; ++ bitRate = maxBitRate; ++ if (bitRate > 75900000UL) { /* max is 75.9 Mb/s */ ++ bitRate = 75900000UL; + } + /* Rational DTO period: + dto_period = (Fsys / bitrate) - 2 + +- result should be floored, ++ Result should be floored, + to make sure >= requested bitrate + */ +- fec_oc_dto_period = (u16) (((state->m_sys_clock_freq) +- * 1000) / bit_rate); +- if (fec_oc_dto_period <= 2) +- fec_oc_dto_period = 0; ++ fecOcDtoPeriod = (u16) (((state->m_sysClockFreq) ++ * 1000) / bitRate); ++ if (fecOcDtoPeriod <= 2) ++ fecOcDtoPeriod = 0; + else +- fec_oc_dto_period -= 2; +- fec_oc_tmd_int_upd_rate = 8; ++ fecOcDtoPeriod -= 2; ++ fecOcTmdIntUpdRate = 8; + } else { +- /* (commonAttr->static_clk == false) => dynamic mode */ +- fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M; +- fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE; +- fec_oc_tmd_int_upd_rate = 5; ++ /* (commonAttr->staticCLK == false) => dynamic mode */ ++ fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M; ++ fecOcFctMode = FEC_OC_FCT_MODE__PRE; ++ fecOcTmdIntUpdRate = 5; + } + + /* Write appropriate registers with requested configuration */ +- status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len); ++ status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period); ++ status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode); ++ status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode); ++ status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode); ++ status = write16(state, FEC_OC_MODE__A, fecOcRegMode); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode); ++ status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode); + if (status < 0) + goto error; + + /* Rate integration settings */ +- status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate); ++ status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, +- fec_oc_tmd_int_upd_rate); ++ status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); ++ status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int mpegts_configure_polarity(struct drxk_state *state) ++static int MPEGTSConfigurePolarity(struct drxk_state *state) + { +- u16 fec_oc_reg_ipr_invert = 0; ++ u16 fecOcRegIprInvert = 0; + + /* Data mask for the output data byte */ +- u16 invert_data_mask = ++ u16 InvertDataMask = + FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | + FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | + FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | +@@ -2135,40 +2185,40 @@ static int mpegts_configure_polarity(struct drxk_state *state) + dprintk(1, "\n"); + + /* Control selective inversion of output bits */ +- fec_oc_reg_ipr_invert &= (~(invert_data_mask)); +- if (state->m_invert_data) +- fec_oc_reg_ipr_invert |= invert_data_mask; +- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); +- if (state->m_invert_err) +- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; +- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); +- if (state->m_invert_str) +- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; +- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); +- if (state->m_invert_val) +- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; +- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); +- if (state->m_invert_clk) +- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; +- +- return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); ++ fecOcRegIprInvert &= (~(InvertDataMask)); ++ if (state->m_invertDATA == true) ++ fecOcRegIprInvert |= InvertDataMask; ++ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M)); ++ if (state->m_invertERR == true) ++ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M; ++ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); ++ if (state->m_invertSTR == true) ++ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M; ++ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); ++ if (state->m_invertVAL == true) ++ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M; ++ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); ++ if (state->m_invertCLK == true) ++ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M; ++ ++ return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert); + } + + #define SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000 + +-static int set_agc_rf(struct drxk_state *state, +- struct s_cfg_agc *p_agc_cfg, bool is_dtv) ++static int SetAgcRf(struct drxk_state *state, ++ struct SCfgAgc *pAgcCfg, bool isDTV) + { + int status = -EINVAL; + u16 data = 0; +- struct s_cfg_agc *p_if_agc_settings; ++ struct SCfgAgc *pIfAgcSettings; + + dprintk(1, "\n"); + +- if (p_agc_cfg == NULL) ++ if (pAgcCfg == NULL) + goto error; + +- switch (p_agc_cfg->ctrl_mode) { ++ switch (pAgcCfg->ctrlMode) { + case DRXK_AGC_CTRL_AUTO: + /* Enable RF AGC DAC */ + status = read16(state, IQM_AF_STDBY__A, &data); +@@ -2186,7 +2236,7 @@ static int set_agc_rf(struct drxk_state *state, + data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; + + /* Polarity */ +- if (state->m_rf_agc_pol) ++ if (state->m_RfAgcPol) + data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; + else + data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; +@@ -2200,7 +2250,7 @@ static int set_agc_rf(struct drxk_state *state, + goto error; + + data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; +- data |= (~(p_agc_cfg->speed << ++ data |= (~(pAgcCfg->speed << + SCU_RAM_AGC_KI_RED_RAGC_RED__B) + & SCU_RAM_AGC_KI_RED_RAGC_RED__M); + +@@ -2208,35 +2258,30 @@ static int set_agc_rf(struct drxk_state *state, + if (status < 0) + goto error; + +- if (is_dvbt(state)) +- p_if_agc_settings = &state->m_dvbt_if_agc_cfg; +- else if (is_qam(state)) +- p_if_agc_settings = &state->m_qam_if_agc_cfg; ++ if (IsDVBT(state)) ++ pIfAgcSettings = &state->m_dvbtIfAgcCfg; ++ else if (IsQAM(state)) ++ pIfAgcSettings = &state->m_qamIfAgcCfg; + else +- p_if_agc_settings = &state->m_atv_if_agc_cfg; +- if (p_if_agc_settings == NULL) { ++ pIfAgcSettings = &state->m_atvIfAgcCfg; ++ if (pIfAgcSettings == NULL) { + status = -EINVAL; + goto error; + } + + /* Set TOP, only if IF-AGC is in AUTO mode */ +- if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) { +- status = write16(state, +- SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, +- p_agc_cfg->top); ++ if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO) ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top); + if (status < 0) + goto error; +- } + + /* Cut-Off current */ +- status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, +- p_agc_cfg->cut_off_current); ++ status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent); + if (status < 0) + goto error; + + /* Max. output level */ +- status = write16(state, SCU_RAM_AGC_RF_MAX__A, +- p_agc_cfg->max_output_level); ++ status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel); + if (status < 0) + goto error; + +@@ -2257,7 +2302,7 @@ static int set_agc_rf(struct drxk_state *state, + if (status < 0) + goto error; + data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; +- if (state->m_rf_agc_pol) ++ if (state->m_RfAgcPol) + data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; + else + data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; +@@ -2271,8 +2316,7 @@ static int set_agc_rf(struct drxk_state *state, + goto error; + + /* Write value to output pin */ +- status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, +- p_agc_cfg->output_level); ++ status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel); + if (status < 0) + goto error; + break; +@@ -2303,22 +2347,22 @@ static int set_agc_rf(struct drxk_state *state, + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + + #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000 + +-static int set_agc_if(struct drxk_state *state, +- struct s_cfg_agc *p_agc_cfg, bool is_dtv) ++static int SetAgcIf(struct drxk_state *state, ++ struct SCfgAgc *pAgcCfg, bool isDTV) + { + u16 data = 0; + int status = 0; +- struct s_cfg_agc *p_rf_agc_settings; ++ struct SCfgAgc *pRfAgcSettings; + + dprintk(1, "\n"); + +- switch (p_agc_cfg->ctrl_mode) { ++ switch (pAgcCfg->ctrlMode) { + case DRXK_AGC_CTRL_AUTO: + + /* Enable IF AGC DAC */ +@@ -2338,7 +2382,7 @@ static int set_agc_if(struct drxk_state *state, + data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; + + /* Polarity */ +- if (state->m_if_agc_pol) ++ if (state->m_IfAgcPol) + data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; + else + data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; +@@ -2351,7 +2395,7 @@ static int set_agc_if(struct drxk_state *state, + if (status < 0) + goto error; + data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; +- data |= (~(p_agc_cfg->speed << ++ data |= (~(pAgcCfg->speed << + SCU_RAM_AGC_KI_RED_IAGC_RED__B) + & SCU_RAM_AGC_KI_RED_IAGC_RED__M); + +@@ -2359,15 +2403,14 @@ static int set_agc_if(struct drxk_state *state, + if (status < 0) + goto error; + +- if (is_qam(state)) +- p_rf_agc_settings = &state->m_qam_rf_agc_cfg; ++ if (IsQAM(state)) ++ pRfAgcSettings = &state->m_qamRfAgcCfg; + else +- p_rf_agc_settings = &state->m_atv_rf_agc_cfg; +- if (p_rf_agc_settings == NULL) ++ pRfAgcSettings = &state->m_atvRfAgcCfg; ++ if (pRfAgcSettings == NULL) + return -1; + /* Restore TOP */ +- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, +- p_rf_agc_settings->top); ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top); + if (status < 0) + goto error; + break; +@@ -2391,7 +2434,7 @@ static int set_agc_if(struct drxk_state *state, + data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; + + /* Polarity */ +- if (state->m_if_agc_pol) ++ if (state->m_IfAgcPol) + data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; + else + data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; +@@ -2400,8 +2443,7 @@ static int set_agc_if(struct drxk_state *state, + goto error; + + /* Write value to output pin */ +- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, +- p_agc_cfg->output_level); ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel); + if (status < 0) + goto error; + break; +@@ -2426,181 +2468,207 @@ static int set_agc_if(struct drxk_state *state, + if (status < 0) + goto error; + break; +- } /* switch (agcSettingsIf->ctrl_mode) */ ++ } /* switch (agcSettingsIf->ctrlMode) */ + + /* always set the top to support + configurations without if-loop */ +- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top); ++ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int get_qam_signal_to_noise(struct drxk_state *state, +- s32 *p_signal_to_noise) ++static int ReadIFAgc(struct drxk_state *state, u32 *pValue) ++{ ++ u16 agcDacLvl; ++ int status; ++ u16 Level = 0; ++ ++ dprintk(1, "\n"); ++ ++ status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl); ++ if (status < 0) { ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); ++ return status; ++ } ++ ++ *pValue = 0; ++ ++ if (agcDacLvl > DRXK_AGC_DAC_OFFSET) ++ Level = agcDacLvl - DRXK_AGC_DAC_OFFSET; ++ if (Level < 14000) ++ *pValue = (14000 - Level) / 4; ++ else ++ *pValue = 0; ++ ++ return status; ++} ++ ++static int GetQAMSignalToNoise(struct drxk_state *state, ++ s32 *pSignalToNoise) + { + int status = 0; +- u16 qam_sl_err_power = 0; /* accum. error between ++ u16 qamSlErrPower = 0; /* accum. error between + raw and sliced symbols */ +- u32 qam_sl_sig_power = 0; /* used for MER, depends of ++ u32 qamSlSigPower = 0; /* used for MER, depends of + QAM modulation */ +- u32 qam_sl_mer = 0; /* QAM MER */ ++ u32 qamSlMer = 0; /* QAM MER */ + + dprintk(1, "\n"); + + /* MER calculation */ + + /* get the register value needed for MER */ +- status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); ++ status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower); + if (status < 0) { +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return -EINVAL; + } + + switch (state->props.modulation) { + case QAM_16: +- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; ++ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; + break; + case QAM_32: +- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; ++ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; + break; + case QAM_64: +- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; ++ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; + break; + case QAM_128: +- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; ++ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; + break; + default: + case QAM_256: +- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; ++ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; + break; + } + +- if (qam_sl_err_power > 0) { +- qam_sl_mer = log10times100(qam_sl_sig_power) - +- log10times100((u32) qam_sl_err_power); ++ if (qamSlErrPower > 0) { ++ qamSlMer = Log10Times100(qamSlSigPower) - ++ Log10Times100((u32) qamSlErrPower); + } +- *p_signal_to_noise = qam_sl_mer; ++ *pSignalToNoise = qamSlMer; + + return status; + } + +-static int get_dvbt_signal_to_noise(struct drxk_state *state, +- s32 *p_signal_to_noise) ++static int GetDVBTSignalToNoise(struct drxk_state *state, ++ s32 *pSignalToNoise) + { + int status; +- u16 reg_data = 0; +- u32 eq_reg_td_sqr_err_i = 0; +- u32 eq_reg_td_sqr_err_q = 0; +- u16 eq_reg_td_sqr_err_exp = 0; +- u16 eq_reg_td_tps_pwr_ofs = 0; +- u16 eq_reg_td_req_smb_cnt = 0; +- u32 tps_cnt = 0; +- u32 sqr_err_iq = 0; ++ u16 regData = 0; ++ u32 EqRegTdSqrErrI = 0; ++ u32 EqRegTdSqrErrQ = 0; ++ u16 EqRegTdSqrErrExp = 0; ++ u16 EqRegTdTpsPwrOfs = 0; ++ u16 EqRegTdReqSmbCnt = 0; ++ u32 tpsCnt = 0; ++ u32 SqrErrIQ = 0; + u32 a = 0; + u32 b = 0; + u32 c = 0; +- u32 i_mer = 0; +- u16 transmission_params = 0; ++ u32 iMER = 0; ++ u16 transmissionParams = 0; + + dprintk(1, "\n"); + +- status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, +- &eq_reg_td_tps_pwr_ofs); ++ status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs); + if (status < 0) + goto error; +- status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, +- &eq_reg_td_req_smb_cnt); ++ status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt); + if (status < 0) + goto error; +- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, +- &eq_reg_td_sqr_err_exp); ++ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp); + if (status < 0) + goto error; +- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, +- ®_data); ++ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®Data); + if (status < 0) + goto error; + /* Extend SQR_ERR_I operational range */ +- eq_reg_td_sqr_err_i = (u32) reg_data; +- if ((eq_reg_td_sqr_err_exp > 11) && +- (eq_reg_td_sqr_err_i < 0x00000FFFUL)) { +- eq_reg_td_sqr_err_i += 0x00010000UL; ++ EqRegTdSqrErrI = (u32) regData; ++ if ((EqRegTdSqrErrExp > 11) && ++ (EqRegTdSqrErrI < 0x00000FFFUL)) { ++ EqRegTdSqrErrI += 0x00010000UL; + } +- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®_data); ++ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®Data); + if (status < 0) + goto error; + /* Extend SQR_ERR_Q operational range */ +- eq_reg_td_sqr_err_q = (u32) reg_data; +- if ((eq_reg_td_sqr_err_exp > 11) && +- (eq_reg_td_sqr_err_q < 0x00000FFFUL)) +- eq_reg_td_sqr_err_q += 0x00010000UL; ++ EqRegTdSqrErrQ = (u32) regData; ++ if ((EqRegTdSqrErrExp > 11) && ++ (EqRegTdSqrErrQ < 0x00000FFFUL)) ++ EqRegTdSqrErrQ += 0x00010000UL; + +- status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, +- &transmission_params); ++ status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams); + if (status < 0) + goto error; + + /* Check input data for MER */ + + /* MER calculation (in 0.1 dB) without math.h */ +- if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0)) +- i_mer = 0; +- else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) { ++ if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0)) ++ iMER = 0; ++ else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) { + /* No error at all, this must be the HW reset value + * Apparently no first measurement yet + * Set MER to 0.0 */ +- i_mer = 0; ++ iMER = 0; + } else { +- sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) << +- eq_reg_td_sqr_err_exp; +- if ((transmission_params & ++ SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) << ++ EqRegTdSqrErrExp; ++ if ((transmissionParams & + OFDM_SC_RA_RAM_OP_PARAM_MODE__M) + == OFDM_SC_RA_RAM_OP_PARAM_MODE_2K) +- tps_cnt = 17; ++ tpsCnt = 17; + else +- tps_cnt = 68; ++ tpsCnt = 68; + + /* IMER = 100 * log10 (x) +- where x = (eq_reg_td_tps_pwr_ofs^2 * +- eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq ++ where x = (EqRegTdTpsPwrOfs^2 * ++ EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ + + => IMER = a + b -c +- where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2) +- b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt) +- c = 100 * log10 (sqr_err_iq) ++ where a = 100 * log10 (EqRegTdTpsPwrOfs^2) ++ b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt) ++ c = 100 * log10 (SqrErrIQ) + */ + + /* log(x) x = 9bits * 9bits->18 bits */ +- a = log10times100(eq_reg_td_tps_pwr_ofs * +- eq_reg_td_tps_pwr_ofs); ++ a = Log10Times100(EqRegTdTpsPwrOfs * ++ EqRegTdTpsPwrOfs); + /* log(x) x = 16bits * 7bits->23 bits */ +- b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt); ++ b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt); + /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ +- c = log10times100(sqr_err_iq); ++ c = Log10Times100(SqrErrIQ); + +- i_mer = a + b - c; ++ iMER = a + b; ++ /* No negative MER, clip to zero */ ++ if (iMER > c) ++ iMER -= c; ++ else ++ iMER = 0; + } +- *p_signal_to_noise = i_mer; ++ *pSignalToNoise = iMER; + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) ++static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) + { + dprintk(1, "\n"); + +- *p_signal_to_noise = 0; +- switch (state->m_operation_mode) { ++ *pSignalToNoise = 0; ++ switch (state->m_OperationMode) { + case OM_DVBT: +- return get_dvbt_signal_to_noise(state, p_signal_to_noise); ++ return GetDVBTSignalToNoise(state, pSignalToNoise); + case OM_QAM_ITU_A: + case OM_QAM_ITU_C: +- return get_qam_signal_to_noise(state, p_signal_to_noise); ++ return GetQAMSignalToNoise(state, pSignalToNoise); + default: + break; + } +@@ -2608,7 +2676,7 @@ static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) + } + + #if 0 +-static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) ++static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) + { + /* SNR Values for quasi errorfree reception rom Nordig 2.2 */ + int status = 0; +@@ -2633,104 +2701,102 @@ static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) + 225, /* 64-QAM 7/8 */ + }; + +- *p_quality = 0; ++ *pQuality = 0; + + do { +- s32 signal_to_noise = 0; +- u16 constellation = 0; +- u16 code_rate = 0; +- u32 signal_to_noise_rel; +- u32 ber_quality; ++ s32 SignalToNoise = 0; ++ u16 Constellation = 0; ++ u16 CodeRate = 0; ++ u32 SignalToNoiseRel; ++ u32 BERQuality; + +- status = get_dvbt_signal_to_noise(state, &signal_to_noise); ++ status = GetDVBTSignalToNoise(state, &SignalToNoise); + if (status < 0) + break; +- status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, +- &constellation); ++ status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation); + if (status < 0) + break; +- constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; ++ Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; + +- status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, +- &code_rate); ++ status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate); + if (status < 0) + break; +- code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; ++ CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; + +- if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || +- code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) ++ if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || ++ CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) + break; +- signal_to_noise_rel = signal_to_noise - +- QE_SN[constellation * 5 + code_rate]; +- ber_quality = 100; +- +- if (signal_to_noise_rel < -70) +- *p_quality = 0; +- else if (signal_to_noise_rel < 30) +- *p_quality = ((signal_to_noise_rel + 70) * +- ber_quality) / 100; ++ SignalToNoiseRel = SignalToNoise - ++ QE_SN[Constellation * 5 + CodeRate]; ++ BERQuality = 100; ++ ++ if (SignalToNoiseRel < -70) ++ *pQuality = 0; ++ else if (SignalToNoiseRel < 30) ++ *pQuality = ((SignalToNoiseRel + 70) * ++ BERQuality) / 100; + else +- *p_quality = ber_quality; ++ *pQuality = BERQuality; + } while (0); + return 0; + }; + +-static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality) ++static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality) + { + int status = 0; +- *p_quality = 0; ++ *pQuality = 0; + + dprintk(1, "\n"); + + do { +- u32 signal_to_noise = 0; +- u32 ber_quality = 100; +- u32 signal_to_noise_rel = 0; ++ u32 SignalToNoise = 0; ++ u32 BERQuality = 100; ++ u32 SignalToNoiseRel = 0; + +- status = get_qam_signal_to_noise(state, &signal_to_noise); ++ status = GetQAMSignalToNoise(state, &SignalToNoise); + if (status < 0) + break; + + switch (state->props.modulation) { + case QAM_16: +- signal_to_noise_rel = signal_to_noise - 200; ++ SignalToNoiseRel = SignalToNoise - 200; + break; + case QAM_32: +- signal_to_noise_rel = signal_to_noise - 230; ++ SignalToNoiseRel = SignalToNoise - 230; + break; /* Not in NorDig */ + case QAM_64: +- signal_to_noise_rel = signal_to_noise - 260; ++ SignalToNoiseRel = SignalToNoise - 260; + break; + case QAM_128: +- signal_to_noise_rel = signal_to_noise - 290; ++ SignalToNoiseRel = SignalToNoise - 290; + break; + default: + case QAM_256: +- signal_to_noise_rel = signal_to_noise - 320; ++ SignalToNoiseRel = SignalToNoise - 320; + break; + } + +- if (signal_to_noise_rel < -70) +- *p_quality = 0; +- else if (signal_to_noise_rel < 30) +- *p_quality = ((signal_to_noise_rel + 70) * +- ber_quality) / 100; ++ if (SignalToNoiseRel < -70) ++ *pQuality = 0; ++ else if (SignalToNoiseRel < 30) ++ *pQuality = ((SignalToNoiseRel + 70) * ++ BERQuality) / 100; + else +- *p_quality = ber_quality; ++ *pQuality = BERQuality; + } while (0); + + return status; + } + +-static int get_quality(struct drxk_state *state, s32 *p_quality) ++static int GetQuality(struct drxk_state *state, s32 *pQuality) + { + dprintk(1, "\n"); + +- switch (state->m_operation_mode) { ++ switch (state->m_OperationMode) { + case OM_DVBT: +- return get_dvbt_quality(state, p_quality); ++ return GetDVBTQuality(state, pQuality); + case OM_QAM_ITU_A: +- return get_dvbc_quality(state, p_quality); ++ return GetDVBCQuality(state, pQuality); + default: + break; + } +@@ -2752,68 +2818,65 @@ static int get_quality(struct drxk_state *state, s32 *p_quality) + #define DRXDAP_FASI_ADDR2BANK(addr) (((addr) >> 16) & 0x3F) + #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF) + +-static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) ++static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) + { + int status = -EINVAL; + + dprintk(1, "\n"); + +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return 0; +- if (state->m_drxk_state == DRXK_POWERED_DOWN) ++ if (state->m_DrxkState == DRXK_UNINITIALIZED) ++ goto error; ++ if (state->m_DrxkState == DRXK_POWERED_DOWN) + goto error; + + if (state->no_i2c_bridge) + return 0; + +- status = write16(state, SIO_HI_RA_RAM_PAR_1__A, +- SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); ++ status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + if (status < 0) + goto error; +- if (b_enable_bridge) { +- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, +- SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); ++ if (bEnableBridge) { ++ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); + if (status < 0) + goto error; + } else { +- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, +- SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); ++ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); + if (status < 0) + goto error; + } + +- status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, NULL); ++ status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int set_pre_saw(struct drxk_state *state, +- struct s_cfg_pre_saw *p_pre_saw_cfg) ++static int SetPreSaw(struct drxk_state *state, ++ struct SCfgPreSaw *pPreSawCfg) + { + int status = -EINVAL; + + dprintk(1, "\n"); + +- if ((p_pre_saw_cfg == NULL) +- || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M)) ++ if ((pPreSawCfg == NULL) ++ || (pPreSawCfg->reference > IQM_AF_PDREF__M)) + goto error; + +- status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference); ++ status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, +- u16 rom_offset, u16 nr_of_elements, u32 time_out) ++static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, ++ u16 romOffset, u16 nrOfElements, u32 timeOut) + { +- u16 bl_status = 0; +- u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF); +- u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF); ++ u16 blStatus = 0; ++ u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF); ++ u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF); + int status; + unsigned long end; + +@@ -2829,44 +2892,44 @@ static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, + status = write16(state, SIO_BL_TGT_ADDR__A, offset); + if (status < 0) + goto error; +- status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset); ++ status = write16(state, SIO_BL_SRC_ADDR__A, romOffset); + if (status < 0) + goto error; +- status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements); ++ status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements); + if (status < 0) + goto error; + status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); + if (status < 0) + goto error; + +- end = jiffies + msecs_to_jiffies(time_out); ++ end = jiffies + msecs_to_jiffies(timeOut); + do { +- status = read16(state, SIO_BL_STATUS__A, &bl_status); ++ status = read16(state, SIO_BL_STATUS__A, &blStatus); + if (status < 0) + goto error; +- } while ((bl_status == 0x1) && time_is_after_jiffies(end)); +- if (bl_status == 0x1) { +- pr_err("SIO not ready\n"); ++ } while ((blStatus == 0x1) && time_is_after_jiffies(end)); ++ if (blStatus == 0x1) { ++ printk(KERN_ERR "drxk: SIO not ready\n"); + status = -EINVAL; + goto error2; + } + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + error2: + mutex_unlock(&state->mutex); + return status; + + } + +-static int adc_sync_measurement(struct drxk_state *state, u16 *count) ++static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) + { + u16 data = 0; + int status; + + dprintk(1, "\n"); + +- /* start measurement */ ++ /* Start measurement */ + status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE); + if (status < 0) + goto error; +@@ -2893,42 +2956,42 @@ static int adc_sync_measurement(struct drxk_state *state, u16 *count) + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int adc_synchronization(struct drxk_state *state) ++static int ADCSynchronization(struct drxk_state *state) + { + u16 count = 0; + int status; + + dprintk(1, "\n"); + +- status = adc_sync_measurement(state, &count); ++ status = ADCSyncMeasurement(state, &count); + if (status < 0) + goto error; + + if (count == 1) { +- /* Try sampling on a different edge */ +- u16 clk_neg = 0; ++ /* Try sampling on a diffrent edge */ ++ u16 clkNeg = 0; + +- status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); ++ status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); + if (status < 0) + goto error; +- if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) == ++ if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) == + IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { +- clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); +- clk_neg |= ++ clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); ++ clkNeg |= + IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG; + } else { +- clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); +- clk_neg |= ++ clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); ++ clkNeg |= + IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS; + } +- status = write16(state, IQM_AF_CLKNEG__A, clk_neg); ++ status = write16(state, IQM_AF_CLKNEG__A, clkNeg); + if (status < 0) + goto error; +- status = adc_sync_measurement(state, &count); ++ status = ADCSyncMeasurement(state, &count); + if (status < 0) + goto error; + } +@@ -2937,25 +3000,25 @@ static int adc_synchronization(struct drxk_state *state) + status = -EINVAL; + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int set_frequency_shifter(struct drxk_state *state, +- u16 intermediate_freqk_hz, +- s32 tuner_freq_offset, bool is_dtv) ++static int SetFrequencyShifter(struct drxk_state *state, ++ u16 intermediateFreqkHz, ++ s32 tunerFreqOffset, bool isDTV) + { +- bool select_pos_image = false; +- u32 rf_freq_residual = tuner_freq_offset; +- u32 fm_frequency_shift = 0; +- bool tuner_mirror = !state->m_b_mirror_freq_spect; +- u32 adc_freq; +- bool adc_flip; ++ bool selectPosImage = false; ++ u32 rfFreqResidual = tunerFreqOffset; ++ u32 fmFrequencyShift = 0; ++ bool tunerMirror = !state->m_bMirrorFreqSpect; ++ u32 adcFreq; ++ bool adcFlip; + int status; +- u32 if_freq_actual; +- u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3); +- u32 frequency_shift; +- bool image_to_select; ++ u32 ifFreqActual; ++ u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3); ++ u32 frequencyShift; ++ bool imageToSelect; + + dprintk(1, "\n"); + +@@ -2963,125 +3026,121 @@ static int set_frequency_shifter(struct drxk_state *state, + Program frequency shifter + No need to account for mirroring on RF + */ +- if (is_dtv) { +- if ((state->m_operation_mode == OM_QAM_ITU_A) || +- (state->m_operation_mode == OM_QAM_ITU_C) || +- (state->m_operation_mode == OM_DVBT)) +- select_pos_image = true; ++ if (isDTV) { ++ if ((state->m_OperationMode == OM_QAM_ITU_A) || ++ (state->m_OperationMode == OM_QAM_ITU_C) || ++ (state->m_OperationMode == OM_DVBT)) ++ selectPosImage = true; + else +- select_pos_image = false; ++ selectPosImage = false; + } +- if (tuner_mirror) ++ if (tunerMirror) + /* tuner doesn't mirror */ +- if_freq_actual = intermediate_freqk_hz + +- rf_freq_residual + fm_frequency_shift; ++ ifFreqActual = intermediateFreqkHz + ++ rfFreqResidual + fmFrequencyShift; + else + /* tuner mirrors */ +- if_freq_actual = intermediate_freqk_hz - +- rf_freq_residual - fm_frequency_shift; +- if (if_freq_actual > sampling_frequency / 2) { ++ ifFreqActual = intermediateFreqkHz - ++ rfFreqResidual - fmFrequencyShift; ++ if (ifFreqActual > samplingFrequency / 2) { + /* adc mirrors */ +- adc_freq = sampling_frequency - if_freq_actual; +- adc_flip = true; ++ adcFreq = samplingFrequency - ifFreqActual; ++ adcFlip = true; + } else { + /* adc doesn't mirror */ +- adc_freq = if_freq_actual; +- adc_flip = false; ++ adcFreq = ifFreqActual; ++ adcFlip = false; + } + +- frequency_shift = adc_freq; +- image_to_select = state->m_rfmirror ^ tuner_mirror ^ +- adc_flip ^ select_pos_image; +- state->m_iqm_fs_rate_ofs = +- Frac28a((frequency_shift), sampling_frequency); ++ frequencyShift = adcFreq; ++ imageToSelect = state->m_rfmirror ^ tunerMirror ^ ++ adcFlip ^ selectPosImage; ++ state->m_IqmFsRateOfs = ++ Frac28a((frequencyShift), samplingFrequency); + +- if (image_to_select) +- state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1; ++ if (imageToSelect) ++ state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1; + + /* Program frequency shifter with tuner offset compensation */ +- /* frequency_shift += tuner_freq_offset; TODO */ ++ /* frequencyShift += tunerFreqOffset; TODO */ + status = write32(state, IQM_FS_RATE_OFS_LO__A, +- state->m_iqm_fs_rate_ofs); ++ state->m_IqmFsRateOfs); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int init_agc(struct drxk_state *state, bool is_dtv) ++static int InitAGC(struct drxk_state *state, bool isDTV) + { +- u16 ingain_tgt = 0; +- u16 ingain_tgt_min = 0; +- u16 ingain_tgt_max = 0; +- u16 clp_cyclen = 0; +- u16 clp_sum_min = 0; +- u16 clp_dir_to = 0; +- u16 sns_sum_min = 0; +- u16 sns_sum_max = 0; +- u16 clp_sum_max = 0; +- u16 sns_dir_to = 0; +- u16 ki_innergain_min = 0; +- u16 if_iaccu_hi_tgt = 0; +- u16 if_iaccu_hi_tgt_min = 0; +- u16 if_iaccu_hi_tgt_max = 0; ++ u16 ingainTgt = 0; ++ u16 ingainTgtMin = 0; ++ u16 ingainTgtMax = 0; ++ u16 clpCyclen = 0; ++ u16 clpSumMin = 0; ++ u16 clpDirTo = 0; ++ u16 snsSumMin = 0; ++ u16 snsSumMax = 0; ++ u16 clpSumMax = 0; ++ u16 snsDirTo = 0; ++ u16 kiInnergainMin = 0; ++ u16 ifIaccuHiTgt = 0; ++ u16 ifIaccuHiTgtMin = 0; ++ u16 ifIaccuHiTgtMax = 0; + u16 data = 0; +- u16 fast_clp_ctrl_delay = 0; +- u16 clp_ctrl_mode = 0; ++ u16 fastClpCtrlDelay = 0; ++ u16 clpCtrlMode = 0; + int status = 0; + + dprintk(1, "\n"); + + /* Common settings */ +- sns_sum_max = 1023; +- if_iaccu_hi_tgt_min = 2047; +- clp_cyclen = 500; +- clp_sum_max = 1023; ++ snsSumMax = 1023; ++ ifIaccuHiTgtMin = 2047; ++ clpCyclen = 500; ++ clpSumMax = 1023; + + /* AGCInit() not available for DVBT; init done in microcode */ +- if (!is_qam(state)) { +- pr_err("%s: mode %d is not DVB-C\n", +- __func__, state->m_operation_mode); ++ if (!IsQAM(state)) { ++ printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode); + return -EINVAL; + } + + /* FIXME: Analog TV AGC require different settings */ + + /* Standard specific settings */ +- clp_sum_min = 8; +- clp_dir_to = (u16) -9; +- clp_ctrl_mode = 0; +- sns_sum_min = 8; +- sns_dir_to = (u16) -9; +- ki_innergain_min = (u16) -1030; +- if_iaccu_hi_tgt_max = 0x2380; +- if_iaccu_hi_tgt = 0x2380; +- ingain_tgt_min = 0x0511; +- ingain_tgt = 0x0511; +- ingain_tgt_max = 5119; +- fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay; ++ clpSumMin = 8; ++ clpDirTo = (u16) -9; ++ clpCtrlMode = 0; ++ snsSumMin = 8; ++ snsDirTo = (u16) -9; ++ kiInnergainMin = (u16) -1030; ++ ifIaccuHiTgtMax = 0x2380; ++ ifIaccuHiTgt = 0x2380; ++ ingainTgtMin = 0x0511; ++ ingainTgt = 0x0511; ++ ingainTgtMax = 5119; ++ fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay; + +- status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, +- fast_clp_ctrl_delay); ++ status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay); + if (status < 0) + goto error; + +- status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode); ++ status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt); ++ status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min); ++ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); ++ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, +- if_iaccu_hi_tgt_min); ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, +- if_iaccu_hi_tgt_max); ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax); + if (status < 0) + goto error; + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); +@@ -3096,22 +3155,20 @@ static int init_agc(struct drxk_state *state, bool is_dtv) + status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max); ++ status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max); ++ status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax); + if (status < 0) + goto error; + +- status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, +- ki_innergain_min); ++ status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, +- if_iaccu_hi_tgt); ++ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); ++ status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen); + if (status < 0) + goto error; + +@@ -3128,16 +3185,16 @@ static int init_agc(struct drxk_state *state, bool is_dtv) + status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min); ++ status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min); ++ status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to); ++ status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to); ++ status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo); + if (status < 0) + goto error; + status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff); +@@ -3197,39 +3254,38 @@ static int init_agc(struct drxk_state *state, bool is_dtv) + status = write16(state, SCU_RAM_AGC_KI__A, data); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) ++static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr) + { + int status; + + dprintk(1, "\n"); +- if (packet_err == NULL) ++ if (packetErr == NULL) + status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); + else +- status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, +- packet_err); ++ status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int dvbt_sc_command(struct drxk_state *state, ++static int DVBTScCommand(struct drxk_state *state, + u16 cmd, u16 subcmd, + u16 param0, u16 param1, u16 param2, + u16 param3, u16 param4) + { +- u16 cur_cmd = 0; +- u16 err_code = 0; +- u16 retry_cnt = 0; +- u16 sc_exec = 0; ++ u16 curCmd = 0; ++ u16 errCode = 0; ++ u16 retryCnt = 0; ++ u16 scExec = 0; + int status; + + dprintk(1, "\n"); +- status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec); +- if (sc_exec != 1) { ++ status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec); ++ if (scExec != 1) { + /* SC is not running */ + status = -EINVAL; + } +@@ -3237,13 +3293,13 @@ static int dvbt_sc_command(struct drxk_state *state, + goto error; + + /* Wait until sc is ready to receive command */ +- retry_cnt = 0; ++ retryCnt = 0; + do { +- usleep_range(1000, 2000); +- status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); +- retry_cnt++; +- } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); +- if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) ++ msleep(1); ++ status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); ++ retryCnt++; ++ } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); ++ if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + goto error; + + /* Write sub-command */ +@@ -3289,25 +3345,25 @@ static int dvbt_sc_command(struct drxk_state *state, + goto error; + + /* Wait until sc is ready processing command */ +- retry_cnt = 0; ++ retryCnt = 0; + do { +- usleep_range(1000, 2000); +- status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); +- retry_cnt++; +- } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); +- if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) ++ msleep(1); ++ status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); ++ retryCnt++; ++ } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); ++ if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + goto error; + + /* Check for illegal cmd */ +- status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code); +- if (err_code == 0xFFFF) { ++ status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode); ++ if (errCode == 0xFFFF) { + /* illegal command */ + status = -EINVAL; + } + if (status < 0) + goto error; + +- /* Retrieve results parameters from SC */ ++ /* Retreive results parameters from SC */ + switch (cmd) { + /* All commands yielding 5 results */ + /* All commands yielding 4 results */ +@@ -3332,44 +3388,44 @@ static int dvbt_sc_command(struct drxk_state *state, + } /* switch (cmd->cmd) */ + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int power_up_dvbt(struct drxk_state *state) ++static int PowerUpDVBT(struct drxk_state *state) + { +- enum drx_power_mode power_mode = DRX_POWER_UP; ++ enum DRXPowerMode powerMode = DRX_POWER_UP; + int status; + + dprintk(1, "\n"); +- status = ctrl_power_mode(state, &power_mode); ++ status = CtrlPowerMode(state, &powerMode); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) ++static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) + { + int status; + + dprintk(1, "\n"); +- if (*enabled) ++ if (*enabled == true) + status = write16(state, IQM_CF_BYPASSDET__A, 0); + else + status = write16(state, IQM_CF_BYPASSDET__A, 1); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + + #define DEFAULT_FR_THRES_8K 4000 +-static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) ++static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) + { + + int status; + + dprintk(1, "\n"); +- if (*enabled) { ++ if (*enabled == true) { + /* write mask to 1 */ + status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, + DEFAULT_FR_THRES_8K); +@@ -3378,13 +3434,13 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) + status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0); + } + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, +- struct drxk_cfg_dvbt_echo_thres_t *echo_thres) ++static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, ++ struct DRXKCfgDvbtEchoThres_t *echoThres) + { + u16 data = 0; + int status; +@@ -3394,16 +3450,16 @@ static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, + if (status < 0) + goto error; + +- switch (echo_thres->fft_mode) { ++ switch (echoThres->fftMode) { + case DRX_FFTMODE_2K: + data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M; +- data |= ((echo_thres->threshold << ++ data |= ((echoThres->threshold << + OFDM_SC_RA_RAM_ECHO_THRES_2K__B) + & (OFDM_SC_RA_RAM_ECHO_THRES_2K__M)); + break; + case DRX_FFTMODE_8K: + data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M; +- data |= ((echo_thres->threshold << ++ data |= ((echoThres->threshold << + OFDM_SC_RA_RAM_ECHO_THRES_8K__B) + & (OFDM_SC_RA_RAM_ECHO_THRES_8K__M)); + break; +@@ -3414,12 +3470,12 @@ static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, + status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, +- enum drxk_cfg_dvbt_sqi_speed *speed) ++static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, ++ enum DRXKCfgDvbtSqiSpeed *speed) + { + int status = -EINVAL; + +@@ -3437,7 +3493,7 @@ static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, + (u16) *speed); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -3451,33 +3507,32 @@ error: + * Called in DVBTSetStandard + * + */ +-static int dvbt_activate_presets(struct drxk_state *state) ++static int DVBTActivatePresets(struct drxk_state *state) + { + int status; + bool setincenable = false; + bool setfrenable = true; + +- struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K }; +- struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K }; ++ struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K }; ++ struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K }; + + dprintk(1, "\n"); +- status = dvbt_ctrl_set_inc_enable(state, &setincenable); ++ status = DVBTCtrlSetIncEnable(state, &setincenable); + if (status < 0) + goto error; +- status = dvbt_ctrl_set_fr_enable(state, &setfrenable); ++ status = DVBTCtrlSetFrEnable(state, &setfrenable); + if (status < 0) + goto error; +- status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k); ++ status = DVBTCtrlSetEchoThreshold(state, &echoThres2k); + if (status < 0) + goto error; +- status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k); ++ status = DVBTCtrlSetEchoThreshold(state, &echoThres8k); + if (status < 0) + goto error; +- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, +- state->m_dvbt_if_agc_cfg.ingain_tgt_max); ++ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -3491,30 +3546,25 @@ error: + * For ROM code channel filter taps are loaded from the bootloader. For microcode + * the DVB-T taps from the drxk_filters.h are used. + */ +-static int set_dvbt_standard(struct drxk_state *state, +- enum operation_mode o_mode) ++static int SetDVBTStandard(struct drxk_state *state, ++ enum OperationMode oMode) + { +- u16 cmd_result = 0; ++ u16 cmdResult = 0; + u16 data = 0; + int status; + + dprintk(1, "\n"); + +- power_up_dvbt(state); ++ PowerUpDVBT(state); + /* added antenna switch */ +- switch_antenna_to_dvbt(state); ++ SwitchAntennaToDVBT(state); + /* send OFDM reset command */ +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + + /* send OFDM setenv command */ +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + +@@ -3546,7 +3596,7 @@ static int set_dvbt_standard(struct drxk_state *state, + status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); + if (status < 0) + goto error; +- status = set_iqm_af(state, true); ++ status = SetIqmAf(state, true); + if (status < 0) + goto error; + +@@ -3568,7 +3618,7 @@ static int set_dvbt_standard(struct drxk_state *state, + status = write16(state, IQM_RC_STRETCH__A, 16); + if (status < 0) + goto error; +- status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ ++ status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ + if (status < 0) + goto error; + status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */ +@@ -3589,8 +3639,7 @@ static int set_dvbt_standard(struct drxk_state *state, + if (status < 0) + goto error; + +- status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, +- DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); ++ status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + if (status < 0) + goto error; + +@@ -3609,10 +3658,10 @@ static int set_dvbt_standard(struct drxk_state *state, + goto error; + + /* IQM will not be reset from here, sync ADC and update/init AGC */ +- status = adc_synchronization(state); ++ status = ADCSynchronization(state); + if (status < 0) + goto error; +- status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg); ++ status = SetPreSaw(state, &state->m_dvbtPreSawCfg); + if (status < 0) + goto error; + +@@ -3621,10 +3670,10 @@ static int set_dvbt_standard(struct drxk_state *state, + if (status < 0) + goto error; + +- status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true); ++ status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true); + if (status < 0) + goto error; +- status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true); ++ status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true); + if (status < 0) + goto error; + +@@ -3642,10 +3691,9 @@ static int set_dvbt_standard(struct drxk_state *state, + if (status < 0) + goto error; + +- if (!state->m_drxk_a3_rom_code) { +- /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */ +- status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, +- state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); ++ if (!state->m_DRXK_A3_ROM_CODE) { ++ /* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay */ ++ status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay); + if (status < 0) + goto error; + } +@@ -3680,43 +3728,41 @@ static int set_dvbt_standard(struct drxk_state *state, + goto error; + + /* Setup MPEG bus */ +- status = mpegts_dto_setup(state, OM_DVBT); ++ status = MPEGTSDtoSetup(state, OM_DVBT); + if (status < 0) + goto error; + /* Set DVBT Presets */ +- status = dvbt_activate_presets(state); ++ status = DVBTActivatePresets(state); + if (status < 0) + goto error; + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + + /*============================================================================*/ + /** +-* \brief start dvbt demodulating for channel. ++* \brief Start dvbt demodulating for channel. + * \param demod instance of demodulator. + * \return DRXStatus_t. + */ +-static int dvbt_start(struct drxk_state *state) ++static int DVBTStart(struct drxk_state *state) + { + u16 param1; + int status; +- /* drxk_ofdm_sc_cmd_t scCmd; */ ++ /* DRXKOfdmScCmd_t scCmd; */ + + dprintk(1, "\n"); +- /* start correct processes to get in lock */ ++ /* Start correct processes to get in lock */ + /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */ + param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN; +- status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, +- OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, +- 0, 0, 0); ++ status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); + if (status < 0) + goto error; +- /* start FEC OC */ +- status = mpegts_start(state); ++ /* Start FEC OC */ ++ status = MPEGTSStart(state); + if (status < 0) + goto error; + status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); +@@ -3724,7 +3770,7 @@ static int dvbt_start(struct drxk_state *state) + goto error; + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -3737,23 +3783,20 @@ error: + * \return DRXStatus_t. + * // original DVBTSetChannel() + */ +-static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, +- s32 tuner_freq_offset) ++static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, ++ s32 tunerFreqOffset) + { +- u16 cmd_result = 0; +- u16 transmission_params = 0; +- u16 operation_mode = 0; +- u32 iqm_rc_rate_ofs = 0; ++ u16 cmdResult = 0; ++ u16 transmissionParams = 0; ++ u16 operationMode = 0; ++ u32 iqmRcRateOfs = 0; + u32 bandwidth = 0; + u16 param1; + int status; + +- dprintk(1, "IF =%d, TFO = %d\n", +- intermediate_freqk_hz, tuner_freq_offset); ++ dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset); + +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + +@@ -3776,19 +3819,19 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + if (status < 0) + goto error; + +- /*== Write channel settings to device ================================*/ ++ /*== Write channel settings to device =====================================*/ + + /* mode */ + switch (state->props.transmission_mode) { + case TRANSMISSION_MODE_AUTO: + default: +- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; ++ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; + /* fall through , try first guess DRX_FFTMODE_8K */ + case TRANSMISSION_MODE_8K: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; + break; + case TRANSMISSION_MODE_2K: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; + break; + } + +@@ -3796,19 +3839,19 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + switch (state->props.guard_interval) { + default: + case GUARD_INTERVAL_AUTO: +- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; ++ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; + /* fall through , try first guess DRX_GUARD_1DIV4 */ + case GUARD_INTERVAL_1_4: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; + break; + case GUARD_INTERVAL_1_32: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; + break; + case GUARD_INTERVAL_1_16: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; + break; + case GUARD_INTERVAL_1_8: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; + break; + } + +@@ -3817,18 +3860,18 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + case HIERARCHY_AUTO: + case HIERARCHY_NONE: + default: +- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; ++ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; + /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ +- /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ ++ /* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ + /* break; */ + case HIERARCHY_1: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; + break; + case HIERARCHY_2: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; + break; + case HIERARCHY_4: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; + break; + } + +@@ -3837,30 +3880,30 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + switch (state->props.modulation) { + case QAM_AUTO: + default: +- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; ++ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; + /* fall through , try first guess DRX_CONSTELLATION_QAM64 */ + case QAM_64: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; + break; + case QPSK: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; + break; + case QAM_16: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; + break; + } + #if 0 +- /* No hierarchical channels support in BDA */ ++ /* No hierachical channels support in BDA */ + /* Priority (only for hierarchical channels) */ + switch (channel->priority) { + case DRX_PRIORITY_LOW: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; +- WR16(dev_addr, OFDM_EC_SB_PRIOR__A, ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; ++ WR16(devAddr, OFDM_EC_SB_PRIOR__A, + OFDM_EC_SB_PRIOR_LO); + break; + case DRX_PRIORITY_HIGH: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; +- WR16(dev_addr, OFDM_EC_SB_PRIOR__A, ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; ++ WR16(devAddr, OFDM_EC_SB_PRIOR__A, + OFDM_EC_SB_PRIOR_HI)); + break; + case DRX_PRIORITY_UNKNOWN: /* fall through */ +@@ -3870,7 +3913,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + } + #else + /* Set Priorty high */ +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; + status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI); + if (status < 0) + goto error; +@@ -3880,111 +3923,90 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + switch (state->props.code_rate_HP) { + case FEC_AUTO: + default: +- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; ++ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; + /* fall through , try first guess DRX_CODERATE_2DIV3 */ + case FEC_2_3: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; + break; + case FEC_1_2: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; + break; + case FEC_3_4: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; + break; + case FEC_5_6: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; + break; + case FEC_7_8: +- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; ++ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; + break; + } + +- /* +- * SAW filter selection: normaly not necesarry, but if wanted +- * the application can select a SAW filter via the driver by +- * using UIOs +- */ +- ++ /* SAW filter selection: normaly not necesarry, but if wanted ++ the application can select a SAW filter via the driver by using UIOs */ + /* First determine real bandwidth (Hz) */ + /* Also set delay for impulse noise cruncher */ +- /* +- * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is +- * changed by SC for fix for some 8K,1/8 guard but is restored by +- * InitEC and ResetEC functions +- */ ++ /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed ++ by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC ++ functions */ + switch (state->props.bandwidth_hz) { + case 0: + state->props.bandwidth_hz = 8000000; + /* fall though */ + case 8000000: + bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; +- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, +- 3052); ++ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052); + if (status < 0) + goto error; + /* cochannel protection for PAL 8 MHz */ +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, +- 7); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, +- 7); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, +- 7); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, +- 1); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + if (status < 0) + goto error; + break; + case 7000000: + bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ; +- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, +- 3491); ++ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491); + if (status < 0) + goto error; + /* cochannel protection for PAL 7 MHz */ +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, +- 8); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, +- 8); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, +- 4); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, +- 1); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + if (status < 0) + goto error; + break; + case 6000000: + bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ; +- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, +- 4073); ++ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073); + if (status < 0) + goto error; + /* cochannel protection for NTSC 6 MHz */ +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, +- 19); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, +- 19); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, +- 14); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14); + if (status < 0) + goto error; +- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, +- 1); ++ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + if (status < 0) + goto error; + break; +@@ -3993,50 +4015,46 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + goto error; + } + +- if (iqm_rc_rate_ofs == 0) { ++ if (iqmRcRateOfs == 0) { + /* Now compute IQM_RC_RATE_OFS + (((SysFreq/BandWidth)/2)/2) -1) * 2^23) + => + ((SysFreq / BandWidth) * (2^21)) - (2^23) + */ + /* (SysFreq / BandWidth) * (2^28) */ +- /* +- * assert (MAX(sysClk)/MIN(bandwidth) < 16) +- * => assert(MAX(sysClk) < 16*MIN(bandwidth)) +- * => assert(109714272 > 48000000) = true +- * so Frac 28 can be used +- */ +- iqm_rc_rate_ofs = Frac28a((u32) +- ((state->m_sys_clock_freq * ++ /* assert (MAX(sysClk)/MIN(bandwidth) < 16) ++ => assert(MAX(sysClk) < 16*MIN(bandwidth)) ++ => assert(109714272 > 48000000) = true so Frac 28 can be used */ ++ iqmRcRateOfs = Frac28a((u32) ++ ((state->m_sysClockFreq * + 1000) / 3), bandwidth); +- /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ +- if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40) +- iqm_rc_rate_ofs += 0x80L; +- iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7; ++ /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ ++ if ((iqmRcRateOfs & 0x7fL) >= 0x40) ++ iqmRcRateOfs += 0x80L; ++ iqmRcRateOfs = iqmRcRateOfs >> 7; + /* ((SysFreq / BandWidth) * (2^21)) - (2^23) */ +- iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23); ++ iqmRcRateOfs = iqmRcRateOfs - (1 << 23); + } + +- iqm_rc_rate_ofs &= ++ iqmRcRateOfs &= + ((((u32) IQM_RC_RATE_OFS_HI__M) << + IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M); +- status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs); ++ status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs); + if (status < 0) + goto error; + + /* Bandwidth setting done */ + + #if 0 +- status = dvbt_set_frequency_shift(demod, channel, tuner_offset); ++ status = DVBTSetFrequencyShift(demod, channel, tunerOffset); + if (status < 0) + goto error; + #endif +- status = set_frequency_shifter(state, intermediate_freqk_hz, +- tuner_freq_offset, true); ++ status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + if (status < 0) + goto error; + +- /*== start SC, write channel settings to SC ==========================*/ ++ /*== Start SC, write channel settings to SC ===============================*/ + + /* Activate SCU to enable SCU commands */ + status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); +@@ -4052,9 +4070,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + goto error; + + +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM +- | SCU_RAM_COMMAND_CMD_DEMOD_START, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + +@@ -4064,16 +4080,16 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + OFDM_SC_RA_RAM_OP_AUTO_CONST__M | + OFDM_SC_RA_RAM_OP_AUTO_HIER__M | + OFDM_SC_RA_RAM_OP_AUTO_RATE__M); +- status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, +- 0, transmission_params, param1, 0, 0, 0); ++ status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, ++ 0, transmissionParams, param1, 0, 0, 0); + if (status < 0) + goto error; + +- if (!state->m_drxk_a3_rom_code) +- status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed); ++ if (!state->m_DRXK_A3_ROM_CODE) ++ status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } +@@ -4082,13 +4098,13 @@ error: + /*============================================================================*/ + + /** +-* \brief Retrieve lock status . ++* \brief Retreive lock status . + * \param demod Pointer to demodulator instance. + * \param lockStat Pointer to lock status structure. + * \return DRXStatus_t. + * + */ +-static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) ++static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) + { + int status; + const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M | +@@ -4096,58 +4112,58 @@ static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) + const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M); + const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M; + +- u16 sc_ra_ram_lock = 0; +- u16 sc_comm_exec = 0; ++ u16 ScRaRamLock = 0; ++ u16 ScCommExec = 0; + + dprintk(1, "\n"); + +- *p_lock_status = NOT_LOCKED; ++ *pLockStatus = NOT_LOCKED; + /* driver 0.9.0 */ + /* Check if SC is running */ +- status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec); ++ status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec); + if (status < 0) + goto end; +- if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP) ++ if (ScCommExec == OFDM_SC_COMM_EXEC_STOP) + goto end; + +- status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock); ++ status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock); + if (status < 0) + goto end; + +- if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask) +- *p_lock_status = MPEG_LOCK; +- else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask) +- *p_lock_status = FEC_LOCK; +- else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask) +- *p_lock_status = DEMOD_LOCK; +- else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) +- *p_lock_status = NEVER_LOCK; ++ if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) ++ *pLockStatus = MPEG_LOCK; ++ else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) ++ *pLockStatus = FEC_LOCK; ++ else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) ++ *pLockStatus = DEMOD_LOCK; ++ else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) ++ *pLockStatus = NEVER_LOCK; + end: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static int power_up_qam(struct drxk_state *state) ++static int PowerUpQAM(struct drxk_state *state) + { +- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; ++ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; + int status; + + dprintk(1, "\n"); +- status = ctrl_power_mode(state, &power_mode); ++ status = CtrlPowerMode(state, &powerMode); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + + + /** Power Down QAM */ +-static int power_down_qam(struct drxk_state *state) ++static int PowerDownQAM(struct drxk_state *state) + { + u16 data = 0; +- u16 cmd_result; ++ u16 cmdResult; + int status = 0; + + dprintk(1, "\n"); +@@ -4163,18 +4179,16 @@ static int power_down_qam(struct drxk_state *state) + status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); + if (status < 0) + goto error; +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + } + /* powerdown AFE */ +- status = set_iqm_af(state, false); ++ status = SetIqmAf(state, false); + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } +@@ -4192,20 +4206,20 @@ error: + * The implementation does not check this. + * + */ +-static int set_qam_measurement(struct drxk_state *state, +- enum e_drxk_constellation modulation, +- u32 symbol_rate) ++static int SetQAMMeasurement(struct drxk_state *state, ++ enum EDrxkConstellation modulation, ++ u32 symbolRate) + { +- u32 fec_bits_desired = 0; /* BER accounting period */ +- u32 fec_rs_period_total = 0; /* Total period */ +- u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ +- u16 fec_rs_period = 0; /* Value for corresponding I2C register */ ++ u32 fecBitsDesired = 0; /* BER accounting period */ ++ u32 fecRsPeriodTotal = 0; /* Total period */ ++ u16 fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ ++ u16 fecRsPeriod = 0; /* Value for corresponding I2C register */ + int status = 0; + + dprintk(1, "\n"); + +- fec_rs_prescale = 1; +- /* fec_bits_desired = symbol_rate [kHz] * ++ fecRsPrescale = 1; ++ /* fecBitsDesired = symbolRate [kHz] * + FrameLenght [ms] * + (modulation + 1) * + SyncLoss (== 1) * +@@ -4213,19 +4227,19 @@ static int set_qam_measurement(struct drxk_state *state, + */ + switch (modulation) { + case DRX_CONSTELLATION_QAM16: +- fec_bits_desired = 4 * symbol_rate; ++ fecBitsDesired = 4 * symbolRate; + break; + case DRX_CONSTELLATION_QAM32: +- fec_bits_desired = 5 * symbol_rate; ++ fecBitsDesired = 5 * symbolRate; + break; + case DRX_CONSTELLATION_QAM64: +- fec_bits_desired = 6 * symbol_rate; ++ fecBitsDesired = 6 * symbolRate; + break; + case DRX_CONSTELLATION_QAM128: +- fec_bits_desired = 7 * symbol_rate; ++ fecBitsDesired = 7 * symbolRate; + break; + case DRX_CONSTELLATION_QAM256: +- fec_bits_desired = 8 * symbol_rate; ++ fecBitsDesired = 8 * symbolRate; + break; + default: + status = -EINVAL; +@@ -4233,41 +4247,40 @@ static int set_qam_measurement(struct drxk_state *state, + if (status < 0) + goto error; + +- fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ +- fec_bits_desired *= 500; /* meas. period [ms] */ ++ fecBitsDesired /= 1000; /* symbolRate [Hz] -> symbolRate [kHz] */ ++ fecBitsDesired *= 500; /* meas. period [ms] */ + + /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */ +- /* fec_rs_period_total = fec_bits_desired / 1632 */ +- fec_rs_period_total = (fec_bits_desired / 1632UL) + 1; /* roughly ceil */ ++ /* fecRsPeriodTotal = fecBitsDesired / 1632 */ ++ fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1; /* roughly ceil */ + +- /* fec_rs_period_total = fec_rs_prescale * fec_rs_period */ +- fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16); +- if (fec_rs_prescale == 0) { ++ /* fecRsPeriodTotal = fecRsPrescale * fecRsPeriod */ ++ fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16); ++ if (fecRsPrescale == 0) { + /* Divide by zero (though impossible) */ + status = -EINVAL; + if (status < 0) + goto error; + } +- fec_rs_period = +- ((u16) fec_rs_period_total + +- (fec_rs_prescale >> 1)) / fec_rs_prescale; ++ fecRsPeriod = ++ ((u16) fecRsPeriodTotal + ++ (fecRsPrescale >> 1)) / fecRsPrescale; + + /* write corresponding registers */ +- status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period); ++ status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod); + if (status < 0) + goto error; +- status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, +- fec_rs_prescale); ++ status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale); + if (status < 0) + goto error; +- status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); ++ status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int set_qam16(struct drxk_state *state) ++static int SetQAM16(struct drxk_state *state) + { + int status = 0; + +@@ -4323,8 +4336,7 @@ static int set_qam16(struct drxk_state *state) + goto error; + + /* QAM Slicer Settings */ +- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, +- DRXK_QAM_SL_SIG_POWER_QAM16); ++ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16); + if (status < 0) + goto error; + +@@ -4450,7 +4462,7 @@ static int set_qam16(struct drxk_state *state) + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -4461,7 +4473,7 @@ error: + * \param demod instance of demod. + * \return DRXStatus_t. + */ +-static int set_qam32(struct drxk_state *state) ++static int SetQAM32(struct drxk_state *state) + { + int status = 0; + +@@ -4520,8 +4532,7 @@ static int set_qam32(struct drxk_state *state) + + /* QAM Slicer Settings */ + +- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, +- DRXK_QAM_SL_SIG_POWER_QAM32); ++ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32); + if (status < 0) + goto error; + +@@ -4646,7 +4657,7 @@ static int set_qam32(struct drxk_state *state) + status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -4657,7 +4668,7 @@ error: + * \param demod instance of demod. + * \return DRXStatus_t. + */ +-static int set_qam64(struct drxk_state *state) ++static int SetQAM64(struct drxk_state *state) + { + int status = 0; + +@@ -4714,8 +4725,7 @@ static int set_qam64(struct drxk_state *state) + goto error; + + /* QAM Slicer Settings */ +- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, +- DRXK_QAM_SL_SIG_POWER_QAM64); ++ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64); + if (status < 0) + goto error; + +@@ -4840,7 +4850,7 @@ static int set_qam64(struct drxk_state *state) + status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } +@@ -4852,7 +4862,7 @@ error: + * \param demod: instance of demod. + * \return DRXStatus_t. + */ +-static int set_qam128(struct drxk_state *state) ++static int SetQAM128(struct drxk_state *state) + { + int status = 0; + +@@ -4911,8 +4921,7 @@ static int set_qam128(struct drxk_state *state) + + /* QAM Slicer Settings */ + +- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, +- DRXK_QAM_SL_SIG_POWER_QAM128); ++ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128); + if (status < 0) + goto error; + +@@ -5037,7 +5046,7 @@ static int set_qam128(struct drxk_state *state) + status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } +@@ -5049,7 +5058,7 @@ error: + * \param demod: instance of demod. + * \return DRXStatus_t. + */ +-static int set_qam256(struct drxk_state *state) ++static int SetQAM256(struct drxk_state *state) + { + int status = 0; + +@@ -5107,8 +5116,7 @@ static int set_qam256(struct drxk_state *state) + + /* QAM Slicer Settings */ + +- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, +- DRXK_QAM_SL_SIG_POWER_QAM256); ++ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256); + if (status < 0) + goto error; + +@@ -5233,7 +5241,7 @@ static int set_qam256(struct drxk_state *state) + status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -5245,10 +5253,10 @@ error: + * \param channel: pointer to channel data. + * \return DRXStatus_t. + */ +-static int qam_reset_qam(struct drxk_state *state) ++static int QAMResetQAM(struct drxk_state *state) + { + int status; +- u16 cmd_result; ++ u16 cmdResult; + + dprintk(1, "\n"); + /* Stop QAM comstate->m_exec */ +@@ -5256,12 +5264,10 @@ static int qam_reset_qam(struct drxk_state *state) + if (status < 0) + goto error; + +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -5273,18 +5279,18 @@ error: + * \param channel: pointer to channel data. + * \return DRXStatus_t. + */ +-static int qam_set_symbolrate(struct drxk_state *state) ++static int QAMSetSymbolrate(struct drxk_state *state) + { +- u32 adc_frequency = 0; +- u32 symb_freq = 0; +- u32 iqm_rc_rate = 0; ++ u32 adcFrequency = 0; ++ u32 symbFreq = 0; ++ u32 iqmRcRate = 0; + u16 ratesel = 0; +- u32 lc_symb_rate = 0; ++ u32 lcSymbRate = 0; + int status; + + dprintk(1, "\n"); + /* Select & calculate correct IQM rate */ +- adc_frequency = (state->m_sys_clock_freq * 1000) / 3; ++ adcFrequency = (state->m_sysClockFreq * 1000) / 3; + ratesel = 0; + /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */ + if (state->props.symbol_rate <= 1188750) +@@ -5300,38 +5306,38 @@ static int qam_set_symbolrate(struct drxk_state *state) + /* + IqmRcRate = ((Fadc / (symbolrate * (4<props.symbol_rate * (1 << ratesel); +- if (symb_freq == 0) { ++ symbFreq = state->props.symbol_rate * (1 << ratesel); ++ if (symbFreq == 0) { + /* Divide by zero */ + status = -EINVAL; + goto error; + } +- iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) + +- (Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) - ++ iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) + ++ (Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) - + (1 << 23); +- status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate); ++ status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate); + if (status < 0) + goto error; +- state->m_iqm_rc_rate = iqm_rc_rate; ++ state->m_iqmRcRate = iqmRcRate; + /* +- LcSymbFreq = round (.125 * symbolrate / adc_freq * (1<<15)) ++ LcSymbFreq = round (.125 * symbolrate / adcFreq * (1<<15)) + */ +- symb_freq = state->props.symbol_rate; +- if (adc_frequency == 0) { ++ symbFreq = state->props.symbol_rate; ++ if (adcFrequency == 0) { + /* Divide by zero */ + status = -EINVAL; + goto error; + } +- lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) + +- (Frac28a((symb_freq % adc_frequency), adc_frequency) >> ++ lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) + ++ (Frac28a((symbFreq % adcFrequency), adcFrequency) >> + 16); +- if (lc_symb_rate > 511) +- lc_symb_rate = 511; +- status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate); ++ if (lcSymbRate > 511) ++ lcSymbRate = 511; ++ status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate); + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +@@ -5344,36 +5350,34 @@ error: + * \return DRXStatus_t. + */ + +-static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) ++static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) + { + int status; +- u16 result[2] = { 0, 0 }; ++ u16 Result[2] = { 0, 0 }; + + dprintk(1, "\n"); +- *p_lock_status = NOT_LOCKED; ++ *pLockStatus = NOT_LOCKED; + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, +- result); ++ Result); + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status); + +- if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { ++ if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { + /* 0x0000 NOT LOCKED */ +- } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { ++ } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { + /* 0x4000 DEMOD LOCKED */ +- *p_lock_status = DEMOD_LOCK; +- } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { ++ *pLockStatus = DEMOD_LOCK; ++ } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { + /* 0x8000 DEMOD + FEC LOCKED (system lock) */ +- *p_lock_status = MPEG_LOCK; ++ *pLockStatus = MPEG_LOCK; + } else { + /* 0xC000 NEVER LOCKED */ + /* (system will never be able to lock to the signal) */ +- /* +- * TODO: check this, intermediate & standard specific lock +- * states are not taken into account here +- */ +- *p_lock_status = NEVER_LOCK; ++ /* TODO: check this, intermediate & standard specific lock states are not ++ taken into account here */ ++ *pLockStatus = NEVER_LOCK; + } + return status; + } +@@ -5385,70 +5389,12 @@ static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) + #define QAM_LOCKRANGE__M 0x10 + #define QAM_LOCKRANGE_NORMAL 0x10 + +-static int qam_demodulator_command(struct drxk_state *state, +- int number_of_parameters) ++static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, ++ s32 tunerFreqOffset) + { + int status; +- u16 cmd_result; +- u16 set_param_parameters[4] = { 0, 0, 0, 0 }; +- +- set_param_parameters[0] = state->m_constellation; /* modulation */ +- set_param_parameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ +- +- if (number_of_parameters == 2) { +- u16 set_env_parameters[1] = { 0 }; +- +- if (state->m_operation_mode == OM_QAM_ITU_C) +- set_env_parameters[0] = QAM_TOP_ANNEX_C; +- else +- set_env_parameters[0] = QAM_TOP_ANNEX_A; +- +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, +- 1, set_env_parameters, 1, &cmd_result); +- if (status < 0) +- goto error; +- +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, +- number_of_parameters, set_param_parameters, +- 1, &cmd_result); +- } else if (number_of_parameters == 4) { +- if (state->m_operation_mode == OM_QAM_ITU_C) +- set_param_parameters[2] = QAM_TOP_ANNEX_C; +- else +- set_param_parameters[2] = QAM_TOP_ANNEX_A; +- +- set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON); +- /* Env parameters */ +- /* check for LOCKRANGE Extented */ +- /* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */ +- +- status = scu_command(state, +- SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, +- number_of_parameters, set_param_parameters, +- 1, &cmd_result); +- } else { +- pr_warn("Unknown QAM demodulator parameter count %d\n", +- number_of_parameters); +- status = -EINVAL; +- } +- +-error: +- if (status < 0) +- pr_warn("Warning %d on %s\n", status, __func__); +- return status; +-} +- +-static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, +- s32 tuner_freq_offset) +-{ +- int status; +- u16 cmd_result; +- int qam_demod_param_count = state->qam_demod_parameter_count; ++ u16 setParamParameters[4] = { 0, 0, 0, 0 }; ++ u16 cmdResult; + + dprintk(1, "\n"); + /* +@@ -5463,7 +5409,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP); + if (status < 0) + goto error; +- status = qam_reset_qam(state); ++ status = QAMResetQAM(state); + if (status < 0) + goto error; + +@@ -5472,27 +5418,27 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + * -set params; resets IQM,QAM,FEC HW; initializes some + * SCU variables + */ +- status = qam_set_symbolrate(state); ++ status = QAMSetSymbolrate(state); + if (status < 0) + goto error; + + /* Set params */ + switch (state->props.modulation) { + case QAM_256: +- state->m_constellation = DRX_CONSTELLATION_QAM256; ++ state->m_Constellation = DRX_CONSTELLATION_QAM256; + break; + case QAM_AUTO: + case QAM_64: +- state->m_constellation = DRX_CONSTELLATION_QAM64; ++ state->m_Constellation = DRX_CONSTELLATION_QAM64; + break; + case QAM_16: +- state->m_constellation = DRX_CONSTELLATION_QAM16; ++ state->m_Constellation = DRX_CONSTELLATION_QAM16; + break; + case QAM_32: +- state->m_constellation = DRX_CONSTELLATION_QAM32; ++ state->m_Constellation = DRX_CONSTELLATION_QAM32; + break; + case QAM_128: +- state->m_constellation = DRX_CONSTELLATION_QAM128; ++ state->m_Constellation = DRX_CONSTELLATION_QAM128; + break; + default: + status = -EINVAL; +@@ -5500,60 +5446,50 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + } + if (status < 0) + goto error; ++ setParamParameters[0] = state->m_Constellation; /* modulation */ ++ setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ ++ if (state->m_OperationMode == OM_QAM_ITU_C) ++ setParamParameters[2] = QAM_TOP_ANNEX_C; ++ else ++ setParamParameters[2] = QAM_TOP_ANNEX_A; ++ setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); ++ /* Env parameters */ ++ /* check for LOCKRANGE Extented */ ++ /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ + +- /* Use the 4-parameter if it's requested or we're probing for +- * the correct command. */ +- if (state->qam_demod_parameter_count == 4 +- || !state->qam_demod_parameter_count) { +- qam_demod_param_count = 4; +- status = qam_demodulator_command(state, qam_demod_param_count); +- } +- +- /* Use the 2-parameter command if it was requested or if we're +- * probing for the correct command and the 4-parameter command +- * failed. */ +- if (state->qam_demod_parameter_count == 2 +- || (!state->qam_demod_parameter_count && status < 0)) { +- qam_demod_param_count = 2; +- status = qam_demodulator_command(state, qam_demod_param_count); +- } +- ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult); + if (status < 0) { +- dprintk(1, "Could not set demodulator parameters.\n"); +- dprintk(1, +- "Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n", +- state->qam_demod_parameter_count, +- state->microcode_name); +- goto error; +- } else if (!state->qam_demod_parameter_count) { +- dprintk(1, +- "Auto-probing the QAM command parameters was successful - using %d parameters.\n", +- qam_demod_param_count); ++ /* Fall-back to the simpler call */ ++ if (state->m_OperationMode == OM_QAM_ITU_C) ++ setParamParameters[0] = QAM_TOP_ANNEX_C; ++ else ++ setParamParameters[0] = QAM_TOP_ANNEX_A; ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult); ++ if (status < 0) ++ goto error; + +- /* +- * One of our commands was successful. We don't need to +- * auto-probe anymore, now that we got the correct command. +- */ +- state->qam_demod_parameter_count = qam_demod_param_count; ++ setParamParameters[0] = state->m_Constellation; /* modulation */ ++ setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult); + } ++ if (status < 0) ++ goto error; + + /* + * STEP 3: enable the system in a mode where the ADC provides valid + * signal setup modulation independent registers + */ + #if 0 +- status = set_frequency(channel, tuner_freq_offset)); ++ status = SetFrequency(channel, tunerFreqOffset)); + if (status < 0) + goto error; + #endif +- status = set_frequency_shifter(state, intermediate_freqk_hz, +- tuner_freq_offset, true); ++ status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + if (status < 0) + goto error; + + /* Setup BER measurement */ +- status = set_qam_measurement(state, state->m_constellation, +- state->props.symbol_rate); ++ status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate); + if (status < 0) + goto error; + +@@ -5626,8 +5562,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + goto error; + + /* Mirroring, QAM-block starting point not inverted */ +- status = write16(state, QAM_SY_SP_INV__A, +- QAM_SY_SP_INV_SPECTRUM_INV_DIS); ++ status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS); + if (status < 0) + goto error; + +@@ -5639,20 +5574,20 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + /* STEP 4: modulation specific setup */ + switch (state->props.modulation) { + case QAM_16: +- status = set_qam16(state); ++ status = SetQAM16(state); + break; + case QAM_32: +- status = set_qam32(state); ++ status = SetQAM32(state); + break; + case QAM_AUTO: + case QAM_64: +- status = set_qam64(state); ++ status = SetQAM64(state); + break; + case QAM_128: +- status = set_qam128(state); ++ status = SetQAM128(state); + break; + case QAM_256: +- status = set_qam256(state); ++ status = SetQAM256(state); + break; + default: + status = -EINVAL; +@@ -5669,12 +5604,12 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + /* Re-configure MPEG output, requires knowledge of channel bitrate */ + /* extAttr->currentChannel.modulation = channel->modulation; */ + /* extAttr->currentChannel.symbolrate = channel->symbolrate; */ +- status = mpegts_dto_setup(state, state->m_operation_mode); ++ status = MPEGTSDtoSetup(state, state->m_OperationMode); + if (status < 0) + goto error; + +- /* start processes */ +- status = mpegts_start(state); ++ /* Start processes */ ++ status = MPEGTSStart(state); + if (status < 0) + goto error; + status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); +@@ -5688,9 +5623,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + goto error; + + /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ +- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM +- | SCU_RAM_COMMAND_CMD_DEMOD_START, +- 0, NULL, 1, &cmd_result); ++ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + if (status < 0) + goto error; + +@@ -5699,12 +5632,12 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int set_qam_standard(struct drxk_state *state, +- enum operation_mode o_mode) ++static int SetQAMStandard(struct drxk_state *state, ++ enum OperationMode oMode) + { + int status; + #ifdef DRXK_QAM_TAPS +@@ -5716,14 +5649,14 @@ static int set_qam_standard(struct drxk_state *state, + dprintk(1, "\n"); + + /* added antenna switch */ +- switch_antenna_to_qam(state); ++ SwitchAntennaToQAM(state); + + /* Ensure correct power-up mode */ +- status = power_up_qam(state); ++ status = PowerUpQAM(state); + if (status < 0) + goto error; + /* Reset QAM block */ +- status = qam_reset_qam(state); ++ status = QAMResetQAM(state); + if (status < 0) + goto error; + +@@ -5738,24 +5671,15 @@ static int set_qam_standard(struct drxk_state *state, + + /* Upload IQM Channel Filter settings by + boot loader from ROM table */ +- switch (o_mode) { ++ switch (oMode) { + case OM_QAM_ITU_A: +- status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, +- DRXK_BLCC_NR_ELEMENTS_TAPS, +- DRXK_BLC_TIMEOUT); ++ status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + break; + case OM_QAM_ITU_C: +- status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, +- DRXK_BL_ROM_OFFSET_TAPS_ITU_C, +- DRXK_BLDC_NR_ELEMENTS_TAPS, +- DRXK_BLC_TIMEOUT); ++ status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + if (status < 0) + goto error; +- status = bl_direct_cmd(state, +- IQM_CF_TAP_IM0__A, +- DRXK_BL_ROM_OFFSET_TAPS_ITU_C, +- DRXK_BLDC_NR_ELEMENTS_TAPS, +- DRXK_BLC_TIMEOUT); ++ status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + break; + default: + status = -EINVAL; +@@ -5763,14 +5687,13 @@ static int set_qam_standard(struct drxk_state *state, + if (status < 0) + goto error; + +- status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B); ++ status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B)); + if (status < 0) + goto error; + status = write16(state, IQM_CF_SYMMETRIC__A, 0); + if (status < 0) + goto error; +- status = write16(state, IQM_CF_MIDTAP__A, +- ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); ++ status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); + if (status < 0) + goto error; + +@@ -5827,7 +5750,7 @@ static int set_qam_standard(struct drxk_state *state, + goto error; + + /* turn on IQMAF. Must be done before setAgc**() */ +- status = set_iqm_af(state, true); ++ status = SetIqmAf(state, true); + if (status < 0) + goto error; + status = write16(state, IQM_AF_START_LOCK__A, 0x01); +@@ -5835,7 +5758,7 @@ static int set_qam_standard(struct drxk_state *state, + goto error; + + /* IQM will not be reset from here, sync ADC and update/init AGC */ +- status = adc_synchronization(state); ++ status = ADCSynchronization(state); + if (status < 0) + goto error; + +@@ -5852,18 +5775,18 @@ static int set_qam_standard(struct drxk_state *state, + /* No more resets of the IQM, current standard correctly set => + now AGCs can be configured. */ + +- status = init_agc(state, true); ++ status = InitAGC(state, true); + if (status < 0) + goto error; +- status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg)); ++ status = SetPreSaw(state, &(state->m_qamPreSawCfg)); + if (status < 0) + goto error; + + /* Configure AGC's */ +- status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true); ++ status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true); + if (status < 0) + goto error; +- status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true); ++ status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true); + if (status < 0) + goto error; + +@@ -5871,19 +5794,18 @@ static int set_qam_standard(struct drxk_state *state, + status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int write_gpio(struct drxk_state *state) ++static int WriteGPIO(struct drxk_state *state) + { + int status; + u16 value = 0; + + dprintk(1, "\n"); + /* stop lock indicator process */ +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; + +@@ -5892,11 +5814,10 @@ static int write_gpio(struct drxk_state *state) + if (status < 0) + goto error; + +- if (state->m_has_sawsw) { +- if (state->uio_mask & 0x0001) { /* UIO-1 */ ++ if (state->m_hasSAWSW) { ++ if (state->UIO_mask & 0x0001) { /* UIO-1 */ + /* write to io pad configuration register - output mode */ +- status = write16(state, SIO_PDR_SMA_TX_CFG__A, +- state->m_gpio_cfg); ++ status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; + +@@ -5904,7 +5825,7 @@ static int write_gpio(struct drxk_state *state) + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; +- if ((state->m_gpio & 0x0001) == 0) ++ if ((state->m_GPIO & 0x0001) == 0) + value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ + else + value |= 0x8000; /* write one to 15th bit - 1st UIO */ +@@ -5913,10 +5834,9 @@ static int write_gpio(struct drxk_state *state) + if (status < 0) + goto error; + } +- if (state->uio_mask & 0x0002) { /* UIO-2 */ ++ if (state->UIO_mask & 0x0002) { /* UIO-2 */ + /* write to io pad configuration register - output mode */ +- status = write16(state, SIO_PDR_SMA_RX_CFG__A, +- state->m_gpio_cfg); ++ status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; + +@@ -5924,7 +5844,7 @@ static int write_gpio(struct drxk_state *state) + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; +- if ((state->m_gpio & 0x0002) == 0) ++ if ((state->m_GPIO & 0x0002) == 0) + value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ + else + value |= 0x4000; /* write one to 14th bit - 2st UIO */ +@@ -5933,10 +5853,9 @@ static int write_gpio(struct drxk_state *state) + if (status < 0) + goto error; + } +- if (state->uio_mask & 0x0004) { /* UIO-3 */ ++ if (state->UIO_mask & 0x0004) { /* UIO-3 */ + /* write to io pad configuration register - output mode */ +- status = write16(state, SIO_PDR_GPIO_CFG__A, +- state->m_gpio_cfg); ++ status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg); + if (status < 0) + goto error; + +@@ -5944,7 +5863,7 @@ static int write_gpio(struct drxk_state *state) + status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); + if (status < 0) + goto error; +- if ((state->m_gpio & 0x0004) == 0) ++ if ((state->m_GPIO & 0x0004) == 0) + value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ + else + value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ +@@ -5958,11 +5877,11 @@ static int write_gpio(struct drxk_state *state) + status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int switch_antenna_to_qam(struct drxk_state *state) ++static int SwitchAntennaToQAM(struct drxk_state *state) + { + int status = 0; + bool gpio_state; +@@ -5972,22 +5891,22 @@ static int switch_antenna_to_qam(struct drxk_state *state) + if (!state->antenna_gpio) + return 0; + +- gpio_state = state->m_gpio & state->antenna_gpio; ++ gpio_state = state->m_GPIO & state->antenna_gpio; + + if (state->antenna_dvbt ^ gpio_state) { + /* Antenna is on DVB-T mode. Switch */ + if (state->antenna_dvbt) +- state->m_gpio &= ~state->antenna_gpio; ++ state->m_GPIO &= ~state->antenna_gpio; + else +- state->m_gpio |= state->antenna_gpio; +- status = write_gpio(state); ++ state->m_GPIO |= state->antenna_gpio; ++ status = WriteGPIO(state); + } + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + +-static int switch_antenna_to_dvbt(struct drxk_state *state) ++static int SwitchAntennaToDVBT(struct drxk_state *state) + { + int status = 0; + bool gpio_state; +@@ -5997,23 +5916,23 @@ static int switch_antenna_to_dvbt(struct drxk_state *state) + if (!state->antenna_gpio) + return 0; + +- gpio_state = state->m_gpio & state->antenna_gpio; ++ gpio_state = state->m_GPIO & state->antenna_gpio; + + if (!(state->antenna_dvbt ^ gpio_state)) { + /* Antenna is on DVB-C mode. Switch */ + if (state->antenna_dvbt) +- state->m_gpio |= state->antenna_gpio; ++ state->m_GPIO |= state->antenna_gpio; + else +- state->m_gpio &= ~state->antenna_gpio; +- status = write_gpio(state); ++ state->m_GPIO &= ~state->antenna_gpio; ++ status = WriteGPIO(state); + } + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + return status; + } + + +-static int power_down_device(struct drxk_state *state) ++static int PowerDownDevice(struct drxk_state *state) + { + /* Power down to requested mode */ + /* Backup some register settings */ +@@ -6024,86 +5943,98 @@ static int power_down_device(struct drxk_state *state) + int status; + + dprintk(1, "\n"); +- if (state->m_b_p_down_open_bridge) { ++ if (state->m_bPDownOpenBridge) { + /* Open I2C bridge before power down of DRXK */ + status = ConfigureI2CBridge(state, true); + if (status < 0) + goto error; + } + /* driver 0.9.0 */ +- status = dvbt_enable_ofdm_token_ring(state, false); ++ status = DVBTEnableOFDMTokenRing(state, false); + if (status < 0) + goto error; + +- status = write16(state, SIO_CC_PWD_MODE__A, +- SIO_CC_PWD_MODE_LEVEL_CLOCK); ++ status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK); + if (status < 0) + goto error; + status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); + if (status < 0) + goto error; +- state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; +- status = hi_cfg_command(state); ++ state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; ++ status = HI_CfgCommand(state); + error: + if (status < 0) +- pr_err("Error %d on %s\n", status, __func__); ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + ++static int load_microcode(struct drxk_state *state, const char *mc_name) ++{ ++ const struct firmware *fw = NULL; ++ int err = 0; ++ ++ dprintk(1, "\n"); ++ ++ err = request_firmware(&fw, mc_name, state->i2c->dev.parent); ++ if (err < 0) { ++ printk(KERN_ERR ++ "drxk: Could not load firmware file %s.\n", mc_name); ++ printk(KERN_INFO ++ "drxk: Copy %s to your hotplug directory!\n", mc_name); ++ return err; ++ } ++ err = DownloadMicrocode(state, fw->data, fw->size); ++ release_firmware(fw); ++ return err; ++} ++ + static int init_drxk(struct drxk_state *state) + { +- int status = 0, n = 0; +- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; +- u16 driver_version; ++ int status = 0; ++ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; ++ u16 driverVersion; + + dprintk(1, "\n"); +- if ((state->m_drxk_state == DRXK_UNINITIALIZED)) { +- drxk_i2c_lock(state); +- status = power_up_device(state); ++ if ((state->m_DrxkState == DRXK_UNINITIALIZED)) { ++ status = PowerUpDevice(state); + if (status < 0) + goto error; +- status = drxx_open(state); ++ status = DRXX_Open(state); + if (status < 0) + goto error; + /* Soft reset of OFDM-, sys- and osc-clockdomain */ +- status = write16(state, SIO_CC_SOFT_RST__A, +- SIO_CC_SOFT_RST_OFDM__M +- | SIO_CC_SOFT_RST_SYS__M +- | SIO_CC_SOFT_RST_OSC__M); ++ status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M); + if (status < 0) + goto error; + status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); + if (status < 0) + goto error; +- /* +- * TODO is this needed? If yes, how much delay in +- * worst case scenario +- */ +- usleep_range(1000, 2000); +- state->m_drxk_a3_patch_code = true; +- status = get_device_capabilities(state); ++ /* TODO is this needed, if yes how much delay in worst case scenario */ ++ msleep(1); ++ state->m_DRXK_A3_PATCH_CODE = true; ++ status = GetDeviceCapabilities(state); + if (status < 0) + goto error; + + /* Bridge delay, uses oscilator clock */ + /* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */ + /* SDA brdige delay */ +- state->m_hi_cfg_bridge_delay = +- (u16) ((state->m_osc_clock_freq / 1000) * ++ state->m_HICfgBridgeDelay = ++ (u16) ((state->m_oscClockFreq / 1000) * + HI_I2C_BRIDGE_DELAY) / 1000; + /* Clipping */ +- if (state->m_hi_cfg_bridge_delay > ++ if (state->m_HICfgBridgeDelay > + SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) { +- state->m_hi_cfg_bridge_delay = ++ state->m_HICfgBridgeDelay = + SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; + } + /* SCL bridge delay, same as SDA for now */ +- state->m_hi_cfg_bridge_delay += +- state->m_hi_cfg_bridge_delay << ++ state->m_HICfgBridgeDelay += ++ state->m_HICfgBridgeDelay << + SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B; + +- status = init_hi(state); ++ status = InitHI(state); + if (status < 0) + goto error; + /* disable various processes */ +@@ -6112,14 +6043,13 @@ static int init_drxk(struct drxk_state *state) + && !(state->m_DRXK_A2_ROM_CODE)) + #endif + { +- status = write16(state, SCU_RAM_GPIO__A, +- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); ++ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + if (status < 0) + goto error; + } + + /* disable MPEG port */ +- status = mpegts_disable(state); ++ status = MPEGTSDisable(state); + if (status < 0) + goto error; + +@@ -6132,30 +6062,23 @@ static int init_drxk(struct drxk_state *state) + goto error; + + /* enable token-ring bus through OFDM block for possible ucode upload */ +- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, +- SIO_OFDM_SH_OFDM_RING_ENABLE_ON); ++ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON); + if (status < 0) + goto error; + + /* include boot loader section */ +- status = write16(state, SIO_BL_COMM_EXEC__A, +- SIO_BL_COMM_EXEC_ACTIVE); ++ status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE); + if (status < 0) + goto error; +- status = bl_chain_cmd(state, 0, 6, 100); ++ status = BLChainCmd(state, 0, 6, 100); + if (status < 0) + goto error; + +- if (state->fw) { +- status = download_microcode(state, state->fw->data, +- state->fw->size); +- if (status < 0) +- goto error; +- } ++ if (state->microcode_name) ++ load_microcode(state, state->microcode_name); + + /* disable token-ring bus through OFDM block for possible ucode upload */ +- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, +- SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); ++ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); + if (status < 0) + goto error; + +@@ -6163,55 +6086,50 @@ static int init_drxk(struct drxk_state *state) + status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); + if (status < 0) + goto error; +- status = drxx_open(state); ++ status = DRXX_Open(state); + if (status < 0) + goto error; + /* added for test */ + msleep(30); + +- power_mode = DRXK_POWER_DOWN_OFDM; +- status = ctrl_power_mode(state, &power_mode); ++ powerMode = DRXK_POWER_DOWN_OFDM; ++ status = CtrlPowerMode(state, &powerMode); + if (status < 0) + goto error; + + /* Stamp driver version number in SCU data RAM in BCD code +- Done to enable field application engineers to retrieve drxdriver version ++ Done to enable field application engineers to retreive drxdriver version + via I2C from SCU RAM. + Not using SCU command interface for SCU register access since no + microcode may be present. + */ +- driver_version = ++ driverVersion = + (((DRXK_VERSION_MAJOR / 100) % 10) << 12) + + (((DRXK_VERSION_MAJOR / 10) % 10) << 8) + + ((DRXK_VERSION_MAJOR % 10) << 4) + + (DRXK_VERSION_MINOR % 10); +- status = write16(state, SCU_RAM_DRIVER_VER_HI__A, +- driver_version); ++ status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion); + if (status < 0) + goto error; +- driver_version = ++ driverVersion = + (((DRXK_VERSION_PATCH / 1000) % 10) << 12) + + (((DRXK_VERSION_PATCH / 100) % 10) << 8) + + (((DRXK_VERSION_PATCH / 10) % 10) << 4) + + (DRXK_VERSION_PATCH % 10); +- status = write16(state, SCU_RAM_DRIVER_VER_LO__A, +- driver_version); ++ status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion); + if (status < 0) + goto error; + +- pr_info("DRXK driver version %d.%d.%d\n", ++ printk(KERN_INFO "DRXK driver version %d.%d.%d\n", + DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR, + DRXK_VERSION_PATCH); + +- /* +- * Dirty fix of default values for ROM/PATCH microcode +- * Dirty because this fix makes it impossible to setup +- * suitable values before calling DRX_Open. This solution +- * requires changes to RF AGC speed to be done via the CTRL +- * function after calling DRX_Open +- */ ++ /* Dirty fix of default values for ROM/PATCH microcode ++ Dirty because this fix makes it impossible to setup suitable values ++ before calling DRX_Open. This solution requires changes to RF AGC speed ++ to be done via the CTRL function after calling DRX_Open */ + +- /* m_dvbt_rf_agc_cfg.speed = 3; */ ++ /* m_dvbtRfAgcCfg.speed = 3; */ + + /* Reset driver debug flags to 0 */ + status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0); +@@ -6224,94 +6142,45 @@ static int init_drxk(struct drxk_state *state) + if (status < 0) + goto error; + /* MPEGTS functions are still the same */ +- status = mpegts_dto_init(state); ++ status = MPEGTSDtoInit(state); + if (status < 0) + goto error; +- status = mpegts_stop(state); ++ status = MPEGTSStop(state); + if (status < 0) + goto error; +- status = mpegts_configure_polarity(state); ++ status = MPEGTSConfigurePolarity(state); + if (status < 0) + goto error; +- status = mpegts_configure_pins(state, state->m_enable_mpeg_output); ++ status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput); + if (status < 0) + goto error; + /* added: configure GPIO */ +- status = write_gpio(state); ++ status = WriteGPIO(state); + if (status < 0) + goto error; + +- state->m_drxk_state = DRXK_STOPPED; ++ state->m_DrxkState = DRXK_STOPPED; + +- if (state->m_b_power_down) { +- status = power_down_device(state); ++ if (state->m_bPowerDown) { ++ status = PowerDownDevice(state); + if (status < 0) + goto error; +- state->m_drxk_state = DRXK_POWERED_DOWN; ++ state->m_DrxkState = DRXK_POWERED_DOWN; + } else +- state->m_drxk_state = DRXK_STOPPED; +- +- /* Initialize the supported delivery systems */ +- n = 0; +- if (state->m_has_dvbc) { +- state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; +- state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; +- strlcat(state->frontend.ops.info.name, " DVB-C", +- sizeof(state->frontend.ops.info.name)); +- } +- if (state->m_has_dvbt) { +- state->frontend.ops.delsys[n++] = SYS_DVBT; +- strlcat(state->frontend.ops.info.name, " DVB-T", +- sizeof(state->frontend.ops.info.name)); +- } +- drxk_i2c_unlock(state); ++ state->m_DrxkState = DRXK_STOPPED; + } + error: +- if (status < 0) { +- state->m_drxk_state = DRXK_NO_DEV; +- drxk_i2c_unlock(state); +- pr_err("Error %d on %s\n", status, __func__); +- } ++ if (status < 0) ++ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + + return status; + } + +-static void load_firmware_cb(const struct firmware *fw, +- void *context) +-{ +- struct drxk_state *state = context; +- +- dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded"); +- if (!fw) { +- pr_err("Could not load firmware file %s.\n", +- state->microcode_name); +- pr_info("Copy %s to your hotplug directory!\n", +- state->microcode_name); +- state->microcode_name = NULL; +- +- /* +- * As firmware is now load asynchronous, it is not possible +- * anymore to fail at frontend attach. We might silently +- * return here, and hope that the driver won't crash. +- * We might also change all DVB callbacks to return -ENODEV +- * if the device is not initialized. +- * As the DRX-K devices have their own internal firmware, +- * let's just hope that it will match a firmware revision +- * compatible with this driver and proceed. +- */ +- } +- state->fw = fw; +- +- init_drxk(state); +-} +- + static void drxk_release(struct dvb_frontend *fe) + { + struct drxk_state *state = fe->demodulator_priv; + + dprintk(1, "\n"); +- release_firmware(state->fw); +- + kfree(state); + } + +@@ -6320,13 +6189,7 @@ static int drxk_sleep(struct dvb_frontend *fe) + struct drxk_state *state = fe->demodulator_priv; + + dprintk(1, "\n"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return 0; +- +- shut_down(state); ++ ShutDown(state); + return 0; + } + +@@ -6334,11 +6197,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct drxk_state *state = fe->demodulator_priv; + +- dprintk(1, ": %s\n", enable ? "enable" : "disable"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- ++ dprintk(1, "%s\n", enable ? "enable" : "disable"); + return ConfigureI2CBridge(state, enable ? true : false); + } + +@@ -6351,14 +6210,9 @@ static int drxk_set_parameters(struct dvb_frontend *fe) + + dprintk(1, "\n"); + +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- + if (!fe->ops.tuner_ops.get_if_frequency) { +- pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); ++ printk(KERN_ERR ++ "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); + return -EINVAL; + } + +@@ -6373,23 +6227,22 @@ static int drxk_set_parameters(struct dvb_frontend *fe) + state->props = *p; + + if (old_delsys != delsys) { +- shut_down(state); ++ ShutDown(state); + switch (delsys) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: +- if (!state->m_has_dvbc) ++ if (!state->m_hasDVBC) + return -EINVAL; +- state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? +- true : false; ++ state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false; + if (state->m_itut_annex_c) +- setoperation_mode(state, OM_QAM_ITU_C); ++ SetOperationMode(state, OM_QAM_ITU_C); + else +- setoperation_mode(state, OM_QAM_ITU_A); ++ SetOperationMode(state, OM_QAM_ITU_A); + break; + case SYS_DVBT: +- if (!state->m_has_dvbt) ++ if (!state->m_hasDVBT) + return -EINVAL; +- setoperation_mode(state, OM_DVBT); ++ SetOperationMode(state, OM_DVBT); + break; + default: + return -EINVAL; +@@ -6397,261 +6250,35 @@ static int drxk_set_parameters(struct dvb_frontend *fe) + } + + fe->ops.tuner_ops.get_if_frequency(fe, &IF); +- start(state, 0, IF); +- +- /* After set_frontend, stats aren't available */ +- p->strength.stat[0].scale = FE_SCALE_RELATIVE; +- p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; ++ Start(state, 0, IF); + + /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */ + + return 0; + } + +-static int get_strength(struct drxk_state *state, u64 *strength) +-{ +- int status; +- struct s_cfg_agc rf_agc, if_agc; +- u32 total_gain = 0; +- u32 atten = 0; +- u32 agc_range = 0; +- u16 scu_lvl = 0; +- u16 scu_coc = 0; +- /* FIXME: those are part of the tuner presets */ +- u16 tuner_rf_gain = 50; /* Default value on az6007 driver */ +- u16 tuner_if_gain = 40; /* Default value on az6007 driver */ +- +- *strength = 0; +- +- if (is_dvbt(state)) { +- rf_agc = state->m_dvbt_rf_agc_cfg; +- if_agc = state->m_dvbt_if_agc_cfg; +- } else if (is_qam(state)) { +- rf_agc = state->m_qam_rf_agc_cfg; +- if_agc = state->m_qam_if_agc_cfg; +- } else { +- rf_agc = state->m_atv_rf_agc_cfg; +- if_agc = state->m_atv_if_agc_cfg; +- } +- +- if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { +- /* SCU output_level */ +- status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); +- if (status < 0) +- return status; +- +- /* SCU c.o.c. */ +- read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc); +- if (status < 0) +- return status; +- +- if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) +- rf_agc.output_level = scu_lvl + scu_coc; +- else +- rf_agc.output_level = 0xffff; +- +- /* Take RF gain into account */ +- total_gain += tuner_rf_gain; +- +- /* clip output value */ +- if (rf_agc.output_level < rf_agc.min_output_level) +- rf_agc.output_level = rf_agc.min_output_level; +- if (rf_agc.output_level > rf_agc.max_output_level) +- rf_agc.output_level = rf_agc.max_output_level; +- +- agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level); +- if (agc_range > 0) { +- atten += 100UL * +- ((u32)(tuner_rf_gain)) * +- ((u32)(rf_agc.output_level - rf_agc.min_output_level)) +- / agc_range; +- } +- } +- +- if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { +- status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, +- &if_agc.output_level); +- if (status < 0) +- return status; +- +- status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, +- &if_agc.top); +- if (status < 0) +- return status; +- +- /* Take IF gain into account */ +- total_gain += (u32) tuner_if_gain; +- +- /* clip output value */ +- if (if_agc.output_level < if_agc.min_output_level) +- if_agc.output_level = if_agc.min_output_level; +- if (if_agc.output_level > if_agc.max_output_level) +- if_agc.output_level = if_agc.max_output_level; +- +- agc_range = (u32)(if_agc.max_output_level - if_agc.min_output_level); +- if (agc_range > 0) { +- atten += 100UL * +- ((u32)(tuner_if_gain)) * +- ((u32)(if_agc.output_level - if_agc.min_output_level)) +- / agc_range; +- } +- } +- +- /* +- * Convert to 0..65535 scale. +- * If it can't be measured (AGC is disabled), just show 100%. +- */ +- if (total_gain > 0) +- *strength = (65535UL * atten / total_gain / 100); +- else +- *strength = 65535; +- +- return 0; +-} +- +-static int drxk_get_stats(struct dvb_frontend *fe) ++static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) + { +- struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct drxk_state *state = fe->demodulator_priv; +- int status; + u32 stat; +- u16 reg16; +- u32 post_bit_count; +- u32 post_bit_err_count; +- u32 post_bit_error_scale; +- u32 pre_bit_err_count; +- u32 pre_bit_count; +- u32 pkt_count; +- u32 pkt_error_count; +- s32 cnr; +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- +- /* get status */ +- state->fe_status = 0; +- get_lock_status(state, &stat); ++ ++ dprintk(1, "\n"); ++ *status = 0; ++ GetLockStatus(state, &stat, 0); + if (stat == MPEG_LOCK) +- state->fe_status |= 0x1f; ++ *status |= 0x1f; + if (stat == FEC_LOCK) +- state->fe_status |= 0x0f; ++ *status |= 0x0f; + if (stat == DEMOD_LOCK) +- state->fe_status |= 0x07; +- +- /* +- * Estimate signal strength from AGC +- */ +- get_strength(state, &c->strength.stat[0].uvalue); +- c->strength.stat[0].scale = FE_SCALE_RELATIVE; +- +- +- if (stat >= DEMOD_LOCK) { +- get_signal_to_noise(state, &cnr); +- c->cnr.stat[0].svalue = cnr * 100; +- c->cnr.stat[0].scale = FE_SCALE_DECIBEL; +- } else { +- c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- } +- +- if (stat < FEC_LOCK) { +- c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- return 0; +- } +- +- /* Get post BER */ +- +- /* BER measurement is valid if at least FEC lock is achieved */ +- +- /* +- * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be +- * written to set nr of symbols or bits over which to measure +- * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). +- */ +- +- /* Read registers for post/preViterbi BER calculation */ +- status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); +- if (status < 0) +- goto error; +- pre_bit_err_count = reg16; +- +- status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , ®16); +- if (status < 0) +- goto error; +- pre_bit_count = reg16; +- +- /* Number of bit-errors */ +- status = read16(state, FEC_RS_NR_BIT_ERRORS__A, ®16); +- if (status < 0) +- goto error; +- post_bit_err_count = reg16; +- +- status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, ®16); +- if (status < 0) +- goto error; +- post_bit_error_scale = reg16; +- +- status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, ®16); +- if (status < 0) +- goto error; +- pkt_count = reg16; +- +- status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, ®16); +- if (status < 0) +- goto error; +- pkt_error_count = reg16; +- write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); +- +- post_bit_err_count *= post_bit_error_scale; +- +- post_bit_count = pkt_count * 204 * 8; +- +- /* Store the results */ +- c->block_error.stat[0].scale = FE_SCALE_COUNTER; +- c->block_error.stat[0].uvalue += pkt_error_count; +- c->block_count.stat[0].scale = FE_SCALE_COUNTER; +- c->block_count.stat[0].uvalue += pkt_count; +- +- c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; +- c->pre_bit_error.stat[0].uvalue += pre_bit_err_count; +- c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; +- c->pre_bit_count.stat[0].uvalue += pre_bit_count; +- +- c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; +- c->post_bit_error.stat[0].uvalue += post_bit_err_count; +- c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; +- c->post_bit_count.stat[0].uvalue += post_bit_count; +- +-error: +- return status; ++ *status |= 0x07; ++ return 0; + } + +- +-static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) ++static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber) + { +- struct drxk_state *state = fe->demodulator_priv; +- int rc; +- + dprintk(1, "\n"); + +- rc = drxk_get_stats(fe); +- if (rc < 0) +- return rc; +- +- *status = state->fe_status; +- ++ *ber = 0; + return 0; + } + +@@ -6659,16 +6286,11 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) + { + struct drxk_state *state = fe->demodulator_priv; +- struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u32 val = 0; + + dprintk(1, "\n"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- +- *strength = c->strength.stat[0].uvalue; ++ ReadIFAgc(state, &val); ++ *strength = val & 0xffff; + return 0; + } + +@@ -6678,17 +6300,7 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr) + s32 snr2; + + dprintk(1, "\n"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- +- get_signal_to_noise(state, &snr2); +- +- /* No negative SNR, clip to zero */ +- if (snr2 < 0) +- snr2 = 0; ++ GetSignalToNoise(state, &snr2); + *snr = snr2 & 0xffff; + return 0; + } +@@ -6699,30 +6311,17 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) + u16 err; + + dprintk(1, "\n"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- +- dvbtqam_get_acc_pkt_err(state, &err); ++ DVBTQAMGetAccPktErr(state, &err); + *ucblocks = (u32) err; + return 0; + } + +-static int drxk_get_tune_settings(struct dvb_frontend *fe, +- struct dvb_frontend_tune_settings *sets) ++static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings ++ *sets) + { +- struct drxk_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + + dprintk(1, "\n"); +- +- if (state->m_drxk_state == DRXK_NO_DEV) +- return -ENODEV; +- if (state->m_drxk_state == DRXK_UNINITIALIZED) +- return -EAGAIN; +- + switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: +@@ -6764,6 +6363,7 @@ static struct dvb_frontend_ops drxk_ops = { + .get_tune_settings = drxk_get_tune_settings, + + .read_status = drxk_read_status, ++ .read_ber = drxk_read_ber, + .read_signal_strength = drxk_read_signal_strength, + .read_snr = drxk_read_snr, + .read_ucblocks = drxk_read_ucblocks, +@@ -6772,10 +6372,10 @@ static struct dvb_frontend_ops drxk_ops = { + struct dvb_frontend *drxk_attach(const struct drxk_config *config, + struct i2c_adapter *i2c) + { +- struct dtv_frontend_properties *p; ++ int n; ++ + struct drxk_state *state = NULL; + u8 adr = config->adr; +- int status; + + dprintk(1, "\n"); + state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL); +@@ -6786,40 +6386,39 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, + state->demod_address = adr; + state->single_master = config->single_master; + state->microcode_name = config->microcode_name; +- state->qam_demod_parameter_count = config->qam_demod_parameter_count; + state->no_i2c_bridge = config->no_i2c_bridge; + state->antenna_gpio = config->antenna_gpio; + state->antenna_dvbt = config->antenna_dvbt; +- state->m_chunk_size = config->chunk_size; ++ state->m_ChunkSize = config->chunk_size; + state->enable_merr_cfg = config->enable_merr_cfg; + + if (config->dynamic_clk) { +- state->m_dvbt_static_clk = false; +- state->m_dvbc_static_clk = false; ++ state->m_DVBTStaticCLK = 0; ++ state->m_DVBCStaticCLK = 0; + } else { +- state->m_dvbt_static_clk = true; +- state->m_dvbc_static_clk = true; ++ state->m_DVBTStaticCLK = 1; ++ state->m_DVBCStaticCLK = 1; + } + + + if (config->mpeg_out_clk_strength) +- state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07; ++ state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; + else +- state->m_ts_clockk_strength = 0x06; ++ state->m_TSClockkStrength = 0x06; + + if (config->parallel_ts) +- state->m_enable_parallel = true; ++ state->m_enableParallel = true; + else +- state->m_enable_parallel = false; ++ state->m_enableParallel = false; + + /* NOTE: as more UIO bits will be used, add them to the mask */ +- state->uio_mask = config->antenna_gpio; ++ state->UIO_mask = config->antenna_gpio; + + /* Default gpio to DVB-C */ + if (!state->antenna_dvbt && state->antenna_gpio) +- state->m_gpio |= state->antenna_gpio; ++ state->m_GPIO |= state->antenna_gpio; + else +- state->m_gpio &= ~state->antenna_gpio; ++ state->m_GPIO &= ~state->antenna_gpio; + + mutex_init(&state->mutex); + +@@ -6827,45 +6426,28 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, + state->frontend.demodulator_priv = state; + + init_state(state); +- +- /* Load firmware and initialize DRX-K */ +- if (state->microcode_name) { +- const struct firmware *fw = NULL; +- +- status = request_firmware(&fw, state->microcode_name, +- state->i2c->dev.parent); +- if (status < 0) +- fw = NULL; +- load_firmware_cb(fw, state); +- } else if (init_drxk(state) < 0) ++ if (init_drxk(state) < 0) + goto error; + ++ /* Initialize the supported delivery systems */ ++ n = 0; ++ if (state->m_hasDVBC) { ++ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; ++ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; ++ strlcat(state->frontend.ops.info.name, " DVB-C", ++ sizeof(state->frontend.ops.info.name)); ++ } ++ if (state->m_hasDVBT) { ++ state->frontend.ops.delsys[n++] = SYS_DVBT; ++ strlcat(state->frontend.ops.info.name, " DVB-T", ++ sizeof(state->frontend.ops.info.name)); ++ } + +- /* Initialize stats */ +- p = &state->frontend.dtv_property_cache; +- p->strength.len = 1; +- p->cnr.len = 1; +- p->block_error.len = 1; +- p->block_count.len = 1; +- p->pre_bit_error.len = 1; +- p->pre_bit_count.len = 1; +- p->post_bit_error.len = 1; +- p->post_bit_count.len = 1; +- +- p->strength.stat[0].scale = FE_SCALE_RELATIVE; +- p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; +- +- pr_info("frontend initialized.\n"); ++ printk(KERN_INFO "drxk: frontend initialized.\n"); + return &state->frontend; + + error: +- pr_err("not found\n"); ++ printk(KERN_ERR "drxk: not found\n"); + kfree(state); + return NULL; + } +diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h +index bae9c71..4bbf841 100644 +--- a/drivers/media/dvb-frontends/drxk_hard.h ++++ b/drivers/media/dvb-frontends/drxk_hard.h +@@ -46,7 +46,7 @@ + #define IQM_RC_ADJ_SEL_B_QAM 0x1 + #define IQM_RC_ADJ_SEL_B_VSB 0x2 + +-enum operation_mode { ++enum OperationMode { + OM_NONE, + OM_QAM_ITU_A, + OM_QAM_ITU_B, +@@ -54,7 +54,7 @@ enum operation_mode { + OM_DVBT + }; + +-enum drx_power_mode { ++enum DRXPowerMode { + DRX_POWER_UP = 0, + DRX_POWER_MODE_1, + DRX_POWER_MODE_2, +@@ -77,38 +77,25 @@ enum drx_power_mode { + }; + + +-/* Intermediate power mode for DRXK, power down OFDM clock domain */ ++/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */ + #ifndef DRXK_POWER_DOWN_OFDM + #define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1 + #endif + +-/* Intermediate power mode for DRXK, power down core (sysclk) */ ++/** /brief Intermediate power mode for DRXK, power down core (sysclk) */ + #ifndef DRXK_POWER_DOWN_CORE + #define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9 + #endif + +-/* Intermediate power mode for DRXK, power down pll (only osc runs) */ ++/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */ + #ifndef DRXK_POWER_DOWN_PLL + #define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10 + #endif + + +-enum agc_ctrl_mode { +- DRXK_AGC_CTRL_AUTO = 0, +- DRXK_AGC_CTRL_USER, +- DRXK_AGC_CTRL_OFF +-}; +- +-enum e_drxk_state { +- DRXK_UNINITIALIZED = 0, +- DRXK_STOPPED, +- DRXK_DTV_STARTED, +- DRXK_ATV_STARTED, +- DRXK_POWERED_DOWN, +- DRXK_NO_DEV /* If drxk init failed */ +-}; +- +-enum e_drxk_coef_array_index { ++enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; ++enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN }; ++enum EDrxkCoefArrayIndex { + DRXK_COEF_IDX_MN = 0, + DRXK_COEF_IDX_FM , + DRXK_COEF_IDX_L , +@@ -118,13 +105,13 @@ enum e_drxk_coef_array_index { + DRXK_COEF_IDX_I , + DRXK_COEF_IDX_MAX + }; +-enum e_drxk_sif_attenuation { ++enum EDrxkSifAttenuation { + DRXK_SIF_ATTENUATION_0DB, + DRXK_SIF_ATTENUATION_3DB, + DRXK_SIF_ATTENUATION_6DB, + DRXK_SIF_ATTENUATION_9DB + }; +-enum e_drxk_constellation { ++enum EDrxkConstellation { + DRX_CONSTELLATION_BPSK = 0, + DRX_CONSTELLATION_QPSK, + DRX_CONSTELLATION_PSK8, +@@ -138,7 +125,7 @@ enum e_drxk_constellation { + DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, + DRX_CONSTELLATION_AUTO = DRX_AUTO + }; +-enum e_drxk_interleave_mode { ++enum EDrxkInterleaveMode { + DRXK_QAM_I12_J17 = 16, + DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN + }; +@@ -149,14 +136,14 @@ enum { + DRXK_SPIN_UNKNOWN + }; + +-enum drxk_cfg_dvbt_sqi_speed { ++enum DRXKCfgDvbtSqiSpeed { + DRXK_DVBT_SQI_SPEED_FAST = 0, + DRXK_DVBT_SQI_SPEED_MEDIUM, + DRXK_DVBT_SQI_SPEED_SLOW, + DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN + } ; + +-enum drx_fftmode_t { ++enum DRXFftmode_t { + DRX_FFTMODE_2K = 0, + DRX_FFTMODE_4K, + DRX_FFTMODE_8K, +@@ -164,47 +151,47 @@ enum drx_fftmode_t { + DRX_FFTMODE_AUTO = DRX_AUTO + }; + +-enum drxmpeg_str_width_t { ++enum DRXMPEGStrWidth_t { + DRX_MPEG_STR_WIDTH_1, + DRX_MPEG_STR_WIDTH_8 + }; + +-enum drx_qam_lock_range_t { ++enum DRXQamLockRange_t { + DRX_QAM_LOCKRANGE_NORMAL, + DRX_QAM_LOCKRANGE_EXTENDED + }; + +-struct drxk_cfg_dvbt_echo_thres_t { ++struct DRXKCfgDvbtEchoThres_t { + u16 threshold; +- enum drx_fftmode_t fft_mode; ++ enum DRXFftmode_t fftMode; + } ; + +-struct s_cfg_agc { +- enum agc_ctrl_mode ctrl_mode; /* off, user, auto */ +- u16 output_level; /* range dependent on AGC */ +- u16 min_output_level; /* range dependent on AGC */ +- u16 max_output_level; /* range dependent on AGC */ ++struct SCfgAgc { ++ enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */ ++ u16 outputLevel; /* range dependent on AGC */ ++ u16 minOutputLevel; /* range dependent on AGC */ ++ u16 maxOutputLevel; /* range dependent on AGC */ + u16 speed; /* range dependent on AGC */ + u16 top; /* rf-agc take over point */ +- u16 cut_off_current; /* rf-agc is accelerated if output current ++ u16 cutOffCurrent; /* rf-agc is accelerated if output current + is below cut-off current */ +- u16 ingain_tgt_max; +- u16 fast_clip_ctrl_delay; ++ u16 IngainTgtMax; ++ u16 FastClipCtrlDelay; + }; + +-struct s_cfg_pre_saw { ++struct SCfgPreSaw { + u16 reference; /* pre SAW reference value, range 0 .. 31 */ +- bool use_pre_saw; /* TRUE algorithms must use pre SAW sense */ ++ bool usePreSaw; /* TRUE algorithms must use pre SAW sense */ + }; + +-struct drxk_ofdm_sc_cmd_t { +- u16 cmd; /* Command number */ +- u16 subcmd; /* Sub-command parameter*/ +- u16 param0; /* General purpous param */ +- u16 param1; /* General purpous param */ +- u16 param2; /* General purpous param */ +- u16 param3; /* General purpous param */ +- u16 param4; /* General purpous param */ ++struct DRXKOfdmScCmd_t { ++ u16 cmd; /**< Command number */ ++ u16 subcmd; /**< Sub-command parameter*/ ++ u16 param0; /**< General purpous param */ ++ u16 param1; /**< General purpous param */ ++ u16 param2; /**< General purpous param */ ++ u16 param3; /**< General purpous param */ ++ u16 param4; /**< General purpous param */ + }; + + struct drxk_state { +@@ -218,131 +205,132 @@ struct drxk_state { + + struct mutex mutex; + +- u32 m_instance; /* Channel 1,2,3 or 4 */ +- +- int m_chunk_size; +- u8 chunk[256]; +- +- bool m_has_lna; +- bool m_has_dvbt; +- bool m_has_dvbc; +- bool m_has_audio; +- bool m_has_atv; +- bool m_has_oob; +- bool m_has_sawsw; /* TRUE if mat_tx is available */ +- bool m_has_gpio1; /* TRUE if mat_rx is available */ +- bool m_has_gpio2; /* TRUE if GPIO is available */ +- bool m_has_irqn; /* TRUE if IRQN is available */ +- u16 m_osc_clock_freq; +- u16 m_hi_cfg_timing_div; +- u16 m_hi_cfg_bridge_delay; +- u16 m_hi_cfg_wake_up_key; +- u16 m_hi_cfg_timeout; +- u16 m_hi_cfg_ctrl; +- s32 m_sys_clock_freq; /* system clock frequency in kHz */ +- +- enum e_drxk_state m_drxk_state; /* State of Drxk (init,stopped,started) */ +- enum operation_mode m_operation_mode; /* digital standards */ +- struct s_cfg_agc m_vsb_rf_agc_cfg; /* settings for VSB RF-AGC */ +- struct s_cfg_agc m_vsb_if_agc_cfg; /* settings for VSB IF-AGC */ +- u16 m_vsb_pga_cfg; /* settings for VSB PGA */ +- struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /* settings for pre SAW sense */ +- s32 m_Quality83percent; /* MER level (*0.1 dB) for 83% quality indication */ +- s32 m_Quality93percent; /* MER level (*0.1 dB) for 93% quality indication */ +- bool m_smart_ant_inverted; +- bool m_b_debug_enable_bridge; +- bool m_b_p_down_open_bridge; /* only open DRXK bridge before power-down once it has been accessed */ +- bool m_b_power_down; /* Power down when not used */ +- +- u32 m_iqm_fs_rate_ofs; /* frequency shift as written to DRXK register (28bit fixpoint) */ +- +- bool m_enable_mpeg_output; /* If TRUE, enable MPEG output */ +- bool m_insert_rs_byte; /* If TRUE, insert RS byte */ +- bool m_enable_parallel; /* If TRUE, parallel out otherwise serial */ +- bool m_invert_data; /* If TRUE, invert DATA signals */ +- bool m_invert_err; /* If TRUE, invert ERR signal */ +- bool m_invert_str; /* If TRUE, invert STR signals */ +- bool m_invert_val; /* If TRUE, invert VAL signals */ +- bool m_invert_clk; /* If TRUE, invert CLK signals */ +- bool m_dvbc_static_clk; +- bool m_dvbt_static_clk; /* If TRUE, static MPEG clockrate will ++ u32 m_Instance; /**< Channel 1,2,3 or 4 */ ++ ++ int m_ChunkSize; ++ u8 Chunk[256]; ++ ++ bool m_hasLNA; ++ bool m_hasDVBT; ++ bool m_hasDVBC; ++ bool m_hasAudio; ++ bool m_hasATV; ++ bool m_hasOOB; ++ bool m_hasSAWSW; /**< TRUE if mat_tx is available */ ++ bool m_hasGPIO1; /**< TRUE if mat_rx is available */ ++ bool m_hasGPIO2; /**< TRUE if GPIO is available */ ++ bool m_hasIRQN; /**< TRUE if IRQN is available */ ++ u16 m_oscClockFreq; ++ u16 m_HICfgTimingDiv; ++ u16 m_HICfgBridgeDelay; ++ u16 m_HICfgWakeUpKey; ++ u16 m_HICfgTimeout; ++ u16 m_HICfgCtrl; ++ s32 m_sysClockFreq; /**< system clock frequency in kHz */ ++ ++ enum EDrxkState m_DrxkState; /**< State of Drxk (init,stopped,started) */ ++ enum OperationMode m_OperationMode; /**< digital standards */ ++ struct SCfgAgc m_vsbRfAgcCfg; /**< settings for VSB RF-AGC */ ++ struct SCfgAgc m_vsbIfAgcCfg; /**< settings for VSB IF-AGC */ ++ u16 m_vsbPgaCfg; /**< settings for VSB PGA */ ++ struct SCfgPreSaw m_vsbPreSawCfg; /**< settings for pre SAW sense */ ++ s32 m_Quality83percent; /**< MER level (*0.1 dB) for 83% quality indication */ ++ s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ ++ bool m_smartAntInverted; ++ bool m_bDebugEnableBridge; ++ bool m_bPDownOpenBridge; /**< only open DRXK bridge before power-down once it has been accessed */ ++ bool m_bPowerDown; /**< Power down when not used */ ++ ++ u32 m_IqmFsRateOfs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ ++ ++ bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */ ++ bool m_insertRSByte; /**< If TRUE, insert RS byte */ ++ bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */ ++ bool m_invertDATA; /**< If TRUE, invert DATA signals */ ++ bool m_invertERR; /**< If TRUE, invert ERR signal */ ++ bool m_invertSTR; /**< If TRUE, invert STR signals */ ++ bool m_invertVAL; /**< If TRUE, invert VAL signals */ ++ bool m_invertCLK; /**< If TRUE, invert CLK signals */ ++ bool m_DVBCStaticCLK; ++ bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will + be used, otherwise clockrate will + adapt to the bitrate of the TS */ +- u32 m_dvbt_bitrate; +- u32 m_dvbc_bitrate; ++ u32 m_DVBTBitrate; ++ u32 m_DVBCBitrate; + +- u8 m_ts_data_strength; +- u8 m_ts_clockk_strength; ++ u8 m_TSDataStrength; ++ u8 m_TSClockkStrength; + + bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ + +- enum drxmpeg_str_width_t m_width_str; /* MPEG start width */ +- u32 m_mpeg_ts_static_bitrate; /* Maximum bitrate in b/s in case ++ enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width */ ++ u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case + static clockrate is selected */ + +- /* LARGE_INTEGER m_startTime; */ /* Contains the time of the last demod start */ +- s32 m_mpeg_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ +- s32 m_demod_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ +- +- bool m_disable_te_ihandling; +- +- bool m_rf_agc_pol; +- bool m_if_agc_pol; +- +- struct s_cfg_agc m_atv_rf_agc_cfg; /* settings for ATV RF-AGC */ +- struct s_cfg_agc m_atv_if_agc_cfg; /* settings for ATV IF-AGC */ +- struct s_cfg_pre_saw m_atv_pre_saw_cfg; /* settings for ATV pre SAW sense */ +- bool m_phase_correction_bypass; +- s16 m_atv_top_vid_peak; +- u16 m_atv_top_noise_th; +- enum e_drxk_sif_attenuation m_sif_attenuation; +- bool m_enable_cvbs_output; +- bool m_enable_sif_output; +- bool m_b_mirror_freq_spect; +- enum e_drxk_constellation m_constellation; /* constellation type of the channel */ +- u32 m_curr_symbol_rate; /* Current QAM symbol rate */ +- struct s_cfg_agc m_qam_rf_agc_cfg; /* settings for QAM RF-AGC */ +- struct s_cfg_agc m_qam_if_agc_cfg; /* settings for QAM IF-AGC */ +- u16 m_qam_pga_cfg; /* settings for QAM PGA */ +- struct s_cfg_pre_saw m_qam_pre_saw_cfg; /* settings for QAM pre SAW sense */ +- enum e_drxk_interleave_mode m_qam_interleave_mode; /* QAM Interleave mode */ +- u16 m_fec_rs_plen; +- u16 m_fec_rs_prescale; +- +- enum drxk_cfg_dvbt_sqi_speed m_sqi_speed; +- +- u16 m_gpio; +- u16 m_gpio_cfg; +- +- struct s_cfg_agc m_dvbt_rf_agc_cfg; /* settings for QAM RF-AGC */ +- struct s_cfg_agc m_dvbt_if_agc_cfg; /* settings for QAM IF-AGC */ +- struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /* settings for QAM pre SAW sense */ +- +- u16 m_agcfast_clip_ctrl_delay; +- bool m_adc_comp_passed; ++ /* LARGE_INTEGER m_StartTime; */ /**< Contains the time of the last demod start */ ++ s32 m_MpegLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ ++ s32 m_DemodLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ ++ ++ bool m_disableTEIhandling; ++ ++ bool m_RfAgcPol; ++ bool m_IfAgcPol; ++ ++ struct SCfgAgc m_atvRfAgcCfg; /**< settings for ATV RF-AGC */ ++ struct SCfgAgc m_atvIfAgcCfg; /**< settings for ATV IF-AGC */ ++ struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */ ++ bool m_phaseCorrectionBypass; ++ s16 m_atvTopVidPeak; ++ u16 m_atvTopNoiseTh; ++ enum EDrxkSifAttenuation m_sifAttenuation; ++ bool m_enableCVBSOutput; ++ bool m_enableSIFOutput; ++ bool m_bMirrorFreqSpect; ++ enum EDrxkConstellation m_Constellation; /**< Constellation type of the channel */ ++ u32 m_CurrSymbolRate; /**< Current QAM symbol rate */ ++ struct SCfgAgc m_qamRfAgcCfg; /**< settings for QAM RF-AGC */ ++ struct SCfgAgc m_qamIfAgcCfg; /**< settings for QAM IF-AGC */ ++ u16 m_qamPgaCfg; /**< settings for QAM PGA */ ++ struct SCfgPreSaw m_qamPreSawCfg; /**< settings for QAM pre SAW sense */ ++ enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */ ++ u16 m_fecRsPlen; ++ u16 m_fecRsPrescale; ++ ++ enum DRXKCfgDvbtSqiSpeed m_sqiSpeed; ++ ++ u16 m_GPIO; ++ u16 m_GPIOCfg; ++ ++ struct SCfgAgc m_dvbtRfAgcCfg; /**< settings for QAM RF-AGC */ ++ struct SCfgAgc m_dvbtIfAgcCfg; /**< settings for QAM IF-AGC */ ++ struct SCfgPreSaw m_dvbtPreSawCfg; /**< settings for QAM pre SAW sense */ ++ ++ u16 m_agcFastClipCtrlDelay; ++ bool m_adcCompPassed; + u16 m_adcCompCoef[64]; +- u16 m_adc_state; ++ u16 m_adcState; + + u8 *m_microcode; + int m_microcode_length; +- bool m_drxk_a3_rom_code; +- bool m_drxk_a3_patch_code; ++ bool m_DRXK_A1_PATCH_CODE; ++ bool m_DRXK_A1_ROM_CODE; ++ bool m_DRXK_A2_ROM_CODE; ++ bool m_DRXK_A3_ROM_CODE; ++ bool m_DRXK_A2_PATCH_CODE; ++ bool m_DRXK_A3_PATCH_CODE; + + bool m_rfmirror; +- u8 m_device_spin; +- u32 m_iqm_rc_rate; +- +- enum drx_power_mode m_current_power_mode; ++ u8 m_deviceSpin; ++ u32 m_iqmRcRate; + +- /* when true, avoids other devices to use the I2C bus */ +- bool drxk_i2c_exclusive_lock; ++ enum DRXPowerMode m_currentPowerMode; + + /* + * Configurable parameters at the driver. They stores the values found + * at struct drxk_config. + */ + +- u16 uio_mask; /* Bits used by UIO */ ++ u16 UIO_mask; /* Bits used by UIO */ + + bool enable_merr_cfg; + bool single_master; +@@ -350,13 +338,7 @@ struct drxk_state { + bool antenna_dvbt; + u16 antenna_gpio; + +- fe_status_t fe_status; +- +- /* Firmware */ + const char *microcode_name; +- struct completion fw_wait_load; +- const struct firmware *fw; +- int qam_demod_parameter_count; + }; + + #define NEVER_LOCK 0 +diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h +index 761613f..23e16c1 100644 +--- a/drivers/media/dvb-frontends/drxk_map.h ++++ b/drivers/media/dvb-frontends/drxk_map.h +@@ -10,7 +10,6 @@ + #define FEC_RS_COMM_EXEC_STOP 0x0 + #define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012 + #define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013 +-#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014 + #define FEC_OC_MODE__A 0x1C40011 + #define FEC_OC_MODE_PARITY__M 0x1 + #define FEC_OC_DTO_MODE__A 0x1C40014 +@@ -130,8 +129,6 @@ + #define OFDM_EC_SB_PRIOR__A 0x3410013 + #define OFDM_EC_SB_PRIOR_HI 0x0 + #define OFDM_EC_SB_PRIOR_LO 0x1 +-#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017 +-#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018 + #define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054 + #define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3 + #define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2 +diff --git a/drivers/media/dvb-frontends/lnbh25.c b/drivers/media/dvb-frontends/lnbh25.c +new file mode 100644 +index 0000000..f167e67 +--- /dev/null ++++ b/drivers/media/dvb-frontends/lnbh25.c +@@ -0,0 +1,153 @@ ++/* ++ * Driver for the ST LNBH25 ++ * ++ * Copyright (C) 2014 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "lnbh25.h" ++ ++struct lnbh25 { ++ struct i2c_adapter *i2c; ++ u8 adr; ++ u8 reg[4]; ++ u8 boost; ++}; ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ pr_err("lnbh25: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len) ++{ ++ u8 d[5]; ++ ++ memcpy(&d[1], &lnbh->reg[reg], len); ++ d[0] = reg + 2; ++ return i2c_write(lnbh->i2c, lnbh->adr, d, len + 1); ++} ++ ++static int lnbh25_set_voltage(struct dvb_frontend *fe, ++ fe_sec_voltage_t voltage) ++{ ++ struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ lnbh->reg[0] = 0x00; ++ lnbh->reg[1] &= ~0x01; /* Disable Tone */ ++ lnbh->reg[2] = 0x00; ++ return lnbh25_write_regs(lnbh, 0, 3); ++ case SEC_VOLTAGE_13: ++ lnbh->reg[0] = lnbh->boost + 1; ++ break; ++ case SEC_VOLTAGE_18: ++ lnbh->reg[0] = lnbh->boost + 8; ++ break; ++ default: ++ return -EINVAL; ++ }; ++ ++ if (lnbh->reg[0] == 0x00) { ++ lnbh->reg[2] = 4; ++ lnbh25_write_regs(lnbh, 2, 2); ++ } else if (lnbh->reg[2] != 0x00) { ++ lnbh->reg[2] = 0; ++ lnbh25_write_regs(lnbh, 2, 2); ++ } ++ lnbh->reg[1] |= 0x01; ++ return lnbh25_write_regs(lnbh, 0, 3); ++} ++ ++static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) ++{ ++ struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; ++ ++ lnbh->boost = arg ? 3 : 0; ++ ++ return 0; ++} ++ ++static int lnbh25_set_tone(struct dvb_frontend *fe, ++ fe_sec_tone_mode_t tone) ++{ ++ /* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */ ++ ++ return 0; ++} ++ ++static int lnbh25_init(struct lnbh25 *lnbh) ++{ ++ return lnbh25_write_regs(lnbh, 0, 2); ++} ++ ++static void lnbh25_release(struct dvb_frontend *fe) ++{ ++ kfree(fe->sec_priv); ++ fe->sec_priv = NULL; ++} ++ ++struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ u8 adr) ++{ ++ struct lnbh25 *lnbh = kzalloc(sizeof(struct lnbh25), GFP_KERNEL); ++ if (!lnbh) ++ return NULL; ++ ++ lnbh->i2c = i2c; ++ lnbh->adr = adr; ++ lnbh->boost = 3; ++ ++ if (lnbh25_init(lnbh)) { ++ kfree(lnbh); ++ return NULL; ++ } ++ fe->sec_priv = lnbh; ++ fe->ops.set_voltage = lnbh25_set_voltage; ++ fe->ops.enable_high_lnb_voltage = lnbh25_enable_high_lnb_voltage; ++ fe->ops.release_sec = lnbh25_release; ++ ++ pr_info("LNB25 on %02x\n", lnbh->adr); ++ ++ return fe; ++} ++EXPORT_SYMBOL(lnbh25_attach); ++ ++MODULE_DESCRIPTION("LNBH25"); ++MODULE_AUTHOR("Ralph Metzler"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/lnbh25.h b/drivers/media/dvb-frontends/lnbh25.h +new file mode 100644 +index 0000000..4e8b3cc +--- /dev/null ++++ b/drivers/media/dvb-frontends/lnbh25.h +@@ -0,0 +1,28 @@ ++/* ++ * lnbh25.h ++ */ ++ ++#ifndef _LNBH25_H ++#define _LNBH25_H ++ ++#include ++ ++#if defined(CONFIG_DVB_LNBH25) || \ ++ (defined(CONFIG_DVB_LNBH25_MODULE) && defined(MODULE)) ++ ++extern struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ u8 i2c_addr); ++#else ++ ++static inline struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ u8 i2c_addr) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c +new file mode 100644 +index 0000000..64f7970 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd.c +@@ -0,0 +1,2331 @@ ++/* ++ * stv0367dd: STV0367 DVB-C/T demodulator driver ++ * ++ * Copyright (C) 2011 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "stv0367dd.h" ++#include "stv0367dd_regs.h" ++ ++enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C }; ++enum { QAM_MOD_QAM4 = 0, ++ QAM_MOD_QAM16, ++ QAM_MOD_QAM32, ++ QAM_MOD_QAM64, ++ QAM_MOD_QAM128, ++ QAM_MOD_QAM256, ++ QAM_MOD_QAM512, ++ QAM_MOD_QAM1024 ++}; ++ ++enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED }; ++ ++enum { ++ QAM_FEC_A = 1, /* J83 Annex A */ ++ QAM_FEC_B = (1<<1), /* J83 Annex B */ ++ QAM_FEC_C = (1<<2) /* J83 Annex C */ ++}; ++ ++enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted }; ++ ++struct stv_state { ++#ifdef USE_API3 ++ struct dvb_frontend c_frontend; ++ struct dvb_frontend t_frontend; ++#else ++ struct dvb_frontend frontend; ++#endif ++ fe_modulation_t modulation; ++ u32 symbol_rate; ++ u32 bandwidth; ++ struct device *dev; ++ ++ struct i2c_adapter *i2c; ++ u8 adr; ++ void *priv; ++ ++ struct mutex mutex; ++ struct mutex ctlock; ++ ++ u32 master_clock; ++ u32 adc_clock; ++ u8 ID; ++ u8 I2CRPT; ++ u32 omode; ++ u8 qam_inversion; ++ ++ s32 IF; ++ ++ s32 m_FECTimeOut; ++ s32 m_DemodTimeOut; ++ s32 m_SignalTimeOut; ++ s32 m_DemodLockTime; ++ s32 m_FFTTimeOut; ++ s32 m_TSTimeOut; ++ ++ bool m_bFirstTimeLock; ++ ++ u8 m_Save_QAM_AGC_CTL; ++ ++ enum EDemodState demod_state; ++ ++ u8 m_OFDM_FFTMode; // 0 = 2k, 1 = 8k, 2 = 4k ++ u8 m_OFDM_Modulation; // ++ u8 m_OFDM_FEC; // ++ u8 m_OFDM_Guard; ++ ++ u32 ucblocks; ++ u32 ber; ++}; ++ ++struct init_table { ++ u16 adr; ++ u8 data; ++}; ++ ++struct init_table base_init[] = { ++ { R367_IOCFG0, 0x80 }, ++ { R367_DAC0R, 0x00 }, ++ { R367_IOCFG1, 0x00 }, ++ { R367_DAC1R, 0x00 }, ++ { R367_IOCFG2, 0x00 }, ++ { R367_SDFR, 0x00 }, ++ { R367_AUX_CLK, 0x00 }, ++ { R367_FREESYS1, 0x00 }, ++ { R367_FREESYS2, 0x00 }, ++ { R367_FREESYS3, 0x00 }, ++ { R367_GPIO_CFG, 0x55 }, ++ { R367_GPIO_CMD, 0x01 }, ++ { R367_TSTRES, 0x00 }, ++ { R367_ANACTRL, 0x00 }, ++ { R367_TSTBUS, 0x00 }, ++ { R367_RF_AGC2, 0x20 }, ++ { R367_ANADIGCTRL, 0x0b }, ++ { R367_PLLMDIV, 0x01 }, ++ { R367_PLLNDIV, 0x08 }, ++ { R367_PLLSETUP, 0x18 }, ++ { R367_DUAL_AD12, 0x04 }, ++ { R367_TSTBIST, 0x00 }, ++ { 0x0000, 0x00 } ++}; ++ ++struct init_table qam_init[] = { ++ { R367_QAM_CTRL_1, 0x06 },// Orginal 0x04 ++ { R367_QAM_CTRL_2, 0x03 }, ++ { R367_QAM_IT_STATUS1, 0x2b }, ++ { R367_QAM_IT_STATUS2, 0x08 }, ++ { R367_QAM_IT_EN1, 0x00 }, ++ { R367_QAM_IT_EN2, 0x00 }, ++ { R367_QAM_CTRL_STATUS, 0x04 }, ++ { R367_QAM_TEST_CTL, 0x00 }, ++ { R367_QAM_AGC_CTL, 0x73 }, ++ { R367_QAM_AGC_IF_CFG, 0x50 }, ++ { R367_QAM_AGC_RF_CFG, 0x02 },// RF Freeze ++ { R367_QAM_AGC_PWM_CFG, 0x03 }, ++ { R367_QAM_AGC_PWR_REF_L, 0x5a }, ++ { R367_QAM_AGC_PWR_REF_H, 0x00 }, ++ { R367_QAM_AGC_RF_TH_L, 0xff }, ++ { R367_QAM_AGC_RF_TH_H, 0x07 }, ++ { R367_QAM_AGC_IF_LTH_L, 0x00 }, ++ { R367_QAM_AGC_IF_LTH_H, 0x08 }, ++ { R367_QAM_AGC_IF_HTH_L, 0xff }, ++ { R367_QAM_AGC_IF_HTH_H, 0x07 }, ++ { R367_QAM_AGC_PWR_RD_L, 0xa0 }, ++ { R367_QAM_AGC_PWR_RD_M, 0xe9 }, ++ { R367_QAM_AGC_PWR_RD_H, 0x03 }, ++ { R367_QAM_AGC_PWM_IFCMD_L, 0xe4 }, ++ { R367_QAM_AGC_PWM_IFCMD_H, 0x00 }, ++ { R367_QAM_AGC_PWM_RFCMD_L, 0xff }, ++ { R367_QAM_AGC_PWM_RFCMD_H, 0x07 }, ++ { R367_QAM_IQDEM_CFG, 0x01 }, ++ { R367_QAM_MIX_NCO_LL, 0x22 }, ++ { R367_QAM_MIX_NCO_HL, 0x96 }, ++ { R367_QAM_MIX_NCO_HH, 0x55 }, ++ { R367_QAM_SRC_NCO_LL, 0xff }, ++ { R367_QAM_SRC_NCO_LH, 0x0c }, ++ { R367_QAM_SRC_NCO_HL, 0xf5 }, ++ { R367_QAM_SRC_NCO_HH, 0x20 }, ++ { R367_QAM_IQDEM_GAIN_SRC_L, 0x06 }, ++ { R367_QAM_IQDEM_GAIN_SRC_H, 0x01 }, ++ { R367_QAM_IQDEM_DCRM_CFG_LL, 0xfe }, ++ { R367_QAM_IQDEM_DCRM_CFG_LH, 0xff }, ++ { R367_QAM_IQDEM_DCRM_CFG_HL, 0x0f }, ++ { R367_QAM_IQDEM_DCRM_CFG_HH, 0x00 }, ++ { R367_QAM_IQDEM_ADJ_COEFF0, 0x34 }, ++ { R367_QAM_IQDEM_ADJ_COEFF1, 0xae }, ++ { R367_QAM_IQDEM_ADJ_COEFF2, 0x46 }, ++ { R367_QAM_IQDEM_ADJ_COEFF3, 0x77 }, ++ { R367_QAM_IQDEM_ADJ_COEFF4, 0x96 }, ++ { R367_QAM_IQDEM_ADJ_COEFF5, 0x69 }, ++ { R367_QAM_IQDEM_ADJ_COEFF6, 0xc7 }, ++ { R367_QAM_IQDEM_ADJ_COEFF7, 0x01 }, ++ { R367_QAM_IQDEM_ADJ_EN, 0x04 }, ++ { R367_QAM_IQDEM_ADJ_AGC_REF, 0x94 }, ++ { R367_QAM_ALLPASSFILT1, 0xc9 }, ++ { R367_QAM_ALLPASSFILT2, 0x2d }, ++ { R367_QAM_ALLPASSFILT3, 0xa3 }, ++ { R367_QAM_ALLPASSFILT4, 0xfb }, ++ { R367_QAM_ALLPASSFILT5, 0xf6 }, ++ { R367_QAM_ALLPASSFILT6, 0x45 }, ++ { R367_QAM_ALLPASSFILT7, 0x6f }, ++ { R367_QAM_ALLPASSFILT8, 0x7e }, ++ { R367_QAM_ALLPASSFILT9, 0x05 }, ++ { R367_QAM_ALLPASSFILT10, 0x0a }, ++ { R367_QAM_ALLPASSFILT11, 0x51 }, ++ { R367_QAM_TRL_AGC_CFG, 0x20 }, ++ { R367_QAM_TRL_LPF_CFG, 0x28 }, ++ { R367_QAM_TRL_LPF_ACQ_GAIN, 0x44 }, ++ { R367_QAM_TRL_LPF_TRK_GAIN, 0x22 }, ++ { R367_QAM_TRL_LPF_OUT_GAIN, 0x03 }, ++ { R367_QAM_TRL_LOCKDET_LTH, 0x04 }, ++ { R367_QAM_TRL_LOCKDET_HTH, 0x11 }, ++ { R367_QAM_TRL_LOCKDET_TRGVAL, 0x20 }, ++ { R367_QAM_IQ_QAM, 0x01 }, ++ { R367_QAM_FSM_STATE, 0xa0 }, ++ { R367_QAM_FSM_CTL, 0x08 }, ++ { R367_QAM_FSM_STS, 0x0c }, ++ { R367_QAM_FSM_SNR0_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR1_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR2_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR0_LTH, 0x00 }, ++ { R367_QAM_FSM_SNR1_LTH, 0x00 }, ++ { R367_QAM_FSM_EQA1_HTH, 0x00 }, ++ { R367_QAM_FSM_TEMPO, 0x32 }, ++ { R367_QAM_FSM_CONFIG, 0x03 }, ++ { R367_QAM_EQU_I_TESTTAP_L, 0x11 }, ++ { R367_QAM_EQU_I_TESTTAP_M, 0x00 }, ++ { R367_QAM_EQU_I_TESTTAP_H, 0x00 }, ++ { R367_QAM_EQU_TESTAP_CFG, 0x00 }, ++ { R367_QAM_EQU_Q_TESTTAP_L, 0xff }, ++ { R367_QAM_EQU_Q_TESTTAP_M, 0x00 }, ++ { R367_QAM_EQU_Q_TESTTAP_H, 0x00 }, ++ { R367_QAM_EQU_TAP_CTRL, 0x00 }, ++ { R367_QAM_EQU_CTR_CRL_CONTROL_L, 0x11 }, ++ { R367_QAM_EQU_CTR_CRL_CONTROL_H, 0x05 }, ++ { R367_QAM_EQU_CTR_HIPOW_L, 0x00 }, ++ { R367_QAM_EQU_CTR_HIPOW_H, 0x00 }, ++ { R367_QAM_EQU_I_EQU_LO, 0xef }, ++ { R367_QAM_EQU_I_EQU_HI, 0x00 }, ++ { R367_QAM_EQU_Q_EQU_LO, 0xee }, ++ { R367_QAM_EQU_Q_EQU_HI, 0x00 }, ++ { R367_QAM_EQU_MAPPER, 0xc5 }, ++ { R367_QAM_EQU_SWEEP_RATE, 0x80 }, ++ { R367_QAM_EQU_SNR_LO, 0x64 }, ++ { R367_QAM_EQU_SNR_HI, 0x03 }, ++ { R367_QAM_EQU_GAMMA_LO, 0x00 }, ++ { R367_QAM_EQU_GAMMA_HI, 0x00 }, ++ { R367_QAM_EQU_ERR_GAIN, 0x36 }, ++ { R367_QAM_EQU_RADIUS, 0xaa }, ++ { R367_QAM_EQU_FFE_MAINTAP, 0x00 }, ++ { R367_QAM_EQU_FFE_LEAKAGE, 0x63 }, ++ { R367_QAM_EQU_FFE_MAINTAP_POS, 0xdf }, ++ { R367_QAM_EQU_GAIN_WIDE, 0x88 }, ++ { R367_QAM_EQU_GAIN_NARROW, 0x41 }, ++ { R367_QAM_EQU_CTR_LPF_GAIN, 0xd1 }, ++ { R367_QAM_EQU_CRL_LPF_GAIN, 0xa7 }, ++ { R367_QAM_EQU_GLOBAL_GAIN, 0x06 }, ++ { R367_QAM_EQU_CRL_LD_SEN, 0x85 }, ++ { R367_QAM_EQU_CRL_LD_VAL, 0xe2 }, ++ { R367_QAM_EQU_CRL_TFR, 0x20 }, ++ { R367_QAM_EQU_CRL_BISTH_LO, 0x00 }, ++ { R367_QAM_EQU_CRL_BISTH_HI, 0x00 }, ++ { R367_QAM_EQU_SWEEP_RANGE_LO, 0x00 }, ++ { R367_QAM_EQU_SWEEP_RANGE_HI, 0x00 }, ++ { R367_QAM_EQU_CRL_LIMITER, 0x40 }, ++ { R367_QAM_EQU_MODULUS_MAP, 0x90 }, ++ { R367_QAM_EQU_PNT_GAIN, 0xa7 }, ++ { R367_QAM_FEC_AC_CTR_0, 0x16 }, ++ { R367_QAM_FEC_AC_CTR_1, 0x0b }, ++ { R367_QAM_FEC_AC_CTR_2, 0x88 }, ++ { R367_QAM_FEC_AC_CTR_3, 0x02 }, ++ { R367_QAM_FEC_STATUS, 0x12 }, ++ { R367_QAM_RS_COUNTER_0, 0x7d }, ++ { R367_QAM_RS_COUNTER_1, 0xd0 }, ++ { R367_QAM_RS_COUNTER_2, 0x19 }, ++ { R367_QAM_RS_COUNTER_3, 0x0b }, ++ { R367_QAM_RS_COUNTER_4, 0xa3 }, ++ { R367_QAM_RS_COUNTER_5, 0x00 }, ++ { R367_QAM_BERT_0, 0x01 }, ++ { R367_QAM_BERT_1, 0x25 }, ++ { R367_QAM_BERT_2, 0x41 }, ++ { R367_QAM_BERT_3, 0x39 }, ++ { R367_QAM_OUTFORMAT_0, 0xc2 }, ++ { R367_QAM_OUTFORMAT_1, 0x22 }, ++ { R367_QAM_SMOOTHER_2, 0x28 }, ++ { R367_QAM_TSMF_CTRL_0, 0x01 }, ++ { R367_QAM_TSMF_CTRL_1, 0xc6 }, ++ { R367_QAM_TSMF_CTRL_3, 0x43 }, ++ { R367_QAM_TS_ON_ID_0, 0x00 }, ++ { R367_QAM_TS_ON_ID_1, 0x00 }, ++ { R367_QAM_TS_ON_ID_2, 0x00 }, ++ { R367_QAM_TS_ON_ID_3, 0x00 }, ++ { R367_QAM_RE_STATUS_0, 0x00 }, ++ { R367_QAM_RE_STATUS_1, 0x00 }, ++ { R367_QAM_RE_STATUS_2, 0x00 }, ++ { R367_QAM_RE_STATUS_3, 0x00 }, ++ { R367_QAM_TS_STATUS_0, 0x00 }, ++ { R367_QAM_TS_STATUS_1, 0x00 }, ++ { R367_QAM_TS_STATUS_2, 0xa0 }, ++ { R367_QAM_TS_STATUS_3, 0x00 }, ++ { R367_QAM_T_O_ID_0, 0x00 }, ++ { R367_QAM_T_O_ID_1, 0x00 }, ++ { R367_QAM_T_O_ID_2, 0x00 }, ++ { R367_QAM_T_O_ID_3, 0x00 }, ++ { 0x0000, 0x00 } // EOT ++}; ++ ++struct init_table ofdm_init[] = { ++ //{R367_OFDM_ID ,0x60}, ++ //{R367_OFDM_I2CRPT ,0x22}, ++ //{R367_OFDM_TOPCTRL ,0x02}, ++ //{R367_OFDM_IOCFG0 ,0x40}, ++ //{R367_OFDM_DAC0R ,0x00}, ++ //{R367_OFDM_IOCFG1 ,0x00}, ++ //{R367_OFDM_DAC1R ,0x00}, ++ //{R367_OFDM_IOCFG2 ,0x62}, ++ //{R367_OFDM_SDFR ,0x00}, ++ //{R367_OFDM_STATUS ,0xf8}, ++ //{R367_OFDM_AUX_CLK ,0x0a}, ++ //{R367_OFDM_FREESYS1 ,0x00}, ++ //{R367_OFDM_FREESYS2 ,0x00}, ++ //{R367_OFDM_FREESYS3 ,0x00}, ++ //{R367_OFDM_GPIO_CFG ,0x55}, ++ //{R367_OFDM_GPIO_CMD ,0x00}, ++ {R367_OFDM_AGC2MAX ,0xff}, ++ {R367_OFDM_AGC2MIN ,0x00}, ++ {R367_OFDM_AGC1MAX ,0xff}, ++ {R367_OFDM_AGC1MIN ,0x00}, ++ {R367_OFDM_AGCR ,0xbc}, ++ {R367_OFDM_AGC2TH ,0x00}, ++ //{R367_OFDM_AGC12C ,0x01}, //Note: This defines AGC pins, also needed for QAM ++ {R367_OFDM_AGCCTRL1 ,0x85}, ++ {R367_OFDM_AGCCTRL2 ,0x1f}, ++ {R367_OFDM_AGC1VAL1 ,0x00}, ++ {R367_OFDM_AGC1VAL2 ,0x00}, ++ {R367_OFDM_AGC2VAL1 ,0x6f}, ++ {R367_OFDM_AGC2VAL2 ,0x05}, ++ {R367_OFDM_AGC2PGA ,0x00}, ++ {R367_OFDM_OVF_RATE1 ,0x00}, ++ {R367_OFDM_OVF_RATE2 ,0x00}, ++ {R367_OFDM_GAIN_SRC1 ,0x2b}, ++ {R367_OFDM_GAIN_SRC2 ,0x04}, ++ {R367_OFDM_INC_DEROT1 ,0x55}, ++ {R367_OFDM_INC_DEROT2 ,0x55}, ++ {R367_OFDM_PPM_CPAMP_DIR ,0x2c}, ++ {R367_OFDM_PPM_CPAMP_INV ,0x00}, ++ {R367_OFDM_FREESTFE_1 ,0x00}, ++ {R367_OFDM_FREESTFE_2 ,0x1c}, ++ {R367_OFDM_DCOFFSET ,0x00}, ++ {R367_OFDM_EN_PROCESS ,0x05}, ++ {R367_OFDM_SDI_SMOOTHER ,0x80}, ++ {R367_OFDM_FE_LOOP_OPEN ,0x1c}, ++ {R367_OFDM_FREQOFF1 ,0x00}, ++ {R367_OFDM_FREQOFF2 ,0x00}, ++ {R367_OFDM_FREQOFF3 ,0x00}, ++ {R367_OFDM_TIMOFF1 ,0x00}, ++ {R367_OFDM_TIMOFF2 ,0x00}, ++ {R367_OFDM_EPQ ,0x02}, ++ {R367_OFDM_EPQAUTO ,0x01}, ++ {R367_OFDM_SYR_UPDATE ,0xf5}, ++ {R367_OFDM_CHPFREE ,0x00}, ++ {R367_OFDM_PPM_STATE_MAC ,0x23}, ++ {R367_OFDM_INR_THRESHOLD ,0xff}, ++ {R367_OFDM_EPQ_TPS_ID_CELL ,0xf9}, ++ {R367_OFDM_EPQ_CFG ,0x00}, ++ {R367_OFDM_EPQ_STATUS ,0x01}, ++ {R367_OFDM_AUTORELOCK ,0x81}, ++ {R367_OFDM_BER_THR_VMSB ,0x00}, ++ {R367_OFDM_BER_THR_MSB ,0x00}, ++ {R367_OFDM_BER_THR_LSB ,0x00}, ++ {R367_OFDM_CCD ,0x83}, ++ {R367_OFDM_SPECTR_CFG ,0x00}, ++ {R367_OFDM_CHC_DUMMY ,0x18}, ++ {R367_OFDM_INC_CTL ,0x88}, ++ {R367_OFDM_INCTHRES_COR1 ,0xb4}, ++ {R367_OFDM_INCTHRES_COR2 ,0x96}, ++ {R367_OFDM_INCTHRES_DET1 ,0x0e}, ++ {R367_OFDM_INCTHRES_DET2 ,0x11}, ++ {R367_OFDM_IIR_CELLNB ,0x8d}, ++ {R367_OFDM_IIRCX_COEFF1_MSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF1_LSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF2_MSB ,0x09}, ++ {R367_OFDM_IIRCX_COEFF2_LSB ,0x18}, ++ {R367_OFDM_IIRCX_COEFF3_MSB ,0x14}, ++ {R367_OFDM_IIRCX_COEFF3_LSB ,0x9c}, ++ {R367_OFDM_IIRCX_COEFF4_MSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF4_LSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF5_MSB ,0x36}, ++ {R367_OFDM_IIRCX_COEFF5_LSB ,0x42}, ++ {R367_OFDM_FEPATH_CFG ,0x00}, ++ {R367_OFDM_PMC1_FUNC ,0x65}, ++ {R367_OFDM_PMC1_FOR ,0x00}, ++ {R367_OFDM_PMC2_FUNC ,0x00}, ++ {R367_OFDM_STATUS_ERR_DA ,0xe0}, ++ {R367_OFDM_DIG_AGC_R ,0xfe}, ++ {R367_OFDM_COMAGC_TARMSB ,0x0b}, ++ {R367_OFDM_COM_AGC_TAR_ENMODE ,0x41}, ++ {R367_OFDM_COM_AGC_CFG ,0x3e}, ++ {R367_OFDM_COM_AGC_GAIN1 ,0x39}, ++ {R367_OFDM_AUT_AGC_TARGETMSB ,0x0b}, ++ {R367_OFDM_LOCK_DET_MSB ,0x01}, ++ {R367_OFDM_AGCTAR_LOCK_LSBS ,0x40}, ++ {R367_OFDM_AUT_GAIN_EN ,0xf4}, ++ {R367_OFDM_AUT_CFG ,0xf0}, ++ {R367_OFDM_LOCKN ,0x23}, ++ {R367_OFDM_INT_X_3 ,0x00}, ++ {R367_OFDM_INT_X_2 ,0x03}, ++ {R367_OFDM_INT_X_1 ,0x8d}, ++ {R367_OFDM_INT_X_0 ,0xa0}, ++ {R367_OFDM_MIN_ERRX_MSB ,0x00}, ++ {R367_OFDM_COR_CTL ,0x00}, ++ {R367_OFDM_COR_STAT ,0xf6}, ++ {R367_OFDM_COR_INTEN ,0x00}, ++ {R367_OFDM_COR_INTSTAT ,0x3f}, ++ {R367_OFDM_COR_MODEGUARD ,0x03}, ++ {R367_OFDM_AGC_CTL ,0x08}, ++ {R367_OFDM_AGC_MANUAL1 ,0x00}, ++ {R367_OFDM_AGC_MANUAL2 ,0x00}, ++ {R367_OFDM_AGC_TARG ,0x16}, ++ {R367_OFDM_AGC_GAIN1 ,0x53}, ++ {R367_OFDM_AGC_GAIN2 ,0x1d}, ++ {R367_OFDM_RESERVED_1 ,0x00}, ++ {R367_OFDM_RESERVED_2 ,0x00}, ++ {R367_OFDM_RESERVED_3 ,0x00}, ++ {R367_OFDM_CAS_CTL ,0x44}, ++ {R367_OFDM_CAS_FREQ ,0xb3}, ++ {R367_OFDM_CAS_DAGCGAIN ,0x12}, ++ {R367_OFDM_SYR_CTL ,0x04}, ++ {R367_OFDM_SYR_STAT ,0x10}, ++ {R367_OFDM_SYR_NCO1 ,0x00}, ++ {R367_OFDM_SYR_NCO2 ,0x00}, ++ {R367_OFDM_SYR_OFFSET1 ,0x00}, ++ {R367_OFDM_SYR_OFFSET2 ,0x00}, ++ {R367_OFDM_FFT_CTL ,0x00}, ++ {R367_OFDM_SCR_CTL ,0x70}, ++ {R367_OFDM_PPM_CTL1 ,0xf8}, ++ {R367_OFDM_TRL_CTL ,0xac}, ++ {R367_OFDM_TRL_NOMRATE1 ,0x1e}, ++ {R367_OFDM_TRL_NOMRATE2 ,0x58}, ++ {R367_OFDM_TRL_TIME1 ,0x1d}, ++ {R367_OFDM_TRL_TIME2 ,0xfc}, ++ {R367_OFDM_CRL_CTL ,0x24}, ++ {R367_OFDM_CRL_FREQ1 ,0xad}, ++ {R367_OFDM_CRL_FREQ2 ,0x9d}, ++ {R367_OFDM_CRL_FREQ3 ,0xff}, ++ {R367_OFDM_CHC_CTL ,0x01}, ++ {R367_OFDM_CHC_SNR ,0xf0}, ++ {R367_OFDM_BDI_CTL ,0x00}, ++ {R367_OFDM_DMP_CTL ,0x00}, ++ {R367_OFDM_TPS_RCVD1 ,0x30}, ++ {R367_OFDM_TPS_RCVD2 ,0x02}, ++ {R367_OFDM_TPS_RCVD3 ,0x01}, ++ {R367_OFDM_TPS_RCVD4 ,0x00}, ++ {R367_OFDM_TPS_ID_CELL1 ,0x00}, ++ {R367_OFDM_TPS_ID_CELL2 ,0x00}, ++ {R367_OFDM_TPS_RCVD5_SET1 ,0x02}, ++ {R367_OFDM_TPS_SET2 ,0x02}, ++ {R367_OFDM_TPS_SET3 ,0x01}, ++ {R367_OFDM_TPS_CTL ,0x00}, ++ {R367_OFDM_CTL_FFTOSNUM ,0x34}, ++ {R367_OFDM_TESTSELECT ,0x09}, ++ {R367_OFDM_MSC_REV ,0x0a}, ++ {R367_OFDM_PIR_CTL ,0x00}, ++ {R367_OFDM_SNR_CARRIER1 ,0xa1}, ++ {R367_OFDM_SNR_CARRIER2 ,0x9a}, ++ {R367_OFDM_PPM_CPAMP ,0x2c}, ++ {R367_OFDM_TSM_AP0 ,0x00}, ++ {R367_OFDM_TSM_AP1 ,0x00}, ++ {R367_OFDM_TSM_AP2 ,0x00}, ++ {R367_OFDM_TSM_AP3 ,0x00}, ++ {R367_OFDM_TSM_AP4 ,0x00}, ++ {R367_OFDM_TSM_AP5 ,0x00}, ++ {R367_OFDM_TSM_AP6 ,0x00}, ++ {R367_OFDM_TSM_AP7 ,0x00}, ++ //{R367_OFDM_TSTRES ,0x00}, ++ //{R367_OFDM_ANACTRL ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/ ++ //{R367_OFDM_TSTBUS ,0x00}, ++ //{R367_OFDM_TSTRATE ,0x00}, ++ {R367_OFDM_CONSTMODE ,0x01}, ++ {R367_OFDM_CONSTCARR1 ,0x00}, ++ {R367_OFDM_CONSTCARR2 ,0x00}, ++ {R367_OFDM_ICONSTEL ,0x0a}, ++ {R367_OFDM_QCONSTEL ,0x15}, ++ {R367_OFDM_TSTBISTRES0 ,0x00}, ++ {R367_OFDM_TSTBISTRES1 ,0x00}, ++ {R367_OFDM_TSTBISTRES2 ,0x28}, ++ {R367_OFDM_TSTBISTRES3 ,0x00}, ++ //{R367_OFDM_RF_AGC1 ,0xff}, ++ //{R367_OFDM_RF_AGC2 ,0x83}, ++ //{R367_OFDM_ANADIGCTRL ,0x19}, ++ //{R367_OFDM_PLLMDIV ,0x0c}, ++ //{R367_OFDM_PLLNDIV ,0x55}, ++ //{R367_OFDM_PLLSETUP ,0x18}, ++ //{R367_OFDM_DUAL_AD12 ,0x00}, ++ //{R367_OFDM_TSTBIST ,0x00}, ++ //{R367_OFDM_PAD_COMP_CTRL ,0x00}, ++ //{R367_OFDM_PAD_COMP_WR ,0x00}, ++ //{R367_OFDM_PAD_COMP_RD ,0xe0}, ++ {R367_OFDM_SYR_TARGET_FFTADJT_MSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00}, ++ {R367_OFDM_SYR_FLAG ,0x00}, ++ {R367_OFDM_CRL_TARGET1 ,0x00}, ++ {R367_OFDM_CRL_TARGET2 ,0x00}, ++ {R367_OFDM_CRL_TARGET3 ,0x00}, ++ {R367_OFDM_CRL_TARGET4 ,0x00}, ++ {R367_OFDM_CRL_FLAG ,0x00}, ++ {R367_OFDM_TRL_TARGET1 ,0x00}, ++ {R367_OFDM_TRL_TARGET2 ,0x00}, ++ {R367_OFDM_TRL_CHC ,0x00}, ++ {R367_OFDM_CHC_SNR_TARG ,0x00}, ++ {R367_OFDM_TOP_TRACK ,0x00}, ++ {R367_OFDM_TRACKER_FREE1 ,0x00}, ++ {R367_OFDM_ERROR_CRL1 ,0x00}, ++ {R367_OFDM_ERROR_CRL2 ,0x00}, ++ {R367_OFDM_ERROR_CRL3 ,0x00}, ++ {R367_OFDM_ERROR_CRL4 ,0x00}, ++ {R367_OFDM_DEC_NCO1 ,0x2c}, ++ {R367_OFDM_DEC_NCO2 ,0x0f}, ++ {R367_OFDM_DEC_NCO3 ,0x20}, ++ {R367_OFDM_SNR ,0xf1}, ++ {R367_OFDM_SYR_FFTADJ1 ,0x00}, ++ {R367_OFDM_SYR_FFTADJ2 ,0x00}, ++ {R367_OFDM_SYR_CHCADJ1 ,0x00}, ++ {R367_OFDM_SYR_CHCADJ2 ,0x00}, ++ {R367_OFDM_SYR_OFF ,0x00}, ++ {R367_OFDM_PPM_OFFSET1 ,0x00}, ++ {R367_OFDM_PPM_OFFSET2 ,0x03}, ++ {R367_OFDM_TRACKER_FREE2 ,0x00}, ++ {R367_OFDM_DEBG_LT10 ,0x00}, ++ {R367_OFDM_DEBG_LT11 ,0x00}, ++ {R367_OFDM_DEBG_LT12 ,0x00}, ++ {R367_OFDM_DEBG_LT13 ,0x00}, ++ {R367_OFDM_DEBG_LT14 ,0x00}, ++ {R367_OFDM_DEBG_LT15 ,0x00}, ++ {R367_OFDM_DEBG_LT16 ,0x00}, ++ {R367_OFDM_DEBG_LT17 ,0x00}, ++ {R367_OFDM_DEBG_LT18 ,0x00}, ++ {R367_OFDM_DEBG_LT19 ,0x00}, ++ {R367_OFDM_DEBG_LT1A ,0x00}, ++ {R367_OFDM_DEBG_LT1B ,0x00}, ++ {R367_OFDM_DEBG_LT1C ,0x00}, ++ {R367_OFDM_DEBG_LT1D ,0x00}, ++ {R367_OFDM_DEBG_LT1E ,0x00}, ++ {R367_OFDM_DEBG_LT1F ,0x00}, ++ {R367_OFDM_RCCFGH ,0x00}, ++ {R367_OFDM_RCCFGM ,0x00}, ++ {R367_OFDM_RCCFGL ,0x00}, ++ {R367_OFDM_RCINSDELH ,0x00}, ++ {R367_OFDM_RCINSDELM ,0x00}, ++ {R367_OFDM_RCINSDELL ,0x00}, ++ {R367_OFDM_RCSTATUS ,0x00}, ++ {R367_OFDM_RCSPEED ,0x6f}, ++ {R367_OFDM_RCDEBUGM ,0xe7}, ++ {R367_OFDM_RCDEBUGL ,0x9b}, ++ {R367_OFDM_RCOBSCFG ,0x00}, ++ {R367_OFDM_RCOBSM ,0x00}, ++ {R367_OFDM_RCOBSL ,0x00}, ++ {R367_OFDM_RCFECSPY ,0x00}, ++ {R367_OFDM_RCFSPYCFG ,0x00}, ++ {R367_OFDM_RCFSPYDATA ,0x00}, ++ {R367_OFDM_RCFSPYOUT ,0x00}, ++ {R367_OFDM_RCFSTATUS ,0x00}, ++ {R367_OFDM_RCFGOODPACK ,0x00}, ++ {R367_OFDM_RCFPACKCNT ,0x00}, ++ {R367_OFDM_RCFSPYMISC ,0x00}, ++ {R367_OFDM_RCFBERCPT4 ,0x00}, ++ {R367_OFDM_RCFBERCPT3 ,0x00}, ++ {R367_OFDM_RCFBERCPT2 ,0x00}, ++ {R367_OFDM_RCFBERCPT1 ,0x00}, ++ {R367_OFDM_RCFBERCPT0 ,0x00}, ++ {R367_OFDM_RCFBERERR2 ,0x00}, ++ {R367_OFDM_RCFBERERR1 ,0x00}, ++ {R367_OFDM_RCFBERERR0 ,0x00}, ++ {R367_OFDM_RCFSTATESM ,0x00}, ++ {R367_OFDM_RCFSTATESL ,0x00}, ++ {R367_OFDM_RCFSPYBER ,0x00}, ++ {R367_OFDM_RCFSPYDISTM ,0x00}, ++ {R367_OFDM_RCFSPYDISTL ,0x00}, ++ {R367_OFDM_RCFSPYOBS7 ,0x00}, ++ {R367_OFDM_RCFSPYOBS6 ,0x00}, ++ {R367_OFDM_RCFSPYOBS5 ,0x00}, ++ {R367_OFDM_RCFSPYOBS4 ,0x00}, ++ {R367_OFDM_RCFSPYOBS3 ,0x00}, ++ {R367_OFDM_RCFSPYOBS2 ,0x00}, ++ {R367_OFDM_RCFSPYOBS1 ,0x00}, ++ {R367_OFDM_RCFSPYOBS0 ,0x00}, ++ //{R367_OFDM_TSGENERAL ,0x00}, ++ //{R367_OFDM_RC1SPEED ,0x6f}, ++ //{R367_OFDM_TSGSTATUS ,0x18}, ++ {R367_OFDM_FECM ,0x01}, ++ {R367_OFDM_VTH12 ,0xff}, ++ {R367_OFDM_VTH23 ,0xa1}, ++ {R367_OFDM_VTH34 ,0x64}, ++ {R367_OFDM_VTH56 ,0x40}, ++ {R367_OFDM_VTH67 ,0x00}, ++ {R367_OFDM_VTH78 ,0x2c}, ++ {R367_OFDM_VITCURPUN ,0x12}, ++ {R367_OFDM_VERROR ,0x01}, ++ {R367_OFDM_PRVIT ,0x3f}, ++ {R367_OFDM_VAVSRVIT ,0x00}, ++ {R367_OFDM_VSTATUSVIT ,0xbd}, ++ {R367_OFDM_VTHINUSE ,0xa1}, ++ {R367_OFDM_KDIV12 ,0x20}, ++ {R367_OFDM_KDIV23 ,0x40}, ++ {R367_OFDM_KDIV34 ,0x20}, ++ {R367_OFDM_KDIV56 ,0x30}, ++ {R367_OFDM_KDIV67 ,0x00}, ++ {R367_OFDM_KDIV78 ,0x30}, ++ {R367_OFDM_SIGPOWER ,0x54}, ++ {R367_OFDM_DEMAPVIT ,0x40}, ++ {R367_OFDM_VITSCALE ,0x00}, ++ {R367_OFDM_FFEC1PRG ,0x00}, ++ {R367_OFDM_FVITCURPUN ,0x12}, ++ {R367_OFDM_FVERROR ,0x01}, ++ {R367_OFDM_FVSTATUSVIT ,0xbd}, ++ {R367_OFDM_DEBUG_LT1 ,0x00}, ++ {R367_OFDM_DEBUG_LT2 ,0x00}, ++ {R367_OFDM_DEBUG_LT3 ,0x00}, ++ {R367_OFDM_TSTSFMET ,0x00}, ++ {R367_OFDM_SELOUT ,0x00}, ++ {R367_OFDM_TSYNC ,0x00}, ++ {R367_OFDM_TSTERR ,0x00}, ++ {R367_OFDM_TSFSYNC ,0x00}, ++ {R367_OFDM_TSTSFERR ,0x00}, ++ {R367_OFDM_TSTTSSF1 ,0x01}, ++ {R367_OFDM_TSTTSSF2 ,0x1f}, ++ {R367_OFDM_TSTTSSF3 ,0x00}, ++ {R367_OFDM_TSTTS1 ,0x00}, ++ {R367_OFDM_TSTTS2 ,0x1f}, ++ {R367_OFDM_TSTTS3 ,0x01}, ++ {R367_OFDM_TSTTS4 ,0x00}, ++ {R367_OFDM_TSTTSRC ,0x00}, ++ {R367_OFDM_TSTTSRS ,0x00}, ++ {R367_OFDM_TSSTATEM ,0xb0}, ++ {R367_OFDM_TSSTATEL ,0x40}, ++ {R367_OFDM_TSCFGH ,0x80}, ++ {R367_OFDM_TSCFGM ,0x00}, ++ {R367_OFDM_TSCFGL ,0x20}, ++ {R367_OFDM_TSSYNC ,0x00}, ++ {R367_OFDM_TSINSDELH ,0x00}, ++ {R367_OFDM_TSINSDELM ,0x00}, ++ {R367_OFDM_TSINSDELL ,0x00}, ++ {R367_OFDM_TSDIVN ,0x03}, ++ {R367_OFDM_TSDIVPM ,0x00}, ++ {R367_OFDM_TSDIVPL ,0x00}, ++ {R367_OFDM_TSDIVQM ,0x00}, ++ {R367_OFDM_TSDIVQL ,0x00}, ++ {R367_OFDM_TSDILSTKM ,0x00}, ++ {R367_OFDM_TSDILSTKL ,0x00}, ++ {R367_OFDM_TSSPEED ,0x6f}, ++ {R367_OFDM_TSSTATUS ,0x81}, ++ {R367_OFDM_TSSTATUS2 ,0x6a}, ++ {R367_OFDM_TSBITRATEM ,0x0f}, ++ {R367_OFDM_TSBITRATEL ,0xc6}, ++ {R367_OFDM_TSPACKLENM ,0x00}, ++ {R367_OFDM_TSPACKLENL ,0xfc}, ++ {R367_OFDM_TSBLOCLENM ,0x0a}, ++ {R367_OFDM_TSBLOCLENL ,0x80}, ++ {R367_OFDM_TSDLYH ,0x90}, ++ {R367_OFDM_TSDLYM ,0x68}, ++ {R367_OFDM_TSDLYL ,0x01}, ++ {R367_OFDM_TSNPDAV ,0x00}, ++ {R367_OFDM_TSBUFSTATH ,0x00}, ++ {R367_OFDM_TSBUFSTATM ,0x00}, ++ {R367_OFDM_TSBUFSTATL ,0x00}, ++ {R367_OFDM_TSDEBUGM ,0xcf}, ++ {R367_OFDM_TSDEBUGL ,0x1e}, ++ {R367_OFDM_TSDLYSETH ,0x00}, ++ {R367_OFDM_TSDLYSETM ,0x68}, ++ {R367_OFDM_TSDLYSETL ,0x00}, ++ {R367_OFDM_TSOBSCFG ,0x00}, ++ {R367_OFDM_TSOBSM ,0x47}, ++ {R367_OFDM_TSOBSL ,0x1f}, ++ {R367_OFDM_ERRCTRL1 ,0x95}, ++ {R367_OFDM_ERRCNT1H ,0x80}, ++ {R367_OFDM_ERRCNT1M ,0x00}, ++ {R367_OFDM_ERRCNT1L ,0x00}, ++ {R367_OFDM_ERRCTRL2 ,0x95}, ++ {R367_OFDM_ERRCNT2H ,0x00}, ++ {R367_OFDM_ERRCNT2M ,0x00}, ++ {R367_OFDM_ERRCNT2L ,0x00}, ++ {R367_OFDM_FECSPY ,0x88}, ++ {R367_OFDM_FSPYCFG ,0x2c}, ++ {R367_OFDM_FSPYDATA ,0x3a}, ++ {R367_OFDM_FSPYOUT ,0x06}, ++ {R367_OFDM_FSTATUS ,0x61}, ++ {R367_OFDM_FGOODPACK ,0xff}, ++ {R367_OFDM_FPACKCNT ,0xff}, ++ {R367_OFDM_FSPYMISC ,0x66}, ++ {R367_OFDM_FBERCPT4 ,0x00}, ++ {R367_OFDM_FBERCPT3 ,0x00}, ++ {R367_OFDM_FBERCPT2 ,0x36}, ++ {R367_OFDM_FBERCPT1 ,0x36}, ++ {R367_OFDM_FBERCPT0 ,0x14}, ++ {R367_OFDM_FBERERR2 ,0x00}, ++ {R367_OFDM_FBERERR1 ,0x03}, ++ {R367_OFDM_FBERERR0 ,0x28}, ++ {R367_OFDM_FSTATESM ,0x00}, ++ {R367_OFDM_FSTATESL ,0x02}, ++ {R367_OFDM_FSPYBER ,0x00}, ++ {R367_OFDM_FSPYDISTM ,0x01}, ++ {R367_OFDM_FSPYDISTL ,0x9f}, ++ {R367_OFDM_FSPYOBS7 ,0xc9}, ++ {R367_OFDM_FSPYOBS6 ,0x99}, ++ {R367_OFDM_FSPYOBS5 ,0x08}, ++ {R367_OFDM_FSPYOBS4 ,0xec}, ++ {R367_OFDM_FSPYOBS3 ,0x01}, ++ {R367_OFDM_FSPYOBS2 ,0x0f}, ++ {R367_OFDM_FSPYOBS1 ,0xf5}, ++ {R367_OFDM_FSPYOBS0 ,0x08}, ++ {R367_OFDM_SFDEMAP ,0x40}, ++ {R367_OFDM_SFERROR ,0x00}, ++ {R367_OFDM_SFAVSR ,0x30}, ++ {R367_OFDM_SFECSTATUS ,0xcc}, ++ {R367_OFDM_SFKDIV12 ,0x20}, ++ {R367_OFDM_SFKDIV23 ,0x40}, ++ {R367_OFDM_SFKDIV34 ,0x20}, ++ {R367_OFDM_SFKDIV56 ,0x20}, ++ {R367_OFDM_SFKDIV67 ,0x00}, ++ {R367_OFDM_SFKDIV78 ,0x20}, ++ {R367_OFDM_SFDILSTKM ,0x00}, ++ {R367_OFDM_SFDILSTKL ,0x00}, ++ {R367_OFDM_SFSTATUS ,0xb5}, ++ {R367_OFDM_SFDLYH ,0x90}, ++ {R367_OFDM_SFDLYM ,0x60}, ++ {R367_OFDM_SFDLYL ,0x01}, ++ {R367_OFDM_SFDLYSETH ,0xc0}, ++ {R367_OFDM_SFDLYSETM ,0x60}, ++ {R367_OFDM_SFDLYSETL ,0x00}, ++ {R367_OFDM_SFOBSCFG ,0x00}, ++ {R367_OFDM_SFOBSM ,0x47}, ++ {R367_OFDM_SFOBSL ,0x05}, ++ {R367_OFDM_SFECINFO ,0x40}, ++ {R367_OFDM_SFERRCTRL ,0x74}, ++ {R367_OFDM_SFERRCNTH ,0x80}, ++ {R367_OFDM_SFERRCNTM ,0x00}, ++ {R367_OFDM_SFERRCNTL ,0x00}, ++ {R367_OFDM_SYMBRATEM ,0x2f}, ++ {R367_OFDM_SYMBRATEL ,0x50}, ++ {R367_OFDM_SYMBSTATUS ,0x7f}, ++ {R367_OFDM_SYMBCFG ,0x00}, ++ {R367_OFDM_SYMBFIFOM ,0xf4}, ++ {R367_OFDM_SYMBFIFOL ,0x0d}, ++ {R367_OFDM_SYMBOFFSM ,0xf0}, ++ {R367_OFDM_SYMBOFFSL ,0x2d}, ++ //{R367_OFDM_DEBUG_LT4 ,0x00}, ++ //{R367_OFDM_DEBUG_LT5 ,0x00}, ++ //{R367_OFDM_DEBUG_LT6 ,0x00}, ++ //{R367_OFDM_DEBUG_LT7 ,0x00}, ++ //{R367_OFDM_DEBUG_LT8 ,0x00}, ++ //{R367_OFDM_DEBUG_LT9 ,0x00}, ++ { 0x0000, 0x00 } // EOT ++}; ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = ++ {.addr = adr, .flags = 0, .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ printk("stv0367: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++#if 0 ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ printk("stv0367: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++static int writereg(struct stv_state *state, u16 reg, u8 dat) ++{ ++ u8 mm[3] = { (reg >> 8), reg & 0xff, dat }; ++ ++ return i2c_write(state->i2c, state->adr, mm, 3); ++} ++ ++static int readreg(struct stv_state *state, u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = state->adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1}}; ++ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int readregs(struct stv_state *state, u16 reg, u8 *val, int count) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = state->adr, .flags = I2C_M_RD, ++ .buf = val, .len = count}}; ++ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int write_init_table(struct stv_state *state, struct init_table *tab) ++{ ++ while (1) { ++ if (!tab->adr) ++ break; ++ if (writereg(state, tab->adr, tab->data) < 0) ++ return -1; ++ tab++; ++ } ++ return 0; ++} ++ ++static int qam_set_modulation(struct stv_state *state) ++{ ++ int stat = 0; ++ ++ switch(state->modulation) { ++ case QAM_16: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x64); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0x90); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a); ++ break; ++ case QAM_32: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0xb0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ case QAM_64: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82); /* Set digital AGC reference */ ++ if(state->symbol_rate>4500000) ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xb0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); ++ } ++ else ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0x99); ++ break; ++ case QAM_128: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x76); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0x90); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1); ++ if(state->symbol_rate>4500000) // 45000000 ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); ++ } ++ else ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ case QAM_256: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ if(state->symbol_rate>4500000) // 45000000 ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ } ++ else ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ default: ++ stat = -EINVAL; ++ break; ++ } ++ return stat; ++} ++ ++ ++static int QAM_SetSymbolRate(struct stv_state *state) ++{ ++ int status = 0; ++ u32 sr = state->symbol_rate; ++ u32 Corr = 0; ++ u32 Temp, Temp1, AdpClk; ++ ++ switch(state->modulation) { ++ default: ++ case QAM_16: Corr = 1032; break; ++ case QAM_32: Corr = 954; break; ++ case QAM_64: Corr = 983; break; ++ case QAM_128: Corr = 957; break; ++ case QAM_256: Corr = 948; break; ++ } ++ ++ // Transfer ration ++ Temp = (256*sr) / state->adc_clock; ++ writereg(state, R367_QAM_EQU_CRL_TFR,(Temp)); ++ ++ /* Symbol rate and SRC gain calculation */ ++ AdpClk = (state->master_clock) / 2000; /* TRL works at half the system clock */ ++ ++ Temp = state->symbol_rate; ++ Temp1 = sr; ++ ++ if(sr < 2097152) /* 2097152 = 2^21 */ ++ { ++ Temp = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8; ++ Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000; ++ } ++ else if(sr < 4194304) /* 4194304 = 2**22 */ ++ { ++ Temp = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16; ++ Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000; ++ } ++ else if(sr < 8388608) /* 8388608 = 2**23 */ ++ { ++ Temp = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32; ++ Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000; ++ } ++ else ++ { ++ Temp = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64; ++ Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000; ++ } ++ ++ ///* Filters' coefficients are calculated and written into registers only if the filters are enabled */ ++ //if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init! ++ //{ ++ // FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate); ++ //} ++ ///* AllPass filter is never used on this IC */ ++ //ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init! ++ ++ writereg(state, R367_QAM_SRC_NCO_LL,(Temp)); ++ writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8)); ++ writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16)); ++ writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24)); ++ ++ writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1)); ++ writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8)); ++ return status; ++} ++ ++ ++static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency) ++{ ++ int status = 0; ++ u32 Sampled_IF; ++ ++ do { ++ //if (DerotFrequency < 1000000) ++ // DerotFrequency = state->adc_clock/4; /* ZIF operation */ ++ if (DerotFrequency > state->adc_clock) ++ DerotFrequency = DerotFrequency - state->adc_clock; // User Alias ++ ++ Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256; ++ if(Sampled_IF > 8388607) ++ Sampled_IF = 8388607; ++ ++ writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF)); ++ writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8)); ++ writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16)); ++ } while(0); ++ ++ return status; ++} ++ ++ ++ ++static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) ++{ ++ int status = 0; ++ u32 AGCTimeOut = 25; ++ u32 TRLTimeOut = 100000000 / state->symbol_rate; ++ u32 CRLSymbols = 0; ++ u32 EQLTimeOut = 100; ++ u32 SearchRange = state->symbol_rate / 25; ++ u32 CRLTimeOut; ++ u8 Temp; ++ ++ if( state->demod_state != QAMSet ) { ++ writereg(state, R367_DEBUG_LT4,0x00); ++ writereg(state, R367_DEBUG_LT5,0x01); ++ writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1 ++ writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2 ++ writereg(state, R367_DEBUG_LT8,0x00); ++ writereg(state, R367_DEBUG_LT9,0x00); ++ ++ // Tuner Setup ++ writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */ ++ writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */ ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */ ++ writereg(state, R367_TOPCTRL,0x10); // Set QAM ++ ++ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,232); ++ writereg(state, R367_PLLSETUP,0x18); /* ADC clock is equal to system clock */ ++ ++ msleep(50); ++ writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */ ++ ++ state->master_clock = 58000000; ++ state->adc_clock = 58000000; ++ ++ state->demod_state = QAMSet; ++ } ++ ++ state->m_bFirstTimeLock = true; ++ state->m_DemodLockTime = -1; ++ ++ qam_set_modulation(state); ++ QAM_SetSymbolRate(state); ++ ++ // Will make problems on low symbol rates ( < 2500000 ) ++ ++ switch(state->modulation) { ++ default: ++ case QAM_16: CRLSymbols = 150000; break; ++ case QAM_32: CRLSymbols = 250000; break; ++ case QAM_64: CRLSymbols = 200000; break; ++ case QAM_128: CRLSymbols = 250000; break; ++ case QAM_256: CRLSymbols = 250000; break; ++ } ++ ++ CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000); ++ CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate; ++ if( CRLTimeOut < 50 ) CRLTimeOut = 50; ++ ++ state->m_FECTimeOut = 20; ++ state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut; ++ state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut; ++ ++ // QAM_AGC_ACCUMRSTSEL = 0; ++ readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL); ++ writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F); ++ ++ // QAM_MODULUSMAP_EN = 0 ++ readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40); ++ ++ // QAM_SWEEP_EN = 0 ++ readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08); ++ ++ QAM_SetDerotFrequency(state, IntermediateFrequency); ++ ++ // Release TRL ++ writereg(state, R367_QAM_CTRL_1,0x00); ++ ++ state->IF = IntermediateFrequency; ++ state->demod_state = QAMStarted; ++ ++ return status; ++} ++ ++static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) ++{ ++ int status = 0; ++ u8 GAIN_SRC1; ++ u32 Derot; ++ u8 SYR_CTL; ++ u8 tmp1; ++ u8 tmp2; ++ ++ if ( state->demod_state != OFDMSet ) { ++ // QAM Disable ++ writereg(state, R367_DEBUG_LT4, 0x00); ++ writereg(state, R367_DEBUG_LT5, 0x00); ++ writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1 ++ writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2 ++ writereg(state, R367_DEBUG_LT8, 0x00); ++ writereg(state, R367_DEBUG_LT9, 0x00); ++ ++ // Tuner Setup ++ writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */ ++ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ ++ writereg(state, R367_TOPCTRL, 0x00); // Set OFDM ++ ++ writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV, 8); ++ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ ++ ++ msleep(50); ++ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ ++ ++ state->master_clock = 54000000; ++ state->adc_clock = 54000000; ++ ++ state->demod_state = OFDMSet; ++ } ++ ++ state->m_bFirstTimeLock = true; ++ state->m_DemodLockTime = -1; ++ ++ // Set inversion in GAIN_SRC1 (fixed from init) ++ // is in GAIN_SRC1, see below ++ ++ GAIN_SRC1 = 0xA0; ++ // Bandwidth ++ ++ // Fixed values for 54 MHz ++ switch(state->bandwidth) { ++ case 0: ++ case 8000000: ++ // Normrate = 44384; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x56); ++ // Gain SRC = 2774 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0xD6); ++ break; ++ case 7000000: ++ // Normrate = 38836; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B); ++ // Gain SRC = 2427 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0x7B); ++ break; ++ case 6000000: ++ // Normrate = 33288; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0x04); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x41); ++ // Gain SRC = 2080 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0x20); ++ break; ++ default: ++ return -EINVAL; ++ break; ++ } ++ ++ Derot = ((IntermediateFrequency / 1000) * 65536) / (state->master_clock / 1000); ++ ++ writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8)); ++ writereg(state, R367_OFDM_INC_DEROT2,(Derot)); ++ ++ readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL); ++ SYR_CTL &= ~0x78; ++ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // EchoPos = 0 ++ ++ ++ writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3 ++ SYR_CTL &= 0x01; ++ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // SYR_TR_DIS = 0 ++ ++ msleep(5); ++ ++ writereg(state, R367_OFDM_COR_CTL,0x20); // Start core ++ ++ // -- Begin M.V. ++ // Reset FEC and Read Solomon ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08); ++ writereg(state, R367_TSGENERAL,tmp2 | 0x01); ++ // -- End M.V. ++ ++ state->m_SignalTimeOut = 200; ++ state->IF = IntermediateFrequency; ++ state->demod_state = OFDMStarted; ++ state->m_DemodTimeOut = 0; ++ state->m_FECTimeOut = 0; ++ state->m_TSTimeOut = 0; ++ ++ return status; ++} ++ ++#if 0 ++static int Stop(struct stv_state *state) ++{ ++ int status = 0; ++ ++ switch(state->demod_state) ++ { ++ case QAMStarted: ++ status = writereg(state, R367_QAM_CTRL_1,0x06); ++ state->demod_state = QAMSet; ++ break; ++ case OFDMStarted: ++ status = writereg(state, R367_OFDM_COR_CTL,0x00); ++ state->demod_state = OFDMSet; ++ break; ++ default: ++ break; ++ } ++ return status; ++} ++#endif ++ ++static s32 Log10x100(u32 x) ++{ ++ static u32 LookupTable[100] = { ++ 101157945, 103514217, 105925373, 108392691, 110917482, ++ 113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5 ++ 127350308, 130316678, 133352143, 136458314, 139636836, ++ 142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5 ++ 160324539, 164058977, 167880402, 171790839, 175792361, ++ 179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5 ++ 201836636, 206538016, 211348904, 216271852, 221309471, ++ 226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5 ++ 254097271, 260015956, 266072506, 272270131, 278612117, ++ 285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5 ++ 319889511, 327340695, 334965439, 342767787, 350751874, ++ 358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5 ++ 402717034, 412097519, 421696503, 431519077, 441570447, ++ 451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5 ++ 506990708, 518800039, 530884444, 543250331, 555904257, ++ 568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5 ++ 638263486, 653130553, 668343918, 683911647, 699841996, ++ 716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5 ++ 803526122, 822242650, 841395142, 860993752, 881048873, ++ 901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5 ++ }; ++ s32 y; ++ int i; ++ ++ if (x == 0) ++ return 0; ++ y = 800; ++ if (x >= 1000000000) { ++ x /= 10; ++ y += 100; ++ } ++ ++ while (x < 100000000) { ++ x *= 10; ++ y -= 100; ++ } ++ i = 0; ++ while (i < 100 && x > LookupTable[i]) ++ i += 1; ++ y += i; ++ return y; ++} ++ ++static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) ++{ ++ u32 RegValAvg = 0; ++ u8 RegVal[2]; ++ int status = 0, i; ++ ++ *pSignalToNoise = 0; ++ for (i = 0; i < 10; i += 1 ) { ++ readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2); ++ RegValAvg += RegVal[0] + 256 * RegVal[1]; ++ } ++ if (RegValAvg != 0) { ++ s32 Power = 1; ++ switch(state->modulation) { ++ case QAM_16: ++ Power = 20480; ++ break; ++ case QAM_32: ++ Power = 23040; ++ break; ++ case QAM_64: ++ Power = 21504; ++ break; ++ case QAM_128: ++ Power = 23616; ++ break; ++ case QAM_256: ++ Power = 21760; ++ break; ++ default: ++ break; ++ } ++ *pSignalToNoise = Log10x100((Power * 320) / RegValAvg); ++ } else { ++ *pSignalToNoise = 380; ++ } ++ return status; ++} ++ ++static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) ++{ ++ u8 CHC_SNR = 0; ++ ++ int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR); ++ if (status >= 0) { ++ // Note: very unclear documentation on this. ++ // Datasheet states snr = CHC_SNR/4 dB -> way to high values! ++ // Software snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values ++ // Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367 ++ // 361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best ++ *pSignalToNoise = ( (s32)CHC_SNR * 10) / 8; ++ } ++ //printk("SNR %d\n", *pSignalToNoise); ++ return status; ++} ++ ++#if 0 ++static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ *pQuality = 100; ++ return 0; ++}; ++ ++static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ static s32 QE_SN[] = { ++ 51, // QPSK 1/2 ++ 69, // QPSK 2/3 ++ 79, // QPSK 3/4 ++ 89, // QPSK 5/6 ++ 97, // QPSK 7/8 ++ 108, // 16-QAM 1/2 ++ 131, // 16-QAM 2/3 ++ 146, // 16-QAM 3/4 ++ 156, // 16-QAM 5/6 ++ 160, // 16-QAM 7/8 ++ 165, // 64-QAM 1/2 ++ 187, // 64-QAM 2/3 ++ 202, // 64-QAM 3/4 ++ 216, // 64-QAM 5/6 ++ 225, // 64-QAM 7/8 ++ }; ++ u8 TPS_Received[2]; ++ int Constellation; ++ int CodeRate; ++ s32 SignalToNoiseRel, BERQuality; ++ ++ *pQuality = 0; ++ readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received)); ++ Constellation = TPS_Received[0] & 0x03; ++ CodeRate = TPS_Received[1] & 0x07; ++ ++ if( Constellation > 2 || CodeRate > 5 ) ++ return -1; ++ SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate]; ++ BERQuality = 100; ++ ++ if( SignalToNoiseRel < -70 ) ++ *pQuality = 0; ++ else if( SignalToNoiseRel < 30 ) { ++ *pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100; ++ } else ++ *pQuality = BERQuality; ++ return 0; ++}; ++ ++static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise) ++{ ++ s32 SignalToNoiseRel = 0; ++ s32 Quality = 0; ++ s32 BERQuality = 100; ++ ++ switch(state->modulation) { ++ case QAM_16: SignalToNoiseRel = SignalToNoise - 200 ; break; ++ case QAM_32: SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig ++ case QAM_64: SignalToNoiseRel = SignalToNoise - 260 ; break; ++ case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break; ++ case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break; ++ } ++ ++ if( SignalToNoiseRel < -70 ) Quality = 0; ++ else if( SignalToNoiseRel < 30 ) ++ { ++ Quality = ((SignalToNoiseRel + 70) * BERQuality)/100; ++ } ++ else ++ Quality = BERQuality; ++ ++ return Quality; ++} ++ ++static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ *pQuality = 0; ++ switch(state->demod_state) ++ { ++ case QAMStarted: ++ *pQuality = DVBCQuality(state, SignalToNoise); ++ break; ++ case OFDMStarted: ++ return DVBT_GetQuality(state, SignalToNoise, pQuality); ++ } ++ return 0; ++}; ++#endif ++ ++static int attach_init(struct stv_state *state) ++{ ++ int stat = 0; ++ ++ stat = readreg(state, R367_ID, &state->ID); ++ if ( stat < 0 || state->ID != 0x60 ) ++ return -ENODEV; ++ printk("stv0367 found\n"); ++ ++ writereg(state, R367_TOPCTRL, 0x10); ++ write_init_table(state, base_init); ++ write_init_table(state, qam_init); ++ ++ writereg(state, R367_TOPCTRL, 0x00); ++ write_init_table(state, ofdm_init); ++ ++ writereg(state, R367_OFDM_GAIN_SRC1, 0x2A); ++ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); ++ writereg(state, R367_OFDM_INC_DEROT1, 0x55); ++ writereg(state, R367_OFDM_INC_DEROT2, 0x55); ++ writereg(state, R367_OFDM_TRL_CTL, 0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE); ++ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); ++ writereg(state, R367_OFDM_FEPATH_CFG, 0x0); ++ ++ // OFDM TS Setup ++ ++ writereg(state, R367_OFDM_TSCFGH, 0x70); ++ writereg(state, R367_OFDM_TSCFGM, 0xC0); ++ writereg(state, R367_OFDM_TSCFGL, 0x20); ++ writereg(state, R367_OFDM_TSSPEED, 0x40); // Fixed at 54 MHz ++ //writereg(state, R367_TSTBUS, 0x80); // Invert CLK ++ ++ writereg(state, R367_OFDM_TSCFGH, 0x71); ++ writereg(state, R367_OFDM_TSCFGH, 0x70); ++ ++ writereg(state, R367_TOPCTRL, 0x10); ++ ++ // Also needed for QAM ++ writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup ++ ++ writereg(state, R367_OFDM_AGCCTRL1, 0x8A); // ++ ++ // QAM TS setup, note exact format also depends on descrambler settings ++ writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial ++ // writereg(state, R367_QAM_OUTFORMAT_1, 0x00); // ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ ++ ++ if( state->master_clock == 58000000 ) { ++ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,232); ++ } else { ++ writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,8); ++ } ++ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ ++ ++ // Tuner setup ++ writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */ ++ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ ++ ++ writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */ ++ writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */ ++ writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */ ++ writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */ ++ ++ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ ++ ++ writereg(state, R367_I2CRPT, state->I2CRPT); ++ state->demod_state = QAMSet; ++ return stat; ++} ++ ++#ifdef USE_API3 ++static void c_release(struct dvb_frontend* fe) ++#else ++static void release(struct dvb_frontend* fe) ++#endif ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ printk("%s\n", __FUNCTION__); ++ kfree(state); ++} ++ ++#ifdef USE_API3 ++static int c_init (struct dvb_frontend *fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ ++ if (mutex_trylock(&state->ctlock)==0) ++ return -EBUSY; ++ state->omode = OM_DVBC; ++ return 0; ++} ++ ++static int c_sleep(struct dvb_frontend* fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ ++ mutex_unlock(&state->ctlock); ++ return 0; ++} ++#endif ++ ++static int gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u8 i2crpt = state->I2CRPT & ~0x80; ++ ++ if (enable) ++ i2crpt |= 0x80; ++ if (writereg(state, R367_I2CRPT, i2crpt) < 0) ++ return -1; ++ state->I2CRPT = i2crpt; ++ return 0; ++} ++ ++#if 0 ++static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ return DVBFE_ALGO_SEARCH_AGAIN; ++} ++#endif ++ ++#if 0 ++int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); ++int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); ++#endif ++ ++static int ofdm_lock(struct stv_state *state) ++{ ++ int status = 0; ++ u8 OFDM_Status; ++ s32 DemodTimeOut = 10; ++ s32 FECTimeOut = 0; ++ s32 TSTimeOut = 0; ++ u8 CPAMPMin = 255; ++ u8 CPAMPValue; ++ u8 SYR_STAT; ++ u8 FFTMode; ++ u8 TSStatus; ++ ++ msleep(state->m_SignalTimeOut); ++ readreg(state, R367_OFDM_STATUS,&OFDM_Status); ++ ++ if (!(OFDM_Status & 0x40)) ++ return -1; ++ //printk("lock 1\n"); ++ ++ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); ++ FFTMode = (SYR_STAT & 0x0C) >> 2; ++ ++ switch(FFTMode) ++ { ++ case 0: // 2K ++ DemodTimeOut = 10; ++ FECTimeOut = 150; ++ TSTimeOut = 125; ++ CPAMPMin = 20; ++ break; ++ case 1: // 8K ++ DemodTimeOut = 55; ++ FECTimeOut = 600; ++ TSTimeOut = 500; ++ CPAMPMin = 80; ++ break; ++ case 2: // 4K ++ DemodTimeOut = 40; ++ FECTimeOut = 300; ++ TSTimeOut = 250; ++ CPAMPMin = 30; ++ break; ++ } ++ state->m_OFDM_FFTMode = FFTMode; ++ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); ++ msleep(DemodTimeOut); ++ { ++ // Release FEC and Read Solomon Reset ++ u8 tmp1; ++ u8 tmp2; ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); ++ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); ++ } ++ msleep(FECTimeOut); ++ if( (OFDM_Status & 0x98) != 0x98 ) ++ ;//return -1; ++ //printk("lock 2\n"); ++ ++ { ++ u8 Guard = (SYR_STAT & 0x03); ++ if(Guard < 2) ++ { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER ++ } else { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER ++ } ++ ++ // apply Sfec workaround if 8K 64QAM CR!=1/2 ++ if( FFTMode == 1) ++ { ++ u8 tmp[2]; ++ readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2); ++ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0xc0); ++ writereg(state, R367_OFDM_SFDLYSETM,0x60); ++ writereg(state, R367_OFDM_SFDLYSETL,0x00); ++ } ++ else ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0x00); ++ } ++ } ++ } ++ msleep(TSTimeOut); ++ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); ++ if( (TSStatus & 0x80) != 0x80 ) ++ return -1; ++ //printk("lock 3\n"); ++ return status; ++} ++ ++ ++#ifdef USE_API3 ++static int set_parameters(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *p) ++{ ++ int stat; ++ struct stv_state *state = fe->demodulator_priv; ++ u32 OF = 0; ++ u32 IF; ++ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe, p); ++ ++ switch (state->omode) { ++ case OM_DVBC: ++ case OM_QAM_ITU_C: ++ state->modulation = p->u.qam.modulation; ++ state->symbol_rate = p->u.qam.symbol_rate; ++ break; ++ case OM_DVBT: ++ switch (p->u.ofdm.bandwidth) { ++ case BANDWIDTH_AUTO: ++ case BANDWIDTH_8_MHZ: ++ state->bandwidth = 8000000; ++ break; ++ case BANDWIDTH_7_MHZ: ++ state->bandwidth = 7000000; ++ break; ++ case BANDWIDTH_6_MHZ: ++ state->bandwidth = 6000000; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++#else ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ int stat; ++ struct stv_state *state = fe->demodulator_priv; ++ u32 OF = 0; ++ u32 IF; ++ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ state->omode = OM_DVBC; ++ /* symbol rate 0 might cause an oops */ ++ if (fe->dtv_property_cache.symbol_rate == 0) { ++ printk(KERN_ERR "stv0367dd: Invalid symbol rate\n"); ++ return -EINVAL; ++ } ++ break; ++ case SYS_DVBT: ++ state->omode = OM_DVBT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ state->modulation = fe->dtv_property_cache.modulation; ++ state->symbol_rate = fe->dtv_property_cache.symbol_rate; ++ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; ++#endif ++ fe->ops.tuner_ops.get_if_frequency(fe, &IF); ++ //fe->ops.tuner_ops.get_frequency(fe, &IF); ++ ++ switch(state->omode) { ++ case OM_DVBT: ++ stat = OFDM_Start(state, OF, IF); ++ ofdm_lock(state); ++ break; ++ case OM_DVBC: ++ case OM_QAM_ITU_C: ++ stat = QAM_Start(state, OF, IF); ++ break; ++ default: ++ stat = -EINVAL; ++ } ++ //printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF); ++ return stat; ++} ++ ++#if 0 ++static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ //struct stv_state *state = fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ return 0; ++} ++ ++static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time) ++{ ++ int status = STATUS_SUCCESS; ++ u8 OFDM_Status; ++ s32 DemodTimeOut = 0; ++ s32 FECTimeOut = 0; ++ s32 TSTimeOut = 0; ++ u8 CPAMPMin = 255; ++ u8 CPAMPValue; ++ bool SYRLock; ++ u8 SYR_STAT; ++ u8 FFTMode; ++ u8 TSStatus; ++ ++ readreg(state, R367_OFDM_STATUS,&OFDM_Status); ++ ++ SYRLock = (OFDM_Status & 0x40) != 0; ++ ++ if( Time > m_SignalTimeOut && !SYRLock ) ++ { ++ *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( !SYRLock ) break; ++ ++ *pLockStatus = SIGNAL_PRESENT; ++ ++ // Check Mode ++ ++ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); ++ FFTMode = (SYR_STAT & 0x0C) >> 2; ++ ++ switch(FFTMode) ++ { ++ case 0: // 2K ++ DemodTimeOut = 10; ++ FECTimeOut = 150; ++ TSTimeOut = 125; ++ CPAMPMin = 20; ++ break; ++ case 1: // 8K ++ DemodTimeOut = 55; ++ FECTimeOut = 600; ++ TSTimeOut = 500; ++ CPAMPMin = 80; ++ break; ++ case 2: // 4K ++ DemodTimeOut = 40; ++ FECTimeOut = 300; ++ TSTimeOut = 250; ++ CPAMPMin = 30; ++ break; ++ } ++ ++ m_OFDM_FFTMode = FFTMode; ++ ++ if( m_DemodTimeOut == 0 && m_bFirstTimeLock ) ++ { ++ m_DemodTimeOut = Time + DemodTimeOut; ++ //break; ++ } ++ ++ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); ++ ++ if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin ) ++ { ++ break; ++ } ++ ++ if( CPAMPValue < CPAMPMin && m_bFirstTimeLock ) ++ { ++ // initiate retry ++ *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( CPAMPValue < CPAMPMin ) break; ++ ++ *pLockStatus = DEMOD_LOCK; ++ ++ if( m_FECTimeOut == 0 && m_bFirstTimeLock ) ++ { ++ // Release FEC and Read Solomon Reset ++ u8 tmp1; ++ u8 tmp2; ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); ++ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); ++ ++ m_FECTimeOut = Time + FECTimeOut; ++ } ++ ++ // Wait for TSP_LOCK, LK, PRF ++ if( (OFDM_Status & 0x98) != 0x98 ) ++ { ++ if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( m_bFirstTimeLock && m_TSTimeOut == 0) ++ { ++ u8 Guard = (SYR_STAT & 0x03); ++ if(Guard < 2) ++ { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER ++ } else { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER ++ } ++ ++ // apply Sfec workaround if 8K 64QAM CR!=1/2 ++ if( FFTMode == 1) ++ { ++ u8 tmp[2]; ++ readreg(state, R367_OFDM_TPS_RCVD2,tmp,2); ++ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0xc0); ++ writereg(state, R367_OFDM_SFDLYSETM,0x60); ++ writereg(state, R367_OFDM_SFDLYSETL,0x00); ++ } ++ else ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0x00); ++ } ++ } ++ ++ m_TSTimeOut = Time + TSTimeOut; ++ } ++ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); ++ if( (TSStatus & 0x80) != 0x80 ) ++ { ++ if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ *pLockStatus = MPEG_LOCK; ++ m_bFirstTimeLock = false; ++ return status; ++} ++ ++#endif ++ ++static int read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ *status=0; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ { ++ u8 FEC_Lock; ++ u8 QAM_Lock; ++ ++ readreg(state, R367_QAM_FSM_STS, &QAM_Lock); ++ QAM_Lock &= 0x0F; ++ if (QAM_Lock >10) ++ *status|=0x07; ++ readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock); ++ if (FEC_Lock&2) ++ *status|=0x1f; ++ if (state->m_bFirstTimeLock) { ++ state->m_bFirstTimeLock = false; ++ // QAM_AGC_ACCUMRSTSEL to Tracking; ++ writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL); ++ } ++ break; ++ } ++ case OFDMStarted: ++ { ++ u8 OFDM_Status; ++ u8 TSStatus; ++ ++ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); ++ ++ readreg(state, R367_OFDM_STATUS, &OFDM_Status); ++ if (OFDM_Status & 0x40) ++ *status |= FE_HAS_SIGNAL; ++ ++ if ((OFDM_Status & 0x98) == 0x98) ++ *status|=0x0f; ++ ++ if (TSStatus & 0x80) ++ *status |= 0x1f; ++ break; ++ } ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int read_ber_ter(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u32 err; ++ u8 cnth, cntm, cntl; ++ ++#if 1 ++ readreg(state, R367_OFDM_SFERRCNTH, &cnth); ++ ++ if (cnth & 0x80) { ++ *ber = state->ber; ++ return 0; ++ } ++ ++ readreg(state, R367_OFDM_SFERRCNTM, &cntm); ++ readreg(state, R367_OFDM_SFERRCNTL, &cntl); ++ ++ err = ((cnth & 0x7f) << 16) | (cntm << 8) | cntl; ++ ++#if 0 ++ { ++ u64 err64; ++ err64 = (u64) err; ++ err64 *= 1000000000ULL; ++ err64 >>= 21; ++ err = err64; ++ } ++#endif ++#else ++ readreg(state, R367_OFDM_ERRCNT1HM, &cnth); ++ ++#endif ++ *ber = state->ber = err; ++ return 0; ++} ++ ++static int read_ber_cab(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u32 err; ++ u8 cntm, cntl, ctrl; ++ ++ readreg(state, R367_QAM_BERT_1, &ctrl); ++ if (!(ctrl & 0x20)) { ++ readreg(state, R367_QAM_BERT_2, &cntl); ++ readreg(state, R367_QAM_BERT_3, &cntm); ++ err = (cntm << 8) | cntl; ++ //printk("err %04x\n", err); ++ state->ber = err; ++ writereg(state, R367_QAM_BERT_1, 0x27); ++ } ++ *ber = (u32) state->ber; ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ ++ if (state->demod_state == QAMStarted) ++ return read_ber_cab(fe, ber); ++ if (state->demod_state == OFDMStarted) ++ return read_ber_ter(fe, ber); ++ *ber = 0; ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ if (fe->ops.tuner_ops.get_rf_strength) ++ fe->ops.tuner_ops.get_rf_strength(fe, strength); ++ else ++ *strength = 0; ++ return 0; ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ s32 snr2 = 0; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ QAM_GetSignalToNoise(state, &snr2); ++ break; ++ case OFDMStarted: ++ OFDM_GetSignalToNoise(state, &snr2); ++ break; ++ default: ++ break; ++ } ++ *snr = snr2&0xffff; ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u8 errl, errm, errh; ++ u8 val; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ readreg(state, R367_QAM_RS_COUNTER_4, &errl); ++ readreg(state, R367_QAM_RS_COUNTER_5, &errm); ++ *ucblocks = (errm << 8) | errl; ++ break; ++ case OFDMStarted: ++ readreg(state, R367_OFDM_SFERRCNTH, &val); ++ if ((val & 0x80) == 0) { ++ readreg(state, R367_OFDM_ERRCNT1H, &errh); ++ readreg(state, R367_OFDM_ERRCNT1M, &errl); ++ readreg(state, R367_OFDM_ERRCNT1L, &errm); ++ state->ucblocks = (errh <<16) | (errm << 8) | errl; ++ } ++ *ucblocks = state->ucblocks; ++ break; ++ default: ++ *ucblocks = 0; ++ break; ++ } ++ return 0; ++} ++ ++static int c_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *sets) ++{ ++ sets->min_delay_ms=3000; ++ sets->max_drift=0; ++ sets->step_size=0; ++ return 0; ++} ++ ++#ifndef USE_API3 ++static int get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *sets) ++{ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: ++ return c_get_tune_settings(fe, sets); ++ default: ++ /* DVB-T: Use info.frequency_stepsize. */ ++ return -EINVAL; ++ } ++} ++#endif ++ ++#ifdef USE_API3 ++static void t_release(struct dvb_frontend* fe) ++{ ++ //struct stv_state *state=fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ //kfree(state); ++} ++ ++static int t_init (struct dvb_frontend *fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ if (mutex_trylock(&state->ctlock)==0) ++ return -EBUSY; ++ state->omode = OM_DVBT; ++ return 0; ++} ++ ++static int t_sleep(struct dvb_frontend* fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ mutex_unlock(&state->ctlock); ++ return 0; ++} ++#endif ++ ++#if 0 ++static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ //struct stv_state *state = fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ return 0; ++} ++ ++static enum dvbfe_algo algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_CUSTOM; ++} ++#endif ++ ++#ifdef USE_API3 ++static struct dvb_frontend_ops c_ops = { ++ .info = { ++ .name = "STV0367 DVB-C", ++ .type = FE_QAM, ++ .frequency_stepsize = 62500, ++ .frequency_min = 47000000, ++ .frequency_max = 862000000, ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO ++ }, ++ .release = c_release, ++ .init = c_init, ++ .sleep = c_sleep, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .get_tune_settings = c_get_tune_settings, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++ ++#if 1 ++ .set_frontend = set_parameters, ++#else ++ .get_frontend_algo = algo, ++ .search = search, ++#endif ++}; ++ ++static struct dvb_frontend_ops t_ops = { ++ .info = { ++ .name = "STV0367 DVB-T", ++ .type = FE_OFDM, ++ .frequency_min = 47125000, ++ .frequency_max = 865000000, ++ .frequency_stepsize = 166667, ++ .frequency_tolerance = 0, ++ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ .release = t_release, ++ .init = t_init, ++ .sleep = t_sleep, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .set_frontend = set_parameters, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++}; ++ ++#else ++ ++static struct dvb_frontend_ops common_ops = { ++ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, ++ .info = { ++ .name = "STV0367 DVB-C DVB-T", ++ .frequency_stepsize = 166667, /* DVB-T only */ ++ .frequency_min = 47000000, /* DVB-T: 47125000 */ ++ .frequency_max = 865000000, /* DVB-C: 862000000 */ ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = /* DVB-C */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | ++ FE_CAN_FEC_AUTO | ++ /* DVB-T */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | FE_CAN_MUTE_TS ++ }, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .get_tune_settings = get_tune_settings, ++ ++ .set_frontend = set_parameters, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++}; ++#endif ++ ++ ++static void init_state(struct stv_state *state, struct stv0367_cfg *cfg) ++{ ++ u32 ulENARPTLEVEL = 5; ++ u32 ulQAMInversion = 2; ++ state->omode = OM_NONE; ++ state->adr = cfg->adr; ++ ++ mutex_init(&state->mutex); ++ mutex_init(&state->ctlock); ++ ++#ifdef USE_API3 ++ memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops)); ++ memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops)); ++ state->c_frontend.demodulator_priv = state; ++ state->t_frontend.demodulator_priv = state; ++#else ++ memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++#endif ++ ++ state->master_clock = 58000000; ++ state->adc_clock = 58000000; ++ state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4); ++ state->qam_inversion = ((ulQAMInversion & 3) << 6 ); ++ state->demod_state = Off; ++} ++ ++ ++struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg, ++ struct dvb_frontend **fe_t) ++{ ++ struct stv_state *state = NULL; ++ ++ state = kzalloc(sizeof(struct stv_state), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->i2c = i2c; ++ init_state(state, cfg); ++ ++ if (attach_init(state)<0) ++ goto error; ++#ifdef USE_API3 ++ *fe_t = &state->t_frontend; ++ return &state->c_frontend; ++#else ++ return &state->frontend; ++#endif ++ ++error: ++ printk("stv0367: not found\n"); ++ kfree(state); ++ return NULL; ++} ++ ++ ++MODULE_DESCRIPTION("STV0367DD driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); ++ ++EXPORT_SYMBOL(stv0367_attach); ++ ++ ++ +diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h +new file mode 100644 +index 0000000..665d4c8 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd.h +@@ -0,0 +1,17 @@ ++#ifndef _STV0367DD_H_ ++#define _STV0367DD_H_ ++ ++#include ++#include ++ ++struct stv0367_cfg { ++ u8 adr; ++ u32 xtal; ++ u32 ts_mode; ++}; ++ ++ ++extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, ++ struct stv0367_cfg *cfg, ++ struct dvb_frontend **fe_t); ++#endif +diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h +new file mode 100644 +index 0000000..eec0f57 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd_regs.h +@@ -0,0 +1,3431 @@ ++// @DVB-C/DVB-T STMicroelectronics STV0367 register defintions ++// Author Manfred Völkel, Februar 2011 ++// (c) 2010 DigitalDevices GmbH Germany. All rights reserved ++ ++// $Id: DD_STV0367Register.h 357 2011-04-27 02:39:13Z manfred $ ++ ++/* ======================================================================= ++ -- Registers Declaration ++ -- ------------------------- ++ -- Each register (R367_XXXXX) is defined by its address (2 bytes). ++ -- ++ -- Each field (F367_XXXXX)is defined as follow: ++ -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] ++ ======================================================================= */ ++ ++/* ID */ ++#define R367_ID 0xF000 ++#define F367_IDENTIFICATIONREG 0xF00000FF ++ ++/* I2CRPT */ ++#define R367_I2CRPT 0xF001 ++#define F367_I2CT_ON 0xF0010080 ++#define F367_ENARPT_LEVEL 0xF0010070 ++#define F367_SCLT_DELAY 0xF0010008 ++#define F367_SCLT_NOD 0xF0010004 ++#define F367_STOP_ENABLE 0xF0010002 ++#define F367_SDAT_NOD 0xF0010001 ++ ++/* TOPCTRL */ ++#define R367_TOPCTRL 0xF002 ++#define F367_STDBY 0xF0020080 ++#define F367_STDBY_FEC 0xF0020040 ++#define F367_STDBY_CORE 0xF0020020 ++#define F367_QAM_COFDM 0xF0020010 ++#define F367_TS_DIS 0xF0020008 ++#define F367_DIR_CLK_216 0xF0020004 ++#define F367_TUNER_BB 0xF0020002 ++#define F367_DVBT_H 0xF0020001 ++ ++/* IOCFG0 */ ++#define R367_IOCFG0 0xF003 ++#define F367_OP0_SD 0xF0030080 ++#define F367_OP0_VAL 0xF0030040 ++#define F367_OP0_OD 0xF0030020 ++#define F367_OP0_INV 0xF0030010 ++#define F367_OP0_DACVALUE_HI 0xF003000F ++ ++/* DAC0R */ ++#define R367_DAC0R 0xF004 ++#define F367_OP0_DACVALUE_LO 0xF00400FF ++ ++/* IOCFG1 */ ++#define R367_IOCFG1 0xF005 ++#define F367_IP0 0xF0050040 ++#define F367_OP1_OD 0xF0050020 ++#define F367_OP1_INV 0xF0050010 ++#define F367_OP1_DACVALUE_HI 0xF005000F ++ ++/* DAC1R */ ++#define R367_DAC1R 0xF006 ++#define F367_OP1_DACVALUE_LO 0xF00600FF ++ ++/* IOCFG2 */ ++#define R367_IOCFG2 0xF007 ++#define F367_OP2_LOCK_CONF 0xF00700E0 ++#define F367_OP2_OD 0xF0070010 ++#define F367_OP2_VAL 0xF0070008 ++#define F367_OP1_LOCK_CONF 0xF0070007 ++ ++/* SDFR */ ++#define R367_SDFR 0xF008 ++#define F367_OP0_FREQ 0xF00800F0 ++#define F367_OP1_FREQ 0xF008000F ++ ++/* STATUS */ ++#define R367_OFDM_STATUS 0xF009 ++#define F367_TPS_LOCK 0xF0090080 ++#define F367_SYR_LOCK 0xF0090040 ++#define F367_AGC_LOCK 0xF0090020 ++#define F367_PRF 0xF0090010 ++#define F367_LK 0xF0090008 ++#define F367_PR 0xF0090007 ++ ++/* AUX_CLK */ ++#define R367_AUX_CLK 0xF00A ++#define F367_AUXFEC_CTL 0xF00A00C0 ++#define F367_DIS_CKX4 0xF00A0020 ++#define F367_CKSEL 0xF00A0018 ++#define F367_CKDIV_PROG 0xF00A0006 ++#define F367_AUXCLK_ENA 0xF00A0001 ++ ++/* FREESYS1 */ ++#define R367_FREESYS1 0xF00B ++#define F367_FREE_SYS1 0xF00B00FF ++ ++/* FREESYS2 */ ++#define R367_FREESYS2 0xF00C ++#define F367_FREE_SYS2 0xF00C00FF ++ ++/* FREESYS3 */ ++#define R367_FREESYS3 0xF00D ++#define F367_FREE_SYS3 0xF00D00FF ++ ++/* GPIO_CFG */ ++#define R367_GPIO_CFG 0xF00E ++#define F367_GPIO7_NOD 0xF00E0080 ++#define F367_GPIO7_CFG 0xF00E0040 ++#define F367_GPIO6_NOD 0xF00E0020 ++#define F367_GPIO6_CFG 0xF00E0010 ++#define F367_GPIO5_NOD 0xF00E0008 ++#define F367_GPIO5_CFG 0xF00E0004 ++#define F367_GPIO4_NOD 0xF00E0002 ++#define F367_GPIO4_CFG 0xF00E0001 ++ ++/* GPIO_CMD */ ++#define R367_GPIO_CMD 0xF00F ++#define F367_GPIO7_VAL 0xF00F0008 ++#define F367_GPIO6_VAL 0xF00F0004 ++#define F367_GPIO5_VAL 0xF00F0002 ++#define F367_GPIO4_VAL 0xF00F0001 ++ ++/* AGC2MAX */ ++#define R367_OFDM_AGC2MAX 0xF010 ++#define F367_OFDM_AGC2_MAX 0xF01000FF ++ ++/* AGC2MIN */ ++#define R367_OFDM_AGC2MIN 0xF011 ++#define F367_OFDM_AGC2_MIN 0xF01100FF ++ ++/* AGC1MAX */ ++#define R367_OFDM_AGC1MAX 0xF012 ++#define F367_OFDM_AGC1_MAX 0xF01200FF ++ ++/* AGC1MIN */ ++#define R367_OFDM_AGC1MIN 0xF013 ++#define F367_OFDM_AGC1_MIN 0xF01300FF ++ ++/* AGCR */ ++#define R367_OFDM_AGCR 0xF014 ++#define F367_OFDM_RATIO_A 0xF01400E0 ++#define F367_OFDM_RATIO_B 0xF0140018 ++#define F367_OFDM_RATIO_C 0xF0140007 ++ ++/* AGC2TH */ ++#define R367_OFDM_AGC2TH 0xF015 ++#define F367_OFDM_AGC2_THRES 0xF01500FF ++ ++/* AGC12C */ ++#define R367_OFDM_AGC12C 0xF016 ++#define F367_OFDM_AGC1_IV 0xF0160080 ++#define F367_OFDM_AGC1_OD 0xF0160040 ++#define F367_OFDM_AGC1_LOAD 0xF0160020 ++#define F367_OFDM_AGC2_IV 0xF0160010 ++#define F367_OFDM_AGC2_OD 0xF0160008 ++#define F367_OFDM_AGC2_LOAD 0xF0160004 ++#define F367_OFDM_AGC12_MODE 0xF0160003 ++ ++/* AGCCTRL1 */ ++#define R367_OFDM_AGCCTRL1 0xF017 ++#define F367_OFDM_DAGC_ON 0xF0170080 ++#define F367_OFDM_INVERT_AGC12 0xF0170040 ++#define F367_OFDM_AGC1_MODE 0xF0170008 ++#define F367_OFDM_AGC2_MODE 0xF0170007 ++ ++/* AGCCTRL2 */ ++#define R367_OFDM_AGCCTRL2 0xF018 ++#define F367_OFDM_FRZ2_CTRL 0xF0180060 ++#define F367_OFDM_FRZ1_CTRL 0xF0180018 ++#define F367_OFDM_TIME_CST 0xF0180007 ++ ++/* AGC1VAL1 */ ++#define R367_OFDM_AGC1VAL1 0xF019 ++#define F367_OFDM_AGC1_VAL_LO 0xF01900FF ++ ++/* AGC1VAL2 */ ++#define R367_OFDM_AGC1VAL2 0xF01A ++#define F367_OFDM_AGC1_VAL_HI 0xF01A000F ++ ++/* AGC2VAL1 */ ++#define R367_OFDM_AGC2VAL1 0xF01B ++#define F367_OFDM_AGC2_VAL_LO 0xF01B00FF ++ ++/* AGC2VAL2 */ ++#define R367_OFDM_AGC2VAL2 0xF01C ++#define F367_OFDM_AGC2_VAL_HI 0xF01C000F ++ ++/* AGC2PGA */ ++#define R367_OFDM_AGC2PGA 0xF01D ++#define F367_OFDM_AGC2_PGA 0xF01D00FF ++ ++/* OVF_RATE1 */ ++#define R367_OFDM_OVF_RATE1 0xF01E ++#define F367_OFDM_OVF_RATE_HI 0xF01E000F ++ ++/* OVF_RATE2 */ ++#define R367_OFDM_OVF_RATE2 0xF01F ++#define F367_OFDM_OVF_RATE_LO 0xF01F00FF ++ ++/* GAIN_SRC1 */ ++#define R367_OFDM_GAIN_SRC1 0xF020 ++#define F367_OFDM_INV_SPECTR 0xF0200080 ++#define F367_OFDM_IQ_INVERT 0xF0200040 ++#define F367_OFDM_INR_BYPASS 0xF0200020 ++#define F367_OFDM_STATUS_INV_SPECRUM 0xF0200010 ++#define F367_OFDM_GAIN_SRC_HI 0xF020000F ++ ++/* GAIN_SRC2 */ ++#define R367_OFDM_GAIN_SRC2 0xF021 ++#define F367_OFDM_GAIN_SRC_LO 0xF02100FF ++ ++/* INC_DEROT1 */ ++#define R367_OFDM_INC_DEROT1 0xF022 ++#define F367_OFDM_INC_DEROT_HI 0xF02200FF ++ ++/* INC_DEROT2 */ ++#define R367_OFDM_INC_DEROT2 0xF023 ++#define F367_OFDM_INC_DEROT_LO 0xF02300FF ++ ++/* PPM_CPAMP_DIR */ ++#define R367_OFDM_PPM_CPAMP_DIR 0xF024 ++#define F367_OFDM_PPM_CPAMP_DIRECT 0xF02400FF ++ ++/* PPM_CPAMP_INV */ ++#define R367_OFDM_PPM_CPAMP_INV 0xF025 ++#define F367_OFDM_PPM_CPAMP_INVER 0xF02500FF ++ ++/* FREESTFE_1 */ ++#define R367_OFDM_FREESTFE_1 0xF026 ++#define F367_OFDM_SYMBOL_NUMBER_INC 0xF02600C0 ++#define F367_OFDM_SEL_LSB 0xF0260004 ++#define F367_OFDM_AVERAGE_ON 0xF0260002 ++#define F367_OFDM_DC_ADJ 0xF0260001 ++ ++/* FREESTFE_2 */ ++#define R367_OFDM_FREESTFE_2 0xF027 ++#define F367_OFDM_SEL_SRCOUT 0xF02700C0 ++#define F367_OFDM_SEL_SYRTHR 0xF027001F ++ ++/* DCOFFSET */ ++#define R367_OFDM_DCOFFSET 0xF028 ++#define F367_OFDM_SELECT_I_Q 0xF0280080 ++#define F367_OFDM_DC_OFFSET 0xF028007F ++ ++/* EN_PROCESS */ ++#define R367_OFDM_EN_PROCESS 0xF029 ++#define F367_OFDM_FREE 0xF02900F0 ++#define F367_OFDM_ENAB_MANUAL 0xF0290001 ++ ++/* SDI_SMOOTHER */ ++#define R367_OFDM_SDI_SMOOTHER 0xF02A ++#define F367_OFDM_DIS_SMOOTH 0xF02A0080 ++#define F367_OFDM_SDI_INC_SMOOTHER 0xF02A007F ++ ++/* FE_LOOP_OPEN */ ++#define R367_OFDM_FE_LOOP_OPEN 0xF02B ++#define F367_OFDM_TRL_LOOP_OP 0xF02B0002 ++#define F367_OFDM_CRL_LOOP_OP 0xF02B0001 ++ ++/* FREQOFF1 */ ++#define R367_OFDM_FREQOFF1 0xF02C ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI 0xF02C00FF ++ ++/* FREQOFF2 */ ++#define R367_OFDM_FREQOFF2 0xF02D ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI 0xF02D00FF ++ ++/* FREQOFF3 */ ++#define R367_OFDM_FREQOFF3 0xF02E ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO 0xF02E00FF ++ ++/* TIMOFF1 */ ++#define R367_OFDM_TIMOFF1 0xF02F ++#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI 0xF02F00FF ++ ++/* TIMOFF2 */ ++#define R367_OFDM_TIMOFF2 0xF030 ++#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO 0xF03000FF ++ ++/* EPQ */ ++#define R367_OFDM_EPQ 0xF031 ++#define F367_OFDM_EPQ1 0xF03100FF ++ ++/* EPQAUTO */ ++#define R367_OFDM_EPQAUTO 0xF032 ++#define F367_OFDM_EPQ2 0xF03200FF ++ ++/* SYR_UPDATE */ ++#define R367_OFDM_SYR_UPDATE 0xF033 ++#define F367_OFDM_SYR_PROTV 0xF0330080 ++#define F367_OFDM_SYR_PROTV_GAIN 0xF0330060 ++#define F367_OFDM_SYR_FILTER 0xF0330010 ++#define F367_OFDM_SYR_TRACK_THRES 0xF033000C ++ ++/* CHPFREE */ ++#define R367_OFDM_CHPFREE 0xF034 ++#define F367_OFDM_CHP_FREE 0xF03400FF ++ ++/* PPM_STATE_MAC */ ++#define R367_OFDM_PPM_STATE_MAC 0xF035 ++#define F367_OFDM_PPM_STATE_MACHINE_DECODER 0xF035003F ++ ++/* INR_THRESHOLD */ ++#define R367_OFDM_INR_THRESHOLD 0xF036 ++#define F367_OFDM_INR_THRESH 0xF03600FF ++ ++/* EPQ_TPS_ID_CELL */ ++#define R367_OFDM_EPQ_TPS_ID_CELL 0xF037 ++#define F367_OFDM_ENABLE_LGTH_TO_CF 0xF0370080 ++#define F367_OFDM_DIS_TPS_RSVD 0xF0370040 ++#define F367_OFDM_DIS_BCH 0xF0370020 ++#define F367_OFDM_DIS_ID_CEL 0xF0370010 ++#define F367_OFDM_TPS_ADJUST_SYM 0xF037000F ++ ++/* EPQ_CFG */ ++#define R367_OFDM_EPQ_CFG 0xF038 ++#define F367_OFDM_EPQ_RANGE 0xF0380002 ++#define F367_OFDM_EPQ_SOFT 0xF0380001 ++ ++/* EPQ_STATUS */ ++#define R367_OFDM_EPQ_STATUS 0xF039 ++#define F367_OFDM_SLOPE_INC 0xF03900FC ++#define F367_OFDM_TPS_FIELD 0xF0390003 ++ ++/* AUTORELOCK */ ++#define R367_OFDM_AUTORELOCK 0xF03A ++#define F367_OFDM_BYPASS_BER_TEMPO 0xF03A0080 ++#define F367_OFDM_BER_TEMPO 0xF03A0070 ++#define F367_OFDM_BYPASS_COFDM_TEMPO 0xF03A0008 ++#define F367_OFDM_COFDM_TEMPO 0xF03A0007 ++ ++/* BER_THR_VMSB */ ++#define R367_OFDM_BER_THR_VMSB 0xF03B ++#define F367_OFDM_BER_THRESHOLD_HI 0xF03B00FF ++ ++/* BER_THR_MSB */ ++#define R367_OFDM_BER_THR_MSB 0xF03C ++#define F367_OFDM_BER_THRESHOLD_MID 0xF03C00FF ++ ++/* BER_THR_LSB */ ++#define R367_OFDM_BER_THR_LSB 0xF03D ++#define F367_OFDM_BER_THRESHOLD_LO 0xF03D00FF ++ ++/* CCD */ ++#define R367_OFDM_CCD 0xF03E ++#define F367_OFDM_CCD_DETECTED 0xF03E0080 ++#define F367_OFDM_CCD_RESET 0xF03E0040 ++#define F367_OFDM_CCD_THRESHOLD 0xF03E000F ++ ++/* SPECTR_CFG */ ++#define R367_OFDM_SPECTR_CFG 0xF03F ++#define F367_OFDM_SPECT_CFG 0xF03F0003 ++ ++/* CONSTMU_MSB */ ++#define R367_OFDM_CONSTMU_MSB 0xF040 ++#define F367_OFDM_CONSTMU_FREEZE 0xF0400080 ++#define F367_OFDM_CONSTNU_FORCE_EN 0xF0400040 ++#define F367_OFDM_CONST_MU_MSB 0xF040003F ++ ++/* CONSTMU_LSB */ ++#define R367_OFDM_CONSTMU_LSB 0xF041 ++#define F367_OFDM_CONST_MU_LSB 0xF04100FF ++ ++/* CONSTMU_MAX_MSB */ ++#define R367_OFDM_CONSTMU_MAX_MSB 0xF042 ++#define F367_OFDM_CONST_MU_MAX_MSB 0xF042003F ++ ++/* CONSTMU_MAX_LSB */ ++#define R367_OFDM_CONSTMU_MAX_LSB 0xF043 ++#define F367_OFDM_CONST_MU_MAX_LSB 0xF04300FF ++ ++/* ALPHANOISE */ ++#define R367_OFDM_ALPHANOISE 0xF044 ++#define F367_OFDM_USE_ALLFILTER 0xF0440080 ++#define F367_OFDM_INTER_ON 0xF0440040 ++#define F367_OFDM_ALPHA_NOISE 0xF044001F ++ ++/* MAXGP_MSB */ ++#define R367_OFDM_MAXGP_MSB 0xF045 ++#define F367_OFDM_MUFILTER_LENGTH 0xF04500F0 ++#define F367_OFDM_MAX_GP_MSB 0xF045000F ++ ++/* MAXGP_LSB */ ++#define R367_OFDM_MAXGP_LSB 0xF046 ++#define F367_OFDM_MAX_GP_LSB 0xF04600FF ++ ++/* ALPHAMSB */ ++#define R367_OFDM_ALPHAMSB 0xF047 ++#define F367_OFDM_CHC_DATARATE 0xF04700C0 ++#define F367_OFDM_ALPHA_MSB 0xF047003F ++ ++/* ALPHALSB */ ++#define R367_OFDM_ALPHALSB 0xF048 ++#define F367_OFDM_ALPHA_LSB 0xF04800FF ++ ++/* PILOT_ACCU */ ++#define R367_OFDM_PILOT_ACCU 0xF049 ++#define F367_OFDM_USE_SCAT4ADDAPT 0xF0490080 ++#define F367_OFDM_PILOT_ACC 0xF049001F ++ ++/* PILOTMU_ACCU */ ++#define R367_OFDM_PILOTMU_ACCU 0xF04A ++#define F367_OFDM_DISCARD_BAD_SP 0xF04A0080 ++#define F367_OFDM_DISCARD_BAD_CP 0xF04A0040 ++#define F367_OFDM_PILOT_MU_ACCU 0xF04A001F ++ ++/* FILT_CHANNEL_EST */ ++#define R367_OFDM_FILT_CHANNEL_EST 0xF04B ++#define F367_OFDM_USE_FILT_PILOT 0xF04B0080 ++#define F367_OFDM_FILT_CHANNEL 0xF04B007F ++ ++/* ALPHA_NOPISE_FREQ */ ++#define R367_OFDM_ALPHA_NOPISE_FREQ 0xF04C ++#define F367_OFDM_NOISE_FREQ_FILT 0xF04C0040 ++#define F367_OFDM_ALPHA_NOISE_FREQ 0xF04C003F ++ ++/* RATIO_PILOT */ ++#define R367_OFDM_RATIO_PILOT 0xF04D ++#define F367_OFDM_RATIO_MEAN_SP 0xF04D00F0 ++#define F367_OFDM_RATIO_MEAN_CP 0xF04D000F ++ ++/* CHC_CTL */ ++#define R367_OFDM_CHC_CTL 0xF04E ++#define F367_OFDM_TRACK_EN 0xF04E0080 ++#define F367_OFDM_NOISE_NORM_EN 0xF04E0040 ++#define F367_OFDM_FORCE_CHC_RESET 0xF04E0020 ++#define F367_OFDM_SHORT_TIME 0xF04E0010 ++#define F367_OFDM_FORCE_STATE_EN 0xF04E0008 ++#define F367_OFDM_FORCE_STATE 0xF04E0007 ++ ++/* EPQ_ADJUST */ ++#define R367_OFDM_EPQ_ADJUST 0xF04F ++#define F367_OFDM_ADJUST_SCAT_IND 0xF04F00C0 ++#define F367_OFDM_ONE_SYMBOL 0xF04F0010 ++#define F367_OFDM_EPQ_DECAY 0xF04F000E ++#define F367_OFDM_HOLD_SLOPE 0xF04F0001 ++ ++/* EPQ_THRES */ ++#define R367_OFDM_EPQ_THRES 0xF050 ++#define F367_OFDM_EPQ_THR 0xF05000FF ++ ++/* OMEGA_CTL */ ++#define R367_OFDM_OMEGA_CTL 0xF051 ++#define F367_OFDM_OMEGA_RST 0xF0510080 ++#define F367_OFDM_FREEZE_OMEGA 0xF0510040 ++#define F367_OFDM_OMEGA_SEL 0xF051003F ++ ++/* GP_CTL */ ++#define R367_OFDM_GP_CTL 0xF052 ++#define F367_OFDM_CHC_STATE 0xF05200E0 ++#define F367_OFDM_FREEZE_GP 0xF0520010 ++#define F367_OFDM_GP_SEL 0xF052000F ++ ++/* MUMSB */ ++#define R367_OFDM_MUMSB 0xF053 ++#define F367_OFDM_MU_MSB 0xF053007F ++ ++/* MULSB */ ++#define R367_OFDM_MULSB 0xF054 ++#define F367_OFDM_MU_LSB 0xF05400FF ++ ++/* GPMSB */ ++#define R367_OFDM_GPMSB 0xF055 ++#define F367_OFDM_CSI_THRESHOLD 0xF05500E0 ++#define F367_OFDM_GP_MSB 0xF055000F ++ ++/* GPLSB */ ++#define R367_OFDM_GPLSB 0xF056 ++#define F367_OFDM_GP_LSB 0xF05600FF ++ ++/* OMEGAMSB */ ++#define R367_OFDM_OMEGAMSB 0xF057 ++#define F367_OFDM_OMEGA_MSB 0xF057007F ++ ++/* OMEGALSB */ ++#define R367_OFDM_OMEGALSB 0xF058 ++#define F367_OFDM_OMEGA_LSB 0xF05800FF ++ ++/* SCAT_NB */ ++#define R367_OFDM_SCAT_NB 0xF059 ++#define F367_OFDM_CHC_TEST 0xF05900F8 ++#define F367_OFDM_SCAT_NUMB 0xF0590003 ++ ++/* CHC_DUMMY */ ++#define R367_OFDM_CHC_DUMMY 0xF05A ++#define F367_OFDM_CHC_DUM 0xF05A00FF ++ ++/* INC_CTL */ ++#define R367_OFDM_INC_CTL 0xF05B ++#define F367_OFDM_INC_BYPASS 0xF05B0080 ++#define F367_OFDM_INC_NDEPTH 0xF05B000C ++#define F367_OFDM_INC_MADEPTH 0xF05B0003 ++ ++/* INCTHRES_COR1 */ ++#define R367_OFDM_INCTHRES_COR1 0xF05C ++#define F367_OFDM_INC_THRES_COR1 0xF05C00FF ++ ++/* INCTHRES_COR2 */ ++#define R367_OFDM_INCTHRES_COR2 0xF05D ++#define F367_OFDM_INC_THRES_COR2 0xF05D00FF ++ ++/* INCTHRES_DET1 */ ++#define R367_OFDM_INCTHRES_DET1 0xF05E ++#define F367_OFDM_INC_THRES_DET1 0xF05E003F ++ ++/* INCTHRES_DET2 */ ++#define R367_OFDM_INCTHRES_DET2 0xF05F ++#define F367_OFDM_INC_THRES_DET2 0xF05F003F ++ ++/* IIR_CELLNB */ ++#define R367_OFDM_IIR_CELLNB 0xF060 ++#define F367_OFDM_NRST_IIR 0xF0600080 ++#define F367_OFDM_IIR_CELL_NB 0xF0600007 ++ ++/* IIRCX_COEFF1_MSB */ ++#define R367_OFDM_IIRCX_COEFF1_MSB 0xF061 ++#define F367_OFDM_IIR_CX_COEFF1_MSB 0xF06100FF ++ ++/* IIRCX_COEFF1_LSB */ ++#define R367_OFDM_IIRCX_COEFF1_LSB 0xF062 ++#define F367_OFDM_IIR_CX_COEFF1_LSB 0xF06200FF ++ ++/* IIRCX_COEFF2_MSB */ ++#define R367_OFDM_IIRCX_COEFF2_MSB 0xF063 ++#define F367_OFDM_IIR_CX_COEFF2_MSB 0xF06300FF ++ ++/* IIRCX_COEFF2_LSB */ ++#define R367_OFDM_IIRCX_COEFF2_LSB 0xF064 ++#define F367_OFDM_IIR_CX_COEFF2_LSB 0xF06400FF ++ ++/* IIRCX_COEFF3_MSB */ ++#define R367_OFDM_IIRCX_COEFF3_MSB 0xF065 ++#define F367_OFDM_IIR_CX_COEFF3_MSB 0xF06500FF ++ ++/* IIRCX_COEFF3_LSB */ ++#define R367_OFDM_IIRCX_COEFF3_LSB 0xF066 ++#define F367_OFDM_IIR_CX_COEFF3_LSB 0xF06600FF ++ ++/* IIRCX_COEFF4_MSB */ ++#define R367_OFDM_IIRCX_COEFF4_MSB 0xF067 ++#define F367_OFDM_IIR_CX_COEFF4_MSB 0xF06700FF ++ ++/* IIRCX_COEFF4_LSB */ ++#define R367_OFDM_IIRCX_COEFF4_LSB 0xF068 ++#define F367_OFDM_IIR_CX_COEFF4_LSB 0xF06800FF ++ ++/* IIRCX_COEFF5_MSB */ ++#define R367_OFDM_IIRCX_COEFF5_MSB 0xF069 ++#define F367_OFDM_IIR_CX_COEFF5_MSB 0xF06900FF ++ ++/* IIRCX_COEFF5_LSB */ ++#define R367_OFDM_IIRCX_COEFF5_LSB 0xF06A ++#define F367_OFDM_IIR_CX_COEFF5_LSB 0xF06A00FF ++ ++/* FEPATH_CFG */ ++#define R367_OFDM_FEPATH_CFG 0xF06B ++#define F367_OFDM_DEMUX_SWAP 0xF06B0004 ++#define F367_OFDM_DIGAGC_SWAP 0xF06B0002 ++#define F367_OFDM_LONGPATH_IF 0xF06B0001 ++ ++/* PMC1_FUNC */ ++#define R367_OFDM_PMC1_FUNC 0xF06C ++#define F367_OFDM_SOFT_RSTN 0xF06C0080 ++#define F367_OFDM_PMC1_AVERAGE_TIME 0xF06C0078 ++#define F367_OFDM_PMC1_WAIT_TIME 0xF06C0006 ++#define F367_OFDM_PMC1_2N_SEL 0xF06C0001 ++ ++/* PMC1_FOR */ ++#define R367_OFDM_PMC1_FOR 0xF06D ++#define F367_OFDM_PMC1_FORCE 0xF06D0080 ++#define F367_OFDM_PMC1_FORCE_VALUE 0xF06D007C ++ ++/* PMC2_FUNC */ ++#define R367_OFDM_PMC2_FUNC 0xF06E ++#define F367_OFDM_PMC2_SOFT_STN 0xF06E0080 ++#define F367_OFDM_PMC2_ACCU_TIME 0xF06E0070 ++#define F367_OFDM_PMC2_CMDP_MN 0xF06E0008 ++#define F367_OFDM_PMC2_SWAP 0xF06E0004 ++ ++/* STATUS_ERR_DA */ ++#define R367_OFDM_STATUS_ERR_DA 0xF06F ++#define F367_OFDM_COM_USEGAINTRK 0xF06F0080 ++#define F367_OFDM_COM_AGCLOCK 0xF06F0040 ++#define F367_OFDM_AUT_AGCLOCK 0xF06F0020 ++#define F367_OFDM_MIN_ERR_X_LSB 0xF06F000F ++ ++/* DIG_AGC_R */ ++#define R367_OFDM_DIG_AGC_R 0xF070 ++#define F367_OFDM_COM_SOFT_RSTN 0xF0700080 ++#define F367_OFDM_COM_AGC_ON 0xF0700040 ++#define F367_OFDM_COM_EARLY 0xF0700020 ++#define F367_OFDM_AUT_SOFT_RESETN 0xF0700010 ++#define F367_OFDM_AUT_AGC_ON 0xF0700008 ++#define F367_OFDM_AUT_EARLY 0xF0700004 ++#define F367_OFDM_AUT_ROT_EN 0xF0700002 ++#define F367_OFDM_LOCK_SOFT_RESETN 0xF0700001 ++ ++/* COMAGC_TARMSB */ ++#define R367_OFDM_COMAGC_TARMSB 0xF071 ++#define F367_OFDM_COM_AGC_TARGET_MSB 0xF07100FF ++ ++/* COM_AGC_TAR_ENMODE */ ++#define R367_OFDM_COM_AGC_TAR_ENMODE 0xF072 ++#define F367_OFDM_COM_AGC_TARGET_LSB 0xF07200F0 ++#define F367_OFDM_COM_ENMODE 0xF072000F ++ ++/* COM_AGC_CFG */ ++#define R367_OFDM_COM_AGC_CFG 0xF073 ++#define F367_OFDM_COM_N 0xF07300F8 ++#define F367_OFDM_COM_STABMODE 0xF0730006 ++#define F367_OFDM_ERR_SEL 0xF0730001 ++ ++/* COM_AGC_GAIN1 */ ++#define R367_OFDM_COM_AGC_GAIN1 0xF074 ++#define F367_OFDM_COM_GAIN1ACK 0xF07400F0 ++#define F367_OFDM_COM_GAIN1TRK 0xF074000F ++ ++/* AUT_AGC_TARGETMSB */ ++#define R367_OFDM_AUT_AGC_TARGETMSB 0xF075 ++#define F367_OFDM_AUT_AGC_TARGET_MSB 0xF07500FF ++ ++/* LOCK_DET_MSB */ ++#define R367_OFDM_LOCK_DET_MSB 0xF076 ++#define F367_OFDM_LOCK_DETECT_MSB 0xF07600FF ++ ++/* AGCTAR_LOCK_LSBS */ ++#define R367_OFDM_AGCTAR_LOCK_LSBS 0xF077 ++#define F367_OFDM_AUT_AGC_TARGET_LSB 0xF07700F0 ++#define F367_OFDM_LOCK_DETECT_LSB 0xF077000F ++ ++/* AUT_GAIN_EN */ ++#define R367_OFDM_AUT_GAIN_EN 0xF078 ++#define F367_OFDM_AUT_ENMODE 0xF07800F0 ++#define F367_OFDM_AUT_GAIN2 0xF078000F ++ ++/* AUT_CFG */ ++#define R367_OFDM_AUT_CFG 0xF079 ++#define F367_OFDM_AUT_N 0xF07900F8 ++#define F367_OFDM_INT_CHOICE 0xF0790006 ++#define F367_OFDM_INT_LOAD 0xF0790001 ++ ++/* LOCKN */ ++#define R367_OFDM_LOCKN 0xF07A ++#define F367_OFDM_LOCK_N 0xF07A00F8 ++#define F367_OFDM_SEL_IQNTAR 0xF07A0004 ++#define F367_OFDM_LOCK_DETECT_CHOICE 0xF07A0003 ++ ++/* INT_X_3 */ ++#define R367_OFDM_INT_X_3 0xF07B ++#define F367_OFDM_INT_X3 0xF07B00FF ++ ++/* INT_X_2 */ ++#define R367_OFDM_INT_X_2 0xF07C ++#define F367_OFDM_INT_X2 0xF07C00FF ++ ++/* INT_X_1 */ ++#define R367_OFDM_INT_X_1 0xF07D ++#define F367_OFDM_INT_X1 0xF07D00FF ++ ++/* INT_X_0 */ ++#define R367_OFDM_INT_X_0 0xF07E ++#define F367_OFDM_INT_X0 0xF07E00FF ++ ++/* MIN_ERRX_MSB */ ++#define R367_OFDM_MIN_ERRX_MSB 0xF07F ++#define F367_OFDM_MIN_ERR_X_MSB 0xF07F00FF ++ ++/* COR_CTL */ ++#define R367_OFDM_COR_CTL 0xF080 ++#define F367_OFDM_CORE_ACTIVE 0xF0800020 ++#define F367_OFDM_HOLD 0xF0800010 ++#define F367_OFDM_CORE_STATE_CTL 0xF080000F ++ ++/* COR_STAT */ ++#define R367_OFDM_COR_STAT 0xF081 ++#define F367_OFDM_SCATT_LOCKED 0xF0810080 ++#define F367_OFDM_TPS_LOCKED 0xF0810040 ++#define F367_OFDM_SYR_LOCKED_COR 0xF0810020 ++#define F367_OFDM_AGC_LOCKED_STAT 0xF0810010 ++#define F367_OFDM_CORE_STATE_STAT 0xF081000F ++ ++/* COR_INTEN */ ++#define R367_OFDM_COR_INTEN 0xF082 ++#define F367_OFDM_INTEN 0xF0820080 ++#define F367_OFDM_INTEN_SYR 0xF0820020 ++#define F367_OFDM_INTEN_FFT 0xF0820010 ++#define F367_OFDM_INTEN_AGC 0xF0820008 ++#define F367_OFDM_INTEN_TPS1 0xF0820004 ++#define F367_OFDM_INTEN_TPS2 0xF0820002 ++#define F367_OFDM_INTEN_TPS3 0xF0820001 ++ ++/* COR_INTSTAT */ ++#define R367_OFDM_COR_INTSTAT 0xF083 ++#define F367_OFDM_INTSTAT_SYR 0xF0830020 ++#define F367_OFDM_INTSTAT_FFT 0xF0830010 ++#define F367_OFDM_INTSAT_AGC 0xF0830008 ++#define F367_OFDM_INTSTAT_TPS1 0xF0830004 ++#define F367_OFDM_INTSTAT_TPS2 0xF0830002 ++#define F367_OFDM_INTSTAT_TPS3 0xF0830001 ++ ++/* COR_MODEGUARD */ ++#define R367_OFDM_COR_MODEGUARD 0xF084 ++#define F367_OFDM_FORCE 0xF0840010 ++#define F367_OFDM_MODE 0xF084000C ++#define F367_OFDM_GUARD 0xF0840003 ++ ++/* AGC_CTL */ ++#define R367_OFDM_AGC_CTL 0xF085 ++#define F367_OFDM_AGC_TIMING_FACTOR 0xF08500E0 ++#define F367_OFDM_AGC_LAST 0xF0850010 ++#define F367_OFDM_AGC_GAIN 0xF085000C ++#define F367_OFDM_AGC_NEG 0xF0850002 ++#define F367_OFDM_AGC_SET 0xF0850001 ++ ++/* AGC_MANUAL1 */ ++#define R367_OFDM_AGC_MANUAL1 0xF086 ++#define F367_OFDM_AGC_VAL_LO 0xF08600FF ++ ++/* AGC_MANUAL2 */ ++#define R367_OFDM_AGC_MANUAL2 0xF087 ++#define F367_OFDM_AGC_VAL_HI 0xF087000F ++ ++/* AGC_TARG */ ++#define R367_OFDM_AGC_TARG 0xF088 ++#define F367_OFDM_AGC_TARGET 0xF08800FF ++ ++/* AGC_GAIN1 */ ++#define R367_OFDM_AGC_GAIN1 0xF089 ++#define F367_OFDM_AGC_GAIN_LO 0xF08900FF ++ ++/* AGC_GAIN2 */ ++#define R367_OFDM_AGC_GAIN2 0xF08A ++#define F367_OFDM_AGC_LOCKED_GAIN2 0xF08A0010 ++#define F367_OFDM_AGC_GAIN_HI 0xF08A000F ++ ++/* RESERVED_1 */ ++#define R367_OFDM_RESERVED_1 0xF08B ++#define F367_OFDM_RESERVED1 0xF08B00FF ++ ++/* RESERVED_2 */ ++#define R367_OFDM_RESERVED_2 0xF08C ++#define F367_OFDM_RESERVED2 0xF08C00FF ++ ++/* RESERVED_3 */ ++#define R367_OFDM_RESERVED_3 0xF08D ++#define F367_OFDM_RESERVED3 0xF08D00FF ++ ++/* CAS_CTL */ ++#define R367_OFDM_CAS_CTL 0xF08E ++#define F367_OFDM_CCS_ENABLE 0xF08E0080 ++#define F367_OFDM_ACS_DISABLE 0xF08E0040 ++#define F367_OFDM_DAGC_DIS 0xF08E0020 ++#define F367_OFDM_DAGC_GAIN 0xF08E0018 ++#define F367_OFDM_CCSMU 0xF08E0007 ++ ++/* CAS_FREQ */ ++#define R367_OFDM_CAS_FREQ 0xF08F ++#define F367_OFDM_CCS_FREQ 0xF08F00FF ++ ++/* CAS_DAGCGAIN */ ++#define R367_OFDM_CAS_DAGCGAIN 0xF090 ++#define F367_OFDM_CAS_DAGC_GAIN 0xF09000FF ++ ++/* SYR_CTL */ ++#define R367_OFDM_SYR_CTL 0xF091 ++#define F367_OFDM_SICTH_ENABLE 0xF0910080 ++#define F367_OFDM_LONG_ECHO 0xF0910078 ++#define F367_OFDM_AUTO_LE_EN 0xF0910004 ++#define F367_OFDM_SYR_BYPASS 0xF0910002 ++#define F367_OFDM_SYR_TR_DIS 0xF0910001 ++ ++/* SYR_STAT */ ++#define R367_OFDM_SYR_STAT 0xF092 ++#define F367_OFDM_SYR_LOCKED_STAT 0xF0920010 ++#define F367_OFDM_SYR_MODE 0xF092000C ++#define F367_OFDM_SYR_GUARD 0xF0920003 ++ ++/* SYR_NCO1 */ ++#define R367_OFDM_SYR_NCO1 0xF093 ++#define F367_OFDM_SYR_NCO_LO 0xF09300FF ++ ++/* SYR_NCO2 */ ++#define R367_OFDM_SYR_NCO2 0xF094 ++#define F367_OFDM_SYR_NCO_HI 0xF094003F ++ ++/* SYR_OFFSET1 */ ++#define R367_OFDM_SYR_OFFSET1 0xF095 ++#define F367_OFDM_SYR_OFFSET_LO 0xF09500FF ++ ++/* SYR_OFFSET2 */ ++#define R367_OFDM_SYR_OFFSET2 0xF096 ++#define F367_OFDM_SYR_OFFSET_HI 0xF096003F ++ ++/* FFT_CTL */ ++#define R367_OFDM_FFT_CTL 0xF097 ++#define F367_OFDM_SHIFT_FFT_TRIG 0xF0970018 ++#define F367_OFDM_FFT_TRIGGER 0xF0970004 ++#define F367_OFDM_FFT_MANUAL 0xF0970002 ++#define F367_OFDM_IFFT_MODE 0xF0970001 ++ ++/* SCR_CTL */ ++#define R367_OFDM_SCR_CTL 0xF098 ++#define F367_OFDM_SYRADJDECAY 0xF0980070 ++#define F367_OFDM_SCR_CPEDIS 0xF0980002 ++#define F367_OFDM_SCR_DIS 0xF0980001 ++ ++/* PPM_CTL1 */ ++#define R367_OFDM_PPM_CTL1 0xF099 ++#define F367_OFDM_PPM_MAXFREQ 0xF0990030 ++#define F367_OFDM_PPM_MAXTIM 0xF0990008 ++#define F367_OFDM_PPM_INVSEL 0xF0990004 ++#define F367_OFDM_PPM_SCATDIS 0xF0990002 ++#define F367_OFDM_PPM_BYP 0xF0990001 ++ ++/* TRL_CTL */ ++#define R367_OFDM_TRL_CTL 0xF09A ++#define F367_OFDM_TRL_NOMRATE_LSB 0xF09A0080 ++#define F367_OFDM_TRL_GAIN_FACTOR 0xF09A0078 ++#define F367_OFDM_TRL_LOOPGAIN 0xF09A0007 ++ ++/* TRL_NOMRATE1 */ ++#define R367_OFDM_TRL_NOMRATE1 0xF09B ++#define F367_OFDM_TRL_NOMRATE_LO 0xF09B00FF ++ ++/* TRL_NOMRATE2 */ ++#define R367_OFDM_TRL_NOMRATE2 0xF09C ++#define F367_OFDM_TRL_NOMRATE_HI 0xF09C00FF ++ ++/* TRL_TIME1 */ ++#define R367_OFDM_TRL_TIME1 0xF09D ++#define F367_OFDM_TRL_TOFFSET_LO 0xF09D00FF ++ ++/* TRL_TIME2 */ ++#define R367_OFDM_TRL_TIME2 0xF09E ++#define F367_OFDM_TRL_TOFFSET_HI 0xF09E00FF ++ ++/* CRL_CTL */ ++#define R367_OFDM_CRL_CTL 0xF09F ++#define F367_OFDM_CRL_DIS 0xF09F0080 ++#define F367_OFDM_CRL_GAIN_FACTOR 0xF09F0078 ++#define F367_OFDM_CRL_LOOPGAIN 0xF09F0007 ++ ++/* CRL_FREQ1 */ ++#define R367_OFDM_CRL_FREQ1 0xF0A0 ++#define F367_OFDM_CRL_FOFFSET_LO 0xF0A000FF ++ ++/* CRL_FREQ2 */ ++#define R367_OFDM_CRL_FREQ2 0xF0A1 ++#define F367_OFDM_CRL_FOFFSET_HI 0xF0A100FF ++ ++/* CRL_FREQ3 */ ++#define R367_OFDM_CRL_FREQ3 0xF0A2 ++#define F367_OFDM_CRL_FOFFSET_VHI 0xF0A200FF ++ ++/* TPS_SFRAME_CTL */ ++#define R367_OFDM_TPS_SFRAME_CTL 0xF0A3 ++#define F367_OFDM_TPS_SFRAME_SYNC 0xF0A30001 ++ ++/* CHC_SNR */ ++#define R367_OFDM_CHC_SNR 0xF0A4 ++#define F367_OFDM_CHCSNR 0xF0A400FF ++ ++/* BDI_CTL */ ++#define R367_OFDM_BDI_CTL 0xF0A5 ++#define F367_OFDM_BDI_LPSEL 0xF0A50002 ++#define F367_OFDM_BDI_SERIAL 0xF0A50001 ++ ++/* DMP_CTL */ ++#define R367_OFDM_DMP_CTL 0xF0A6 ++#define F367_OFDM_DMP_SCALING_FACTOR 0xF0A6001E ++#define F367_OFDM_DMP_SDDIS 0xF0A60001 ++ ++/* TPS_RCVD1 */ ++#define R367_OFDM_TPS_RCVD1 0xF0A7 ++#define F367_OFDM_TPS_CHANGE 0xF0A70040 ++#define F367_OFDM_BCH_OK 0xF0A70020 ++#define F367_OFDM_TPS_SYNC 0xF0A70010 ++#define F367_OFDM_TPS_FRAME 0xF0A70003 ++ ++/* TPS_RCVD2 */ ++#define R367_OFDM_TPS_RCVD2 0xF0A8 ++#define F367_OFDM_TPS_HIERMODE 0xF0A80070 ++#define F367_OFDM_TPS_CONST 0xF0A80003 ++ ++/* TPS_RCVD3 */ ++#define R367_OFDM_TPS_RCVD3 0xF0A9 ++#define F367_OFDM_TPS_LPCODE 0xF0A90070 ++#define F367_OFDM_TPS_HPCODE 0xF0A90007 ++ ++/* TPS_RCVD4 */ ++#define R367_OFDM_TPS_RCVD4 0xF0AA ++#define F367_OFDM_TPS_GUARD 0xF0AA0030 ++#define F367_OFDM_TPS_MODE 0xF0AA0003 ++ ++/* TPS_ID_CELL1 */ ++#define R367_OFDM_TPS_ID_CELL1 0xF0AB ++#define F367_OFDM_TPS_ID_CELL_LO 0xF0AB00FF ++ ++/* TPS_ID_CELL2 */ ++#define R367_OFDM_TPS_ID_CELL2 0xF0AC ++#define F367_OFDM_TPS_ID_CELL_HI 0xF0AC00FF ++ ++/* TPS_RCVD5_SET1 */ ++#define R367_OFDM_TPS_RCVD5_SET1 0xF0AD ++#define F367_OFDM_TPS_NA 0xF0AD00FC ++#define F367_OFDM_TPS_SETFRAME 0xF0AD0003 ++ ++/* TPS_SET2 */ ++#define R367_OFDM_TPS_SET2 0xF0AE ++#define F367_OFDM_TPS_SETHIERMODE 0xF0AE0070 ++#define F367_OFDM_TPS_SETCONST 0xF0AE0003 ++ ++/* TPS_SET3 */ ++#define R367_OFDM_TPS_SET3 0xF0AF ++#define F367_OFDM_TPS_SETLPCODE 0xF0AF0070 ++#define F367_OFDM_TPS_SETHPCODE 0xF0AF0007 ++ ++/* TPS_CTL */ ++#define R367_OFDM_TPS_CTL 0xF0B0 ++#define F367_OFDM_TPS_IMM 0xF0B00004 ++#define F367_OFDM_TPS_BCHDIS 0xF0B00002 ++#define F367_OFDM_TPS_UPDDIS 0xF0B00001 ++ ++/* CTL_FFTOSNUM */ ++#define R367_OFDM_CTL_FFTOSNUM 0xF0B1 ++#define F367_OFDM_SYMBOL_NUMBER 0xF0B1007F ++ ++/* TESTSELECT */ ++#define R367_OFDM_TESTSELECT 0xF0B2 ++#define F367_OFDM_TEST_SELECT 0xF0B2001F ++ ++/* MSC_REV */ ++#define R367_OFDM_MSC_REV 0xF0B3 ++#define F367_OFDM_REV_NUMBER 0xF0B300FF ++ ++/* PIR_CTL */ ++#define R367_OFDM_PIR_CTL 0xF0B4 ++#define F367_OFDM_FREEZE 0xF0B40001 ++ ++/* SNR_CARRIER1 */ ++#define R367_OFDM_SNR_CARRIER1 0xF0B5 ++#define F367_OFDM_SNR_CARRIER_LO 0xF0B500FF ++ ++/* SNR_CARRIER2 */ ++#define R367_OFDM_SNR_CARRIER2 0xF0B6 ++#define F367_OFDM_MEAN 0xF0B600C0 ++#define F367_OFDM_SNR_CARRIER_HI 0xF0B6001F ++ ++/* PPM_CPAMP */ ++#define R367_OFDM_PPM_CPAMP 0xF0B7 ++#define F367_OFDM_PPM_CPC 0xF0B700FF ++ ++/* TSM_AP0 */ ++#define R367_OFDM_TSM_AP0 0xF0B8 ++#define F367_OFDM_ADDRESS_BYTE_0 0xF0B800FF ++ ++/* TSM_AP1 */ ++#define R367_OFDM_TSM_AP1 0xF0B9 ++#define F367_OFDM_ADDRESS_BYTE_1 0xF0B900FF ++ ++/* TSM_AP2 */ ++#define R367_OFDM_TSM_AP2 0xF0BA ++#define F367_OFDM_DATA_BYTE_0 0xF0BA00FF ++ ++/* TSM_AP3 */ ++#define R367_OFDM_TSM_AP3 0xF0BB ++#define F367_OFDM_DATA_BYTE_1 0xF0BB00FF ++ ++/* TSM_AP4 */ ++#define R367_OFDM_TSM_AP4 0xF0BC ++#define F367_OFDM_DATA_BYTE_2 0xF0BC00FF ++ ++/* TSM_AP5 */ ++#define R367_OFDM_TSM_AP5 0xF0BD ++#define F367_OFDM_DATA_BYTE_3 0xF0BD00FF ++ ++/* TSM_AP6 */ ++#define R367_OFDM_TSM_AP6 0xF0BE ++#define F367_OFDM_TSM_AP_6 0xF0BE00FF ++ ++/* TSM_AP7 */ ++#define R367_OFDM_TSM_AP7 0xF0BF ++#define F367_OFDM_MEM_SELECT_BYTE 0xF0BF00FF ++ ++/* TSTRES */ ++#define R367_TSTRES 0xF0C0 ++#define F367_FRES_DISPLAY 0xF0C00080 ++#define F367_FRES_FIFO_AD 0xF0C00020 ++#define F367_FRESRS 0xF0C00010 ++#define F367_FRESACS 0xF0C00008 ++#define F367_FRESFEC 0xF0C00004 ++#define F367_FRES_PRIF 0xF0C00002 ++#define F367_FRESCORE 0xF0C00001 ++ ++/* ANACTRL */ ++#define R367_ANACTRL 0xF0C1 ++#define F367_BYPASS_XTAL 0xF0C10040 ++#define F367_BYPASS_PLLXN 0xF0C1000C ++#define F367_DIS_PAD_OSC 0xF0C10002 ++#define F367_STDBY_PLLXN 0xF0C10001 ++ ++/* TSTBUS */ ++#define R367_TSTBUS 0xF0C2 ++#define F367_TS_BYTE_CLK_INV 0xF0C20080 ++#define F367_CFG_IP 0xF0C20070 ++#define F367_CFG_TST 0xF0C2000F ++ ++/* TSTRATE */ ++#define R367_TSTRATE 0xF0C6 ++#define F367_FORCEPHA 0xF0C60080 ++#define F367_FNEWPHA 0xF0C60010 ++#define F367_FROT90 0xF0C60008 ++#define F367_FR 0xF0C60007 ++ ++/* CONSTMODE */ ++#define R367_OFDM_CONSTMODE 0xF0CB ++#define F367_OFDM_TST_PRIF 0xF0CB00E0 ++#define F367_OFDM_CAR_TYPE 0xF0CB0018 ++#define F367_OFDM_CONST_MODE 0xF0CB0003 ++ ++/* CONSTCARR1 */ ++#define R367_OFDM_CONSTCARR1 0xF0CC ++#define F367_OFDM_CONST_CARR_LO 0xF0CC00FF ++ ++/* CONSTCARR2 */ ++#define R367_OFDM_CONSTCARR2 0xF0CD ++#define F367_OFDM_CONST_CARR_HI 0xF0CD001F ++ ++/* ICONSTEL */ ++#define R367_OFDM_ICONSTEL 0xF0CE ++#define F367_OFDM_PICONSTEL 0xF0CE00FF ++ ++/* QCONSTEL */ ++#define R367_OFDM_QCONSTEL 0xF0CF ++#define F367_OFDM_PQCONSTEL 0xF0CF00FF ++ ++/* TSTBISTRES0 */ ++#define R367_OFDM_TSTBISTRES0 0xF0D0 ++#define F367_OFDM_BEND_PPM 0xF0D00080 ++#define F367_OFDM_BBAD_PPM 0xF0D00040 ++#define F367_OFDM_BEND_FFTW 0xF0D00020 ++#define F367_OFDM_BBAD_FFTW 0xF0D00010 ++#define F367_OFDM_BEND_FFT_BUF 0xF0D00008 ++#define F367_OFDM_BBAD_FFT_BUF 0xF0D00004 ++#define F367_OFDM_BEND_SYR 0xF0D00002 ++#define F367_OFDM_BBAD_SYR 0xF0D00001 ++ ++/* TSTBISTRES1 */ ++#define R367_OFDM_TSTBISTRES1 0xF0D1 ++#define F367_OFDM_BEND_CHC_CP 0xF0D10080 ++#define F367_OFDM_BBAD_CHC_CP 0xF0D10040 ++#define F367_OFDM_BEND_CHCI 0xF0D10020 ++#define F367_OFDM_BBAD_CHCI 0xF0D10010 ++#define F367_OFDM_BEND_BDI 0xF0D10008 ++#define F367_OFDM_BBAD_BDI 0xF0D10004 ++#define F367_OFDM_BEND_SDI 0xF0D10002 ++#define F367_OFDM_BBAD_SDI 0xF0D10001 ++ ++/* TSTBISTRES2 */ ++#define R367_OFDM_TSTBISTRES2 0xF0D2 ++#define F367_OFDM_BEND_CHC_INC 0xF0D20080 ++#define F367_OFDM_BBAD_CHC_INC 0xF0D20040 ++#define F367_OFDM_BEND_CHC_SPP 0xF0D20020 ++#define F367_OFDM_BBAD_CHC_SPP 0xF0D20010 ++#define F367_OFDM_BEND_CHC_CPP 0xF0D20008 ++#define F367_OFDM_BBAD_CHC_CPP 0xF0D20004 ++#define F367_OFDM_BEND_CHC_SP 0xF0D20002 ++#define F367_OFDM_BBAD_CHC_SP 0xF0D20001 ++ ++/* TSTBISTRES3 */ ++#define R367_OFDM_TSTBISTRES3 0xF0D3 ++#define F367_OFDM_BEND_QAM 0xF0D30080 ++#define F367_OFDM_BBAD_QAM 0xF0D30040 ++#define F367_OFDM_BEND_SFEC_VIT 0xF0D30020 ++#define F367_OFDM_BBAD_SFEC_VIT 0xF0D30010 ++#define F367_OFDM_BEND_SFEC_DLINE 0xF0D30008 ++#define F367_OFDM_BBAD_SFEC_DLINE 0xF0D30004 ++#define F367_OFDM_BEND_SFEC_HW 0xF0D30002 ++#define F367_OFDM_BBAD_SFEC_HW 0xF0D30001 ++ ++/* RF_AGC1 */ ++#define R367_RF_AGC1 0xF0D4 ++#define F367_RF_AGC1_LEVEL_HI 0xF0D400FF ++ ++/* RF_AGC2 */ ++#define R367_RF_AGC2 0xF0D5 ++#define F367_REF_ADGP 0xF0D50080 ++#define F367_STDBY_ADCGP 0xF0D50020 ++#define F367_CHANNEL_SEL 0xF0D5001C ++#define F367_RF_AGC1_LEVEL_LO 0xF0D50003 ++ ++/* ANADIGCTRL */ ++#define R367_ANADIGCTRL 0xF0D7 ++#define F367_SEL_CLKDEM 0xF0D70020 ++#define F367_EN_BUFFER_Q 0xF0D70010 ++#define F367_EN_BUFFER_I 0xF0D70008 ++#define F367_ADC_RIS_EGDE 0xF0D70004 ++#define F367_SGN_ADC 0xF0D70002 ++#define F367_SEL_AD12_SYNC 0xF0D70001 ++ ++/* PLLMDIV */ ++#define R367_PLLMDIV 0xF0D8 ++#define F367_PLL_MDIV 0xF0D800FF ++ ++/* PLLNDIV */ ++#define R367_PLLNDIV 0xF0D9 ++#define F367_PLL_NDIV 0xF0D900FF ++ ++/* PLLSETUP */ ++#define R367_PLLSETUP 0xF0DA ++#define F367_PLL_PDIV 0xF0DA0070 ++#define F367_PLL_KDIV 0xF0DA000F ++ ++/* DUAL_AD12 */ ++#define R367_DUAL_AD12 0xF0DB ++#define F367_FS20M 0xF0DB0020 ++#define F367_FS50M 0xF0DB0010 ++#define F367_INMODE0 0xF0DB0008 ++#define F367_POFFQ 0xF0DB0004 ++#define F367_POFFI 0xF0DB0002 ++#define F367_INMODE1 0xF0DB0001 ++ ++/* TSTBIST */ ++#define R367_TSTBIST 0xF0DC ++#define F367_TST_BYP_CLK 0xF0DC0080 ++#define F367_TST_GCLKENA_STD 0xF0DC0040 ++#define F367_TST_GCLKENA 0xF0DC0020 ++#define F367_TST_MEMBIST 0xF0DC001F ++ ++/* PAD_COMP_CTRL */ ++#define R367_PAD_COMP_CTRL 0xF0DD ++#define F367_COMPTQ 0xF0DD0010 ++#define F367_COMPEN 0xF0DD0008 ++#define F367_FREEZE2 0xF0DD0004 ++#define F367_SLEEP_INHBT 0xF0DD0002 ++#define F367_CHIP_SLEEP 0xF0DD0001 ++ ++/* PAD_COMP_WR */ ++#define R367_PAD_COMP_WR 0xF0DE ++#define F367_WR_ASRC 0xF0DE007F ++ ++/* PAD_COMP_RD */ ++#define R367_PAD_COMP_RD 0xF0DF ++#define F367_COMPOK 0xF0DF0080 ++#define F367_RD_ASRC 0xF0DF007F ++ ++/* SYR_TARGET_FFTADJT_MSB */ ++#define R367_OFDM_SYR_TARGET_FFTADJT_MSB 0xF100 ++#define F367_OFDM_SYR_START 0xF1000080 ++#define F367_OFDM_SYR_TARGET_FFTADJ_HI 0xF100000F ++ ++/* SYR_TARGET_FFTADJT_LSB */ ++#define R367_OFDM_SYR_TARGET_FFTADJT_LSB 0xF101 ++#define F367_OFDM_SYR_TARGET_FFTADJ_LO 0xF10100FF ++ ++/* SYR_TARGET_CHCADJT_MSB */ ++#define R367_OFDM_SYR_TARGET_CHCADJT_MSB 0xF102 ++#define F367_OFDM_SYR_TARGET_CHCADJ_HI 0xF102000F ++ ++/* SYR_TARGET_CHCADJT_LSB */ ++#define R367_OFDM_SYR_TARGET_CHCADJT_LSB 0xF103 ++#define F367_OFDM_SYR_TARGET_CHCADJ_LO 0xF10300FF ++ ++/* SYR_FLAG */ ++#define R367_OFDM_SYR_FLAG 0xF104 ++#define F367_OFDM_TRIG_FLG1 0xF1040080 ++#define F367_OFDM_TRIG_FLG0 0xF1040040 ++#define F367_OFDM_FFT_FLG1 0xF1040008 ++#define F367_OFDM_FFT_FLG0 0xF1040004 ++#define F367_OFDM_CHC_FLG1 0xF1040002 ++#define F367_OFDM_CHC_FLG0 0xF1040001 ++ ++/* CRL_TARGET1 */ ++#define R367_OFDM_CRL_TARGET1 0xF105 ++#define F367_OFDM_CRL_START 0xF1050080 ++#define F367_OFDM_CRL_TARGET_VHI 0xF105000F ++ ++/* CRL_TARGET2 */ ++#define R367_OFDM_CRL_TARGET2 0xF106 ++#define F367_OFDM_CRL_TARGET_HI 0xF10600FF ++ ++/* CRL_TARGET3 */ ++#define R367_OFDM_CRL_TARGET3 0xF107 ++#define F367_OFDM_CRL_TARGET_LO 0xF10700FF ++ ++/* CRL_TARGET4 */ ++#define R367_OFDM_CRL_TARGET4 0xF108 ++#define F367_OFDM_CRL_TARGET_VLO 0xF10800FF ++ ++/* CRL_FLAG */ ++#define R367_OFDM_CRL_FLAG 0xF109 ++#define F367_OFDM_CRL_FLAG1 0xF1090002 ++#define F367_OFDM_CRL_FLAG0 0xF1090001 ++ ++/* TRL_TARGET1 */ ++#define R367_OFDM_TRL_TARGET1 0xF10A ++#define F367_OFDM_TRL_TARGET_HI 0xF10A00FF ++ ++/* TRL_TARGET2 */ ++#define R367_OFDM_TRL_TARGET2 0xF10B ++#define F367_OFDM_TRL_TARGET_LO 0xF10B00FF ++ ++/* TRL_CHC */ ++#define R367_OFDM_TRL_CHC 0xF10C ++#define F367_OFDM_TRL_START 0xF10C0080 ++#define F367_OFDM_CHC_START 0xF10C0040 ++#define F367_OFDM_TRL_FLAG1 0xF10C0002 ++#define F367_OFDM_TRL_FLAG0 0xF10C0001 ++ ++/* CHC_SNR_TARG */ ++#define R367_OFDM_CHC_SNR_TARG 0xF10D ++#define F367_OFDM_CHC_SNR_TARGET 0xF10D00FF ++ ++/* TOP_TRACK */ ++#define R367_OFDM_TOP_TRACK 0xF10E ++#define F367_OFDM_TOP_START 0xF10E0080 ++#define F367_OFDM_FIRST_FLAG 0xF10E0070 ++#define F367_OFDM_TOP_FLAG1 0xF10E0008 ++#define F367_OFDM_TOP_FLAG0 0xF10E0004 ++#define F367_OFDM_CHC_FLAG1 0xF10E0002 ++#define F367_OFDM_CHC_FLAG0 0xF10E0001 ++ ++/* TRACKER_FREE1 */ ++#define R367_OFDM_TRACKER_FREE1 0xF10F ++#define F367_OFDM_TRACKER_FREE_1 0xF10F00FF ++ ++/* ERROR_CRL1 */ ++#define R367_OFDM_ERROR_CRL1 0xF110 ++#define F367_OFDM_ERROR_CRL_VHI 0xF11000FF ++ ++/* ERROR_CRL2 */ ++#define R367_OFDM_ERROR_CRL2 0xF111 ++#define F367_OFDM_ERROR_CRL_HI 0xF11100FF ++ ++/* ERROR_CRL3 */ ++#define R367_OFDM_ERROR_CRL3 0xF112 ++#define F367_OFDM_ERROR_CRL_LOI 0xF11200FF ++ ++/* ERROR_CRL4 */ ++#define R367_OFDM_ERROR_CRL4 0xF113 ++#define F367_OFDM_ERROR_CRL_VLO 0xF11300FF ++ ++/* DEC_NCO1 */ ++#define R367_OFDM_DEC_NCO1 0xF114 ++#define F367_OFDM_DEC_NCO_VHI 0xF11400FF ++ ++/* DEC_NCO2 */ ++#define R367_OFDM_DEC_NCO2 0xF115 ++#define F367_OFDM_DEC_NCO_HI 0xF11500FF ++ ++/* DEC_NCO3 */ ++#define R367_OFDM_DEC_NCO3 0xF116 ++#define F367_OFDM_DEC_NCO_LO 0xF11600FF ++ ++/* SNR */ ++#define R367_OFDM_SNR 0xF117 ++#define F367_OFDM_SNRATIO 0xF11700FF ++ ++/* SYR_FFTADJ1 */ ++#define R367_OFDM_SYR_FFTADJ1 0xF118 ++#define F367_OFDM_SYR_FFTADJ_HI 0xF11800FF ++ ++/* SYR_FFTADJ2 */ ++#define R367_OFDM_SYR_FFTADJ2 0xF119 ++#define F367_OFDM_SYR_FFTADJ_LO 0xF11900FF ++ ++/* SYR_CHCADJ1 */ ++#define R367_OFDM_SYR_CHCADJ1 0xF11A ++#define F367_OFDM_SYR_CHCADJ_HI 0xF11A00FF ++ ++/* SYR_CHCADJ2 */ ++#define R367_OFDM_SYR_CHCADJ2 0xF11B ++#define F367_OFDM_SYR_CHCADJ_LO 0xF11B00FF ++ ++/* SYR_OFF */ ++#define R367_OFDM_SYR_OFF 0xF11C ++#define F367_OFDM_SYR_OFFSET 0xF11C00FF ++ ++/* PPM_OFFSET1 */ ++#define R367_OFDM_PPM_OFFSET1 0xF11D ++#define F367_OFDM_PPM_OFFSET_HI 0xF11D00FF ++ ++/* PPM_OFFSET2 */ ++#define R367_OFDM_PPM_OFFSET2 0xF11E ++#define F367_OFDM_PPM_OFFSET_LO 0xF11E00FF ++ ++/* TRACKER_FREE2 */ ++#define R367_OFDM_TRACKER_FREE2 0xF11F ++#define F367_OFDM_TRACKER_FREE_2 0xF11F00FF ++ ++/* DEBG_LT10 */ ++#define R367_OFDM_DEBG_LT10 0xF120 ++#define F367_OFDM_DEBUG_LT10 0xF12000FF ++ ++/* DEBG_LT11 */ ++#define R367_OFDM_DEBG_LT11 0xF121 ++#define F367_OFDM_DEBUG_LT11 0xF12100FF ++ ++/* DEBG_LT12 */ ++#define R367_OFDM_DEBG_LT12 0xF122 ++#define F367_OFDM_DEBUG_LT12 0xF12200FF ++ ++/* DEBG_LT13 */ ++#define R367_OFDM_DEBG_LT13 0xF123 ++#define F367_OFDM_DEBUG_LT13 0xF12300FF ++ ++/* DEBG_LT14 */ ++#define R367_OFDM_DEBG_LT14 0xF124 ++#define F367_OFDM_DEBUG_LT14 0xF12400FF ++ ++/* DEBG_LT15 */ ++#define R367_OFDM_DEBG_LT15 0xF125 ++#define F367_OFDM_DEBUG_LT15 0xF12500FF ++ ++/* DEBG_LT16 */ ++#define R367_OFDM_DEBG_LT16 0xF126 ++#define F367_OFDM_DEBUG_LT16 0xF12600FF ++ ++/* DEBG_LT17 */ ++#define R367_OFDM_DEBG_LT17 0xF127 ++#define F367_OFDM_DEBUG_LT17 0xF12700FF ++ ++/* DEBG_LT18 */ ++#define R367_OFDM_DEBG_LT18 0xF128 ++#define F367_OFDM_DEBUG_LT18 0xF12800FF ++ ++/* DEBG_LT19 */ ++#define R367_OFDM_DEBG_LT19 0xF129 ++#define F367_OFDM_DEBUG_LT19 0xF12900FF ++ ++/* DEBG_LT1A */ ++#define R367_OFDM_DEBG_LT1A 0xF12A ++#define F367_OFDM_DEBUG_LT1A 0xF12A00FF ++ ++/* DEBG_LT1B */ ++#define R367_OFDM_DEBG_LT1B 0xF12B ++#define F367_OFDM_DEBUG_LT1B 0xF12B00FF ++ ++/* DEBG_LT1C */ ++#define R367_OFDM_DEBG_LT1C 0xF12C ++#define F367_OFDM_DEBUG_LT1C 0xF12C00FF ++ ++/* DEBG_LT1D */ ++#define R367_OFDM_DEBG_LT1D 0xF12D ++#define F367_OFDM_DEBUG_LT1D 0xF12D00FF ++ ++/* DEBG_LT1E */ ++#define R367_OFDM_DEBG_LT1E 0xF12E ++#define F367_OFDM_DEBUG_LT1E 0xF12E00FF ++ ++/* DEBG_LT1F */ ++#define R367_OFDM_DEBG_LT1F 0xF12F ++#define F367_OFDM_DEBUG_LT1F 0xF12F00FF ++ ++/* RCCFGH */ ++#define R367_OFDM_RCCFGH 0xF200 ++#define F367_OFDM_TSRCFIFO_DVBCI 0xF2000080 ++#define F367_OFDM_TSRCFIFO_SERIAL 0xF2000040 ++#define F367_OFDM_TSRCFIFO_DISABLE 0xF2000020 ++#define F367_OFDM_TSFIFO_2TORC 0xF2000010 ++#define F367_OFDM_TSRCFIFO_HSGNLOUT 0xF2000008 ++#define F367_OFDM_TSRCFIFO_ERRMODE 0xF2000006 ++#define F367_OFDM_RCCFGH_0 0xF2000001 ++ ++/* RCCFGM */ ++#define R367_OFDM_RCCFGM 0xF201 ++#define F367_OFDM_TSRCFIFO_MANSPEED 0xF20100C0 ++#define F367_OFDM_TSRCFIFO_PERMDATA 0xF2010020 ++#define F367_OFDM_TSRCFIFO_NONEWSGNL 0xF2010010 ++#define F367_OFDM_RCBYTE_OVERSAMPLING 0xF201000E ++#define F367_OFDM_TSRCFIFO_INVDATA 0xF2010001 ++ ++/* RCCFGL */ ++#define R367_OFDM_RCCFGL 0xF202 ++#define F367_OFDM_TSRCFIFO_BCLKDEL1CK 0xF20200C0 ++#define F367_OFDM_RCCFGL_5 0xF2020020 ++#define F367_OFDM_TSRCFIFO_DUTY50 0xF2020010 ++#define F367_OFDM_TSRCFIFO_NSGNL2DATA 0xF2020008 ++#define F367_OFDM_TSRCFIFO_DISSERMUX 0xF2020004 ++#define F367_OFDM_RCCFGL_1 0xF2020002 ++#define F367_OFDM_TSRCFIFO_STOPCKDIS 0xF2020001 ++ ++/* RCINSDELH */ ++#define R367_OFDM_RCINSDELH 0xF203 ++#define F367_OFDM_TSRCDEL_SYNCBYTE 0xF2030080 ++#define F367_OFDM_TSRCDEL_XXHEADER 0xF2030040 ++#define F367_OFDM_TSRCDEL_BBHEADER 0xF2030020 ++#define F367_OFDM_TSRCDEL_DATAFIELD 0xF2030010 ++#define F367_OFDM_TSRCINSDEL_ISCR 0xF2030008 ++#define F367_OFDM_TSRCINSDEL_NPD 0xF2030004 ++#define F367_OFDM_TSRCINSDEL_RSPARITY 0xF2030002 ++#define F367_OFDM_TSRCINSDEL_CRC8 0xF2030001 ++ ++/* RCINSDELM */ ++#define R367_OFDM_RCINSDELM 0xF204 ++#define F367_OFDM_TSRCINS_BBPADDING 0xF2040080 ++#define F367_OFDM_TSRCINS_BCHFEC 0xF2040040 ++#define F367_OFDM_TSRCINS_LDPCFEC 0xF2040020 ++#define F367_OFDM_TSRCINS_EMODCOD 0xF2040010 ++#define F367_OFDM_TSRCINS_TOKEN 0xF2040008 ++#define F367_OFDM_TSRCINS_XXXERR 0xF2040004 ++#define F367_OFDM_TSRCINS_MATYPE 0xF2040002 ++#define F367_OFDM_TSRCINS_UPL 0xF2040001 ++ ++/* RCINSDELL */ ++#define R367_OFDM_RCINSDELL 0xF205 ++#define F367_OFDM_TSRCINS_DFL 0xF2050080 ++#define F367_OFDM_TSRCINS_SYNCD 0xF2050040 ++#define F367_OFDM_TSRCINS_BLOCLEN 0xF2050020 ++#define F367_OFDM_TSRCINS_SIGPCOUNT 0xF2050010 ++#define F367_OFDM_TSRCINS_FIFO 0xF2050008 ++#define F367_OFDM_TSRCINS_REALPACK 0xF2050004 ++#define F367_OFDM_TSRCINS_TSCONFIG 0xF2050002 ++#define F367_OFDM_TSRCINS_LATENCY 0xF2050001 ++ ++/* RCSTATUS */ ++#define R367_OFDM_RCSTATUS 0xF206 ++#define F367_OFDM_TSRCFIFO_LINEOK 0xF2060080 ++#define F367_OFDM_TSRCFIFO_ERROR 0xF2060040 ++#define F367_OFDM_TSRCFIFO_DATA7 0xF2060020 ++#define F367_OFDM_RCSTATUS_4 0xF2060010 ++#define F367_OFDM_TSRCFIFO_DEMODSEL 0xF2060008 ++#define F367_OFDM_TSRC1FIFOSPEED_STORE 0xF2060004 ++#define F367_OFDM_RCSTATUS_1 0xF2060002 ++#define F367_OFDM_TSRCSERIAL_IMPOSSIBLE 0xF2060001 ++ ++/* RCSPEED */ ++#define R367_OFDM_RCSPEED 0xF207 ++#define F367_OFDM_TSRCFIFO_OUTSPEED 0xF20700FF ++ ++/* RCDEBUGM */ ++#define R367_OFDM_RCDEBUGM 0xF208 ++#define F367_OFDM_SD_UNSYNC 0xF2080080 ++#define F367_OFDM_ULFLOCK_DETECTM 0xF2080040 ++#define F367_OFDM_SUL_SELECTOS 0xF2080020 ++#define F367_OFDM_DILUL_NOSCRBLE 0xF2080010 ++#define F367_OFDM_NUL_SCRB 0xF2080008 ++#define F367_OFDM_UL_SCRB 0xF2080004 ++#define F367_OFDM_SCRAULBAD 0xF2080002 ++#define F367_OFDM_SCRAUL_UNSYNC 0xF2080001 ++ ++/* RCDEBUGL */ ++#define R367_OFDM_RCDEBUGL 0xF209 ++#define F367_OFDM_RS_ERR 0xF2090080 ++#define F367_OFDM_LLFLOCK_DETECTM 0xF2090040 ++#define F367_OFDM_NOT_SUL_SELECTOS 0xF2090020 ++#define F367_OFDM_DILLL_NOSCRBLE 0xF2090010 ++#define F367_OFDM_NLL_SCRB 0xF2090008 ++#define F367_OFDM_LL_SCRB 0xF2090004 ++#define F367_OFDM_SCRALLBAD 0xF2090002 ++#define F367_OFDM_SCRALL_UNSYNC 0xF2090001 ++ ++/* RCOBSCFG */ ++#define R367_OFDM_RCOBSCFG 0xF20A ++#define F367_OFDM_TSRCFIFO_OBSCFG 0xF20A00FF ++ ++/* RCOBSM */ ++#define R367_OFDM_RCOBSM 0xF20B ++#define F367_OFDM_TSRCFIFO_OBSDATA_HI 0xF20B00FF ++ ++/* RCOBSL */ ++#define R367_OFDM_RCOBSL 0xF20C ++#define F367_OFDM_TSRCFIFO_OBSDATA_LO 0xF20C00FF ++ ++/* RCFECSPY */ ++#define R367_OFDM_RCFECSPY 0xF210 ++#define F367_OFDM_SPYRC_ENABLE 0xF2100080 ++#define F367_OFDM_RCNO_SYNCBYTE 0xF2100040 ++#define F367_OFDM_RCSERIAL_MODE 0xF2100020 ++#define F367_OFDM_RCUNUSUAL_PACKET 0xF2100010 ++#define F367_OFDM_BERRCMETER_DATAMODE 0xF210000C ++#define F367_OFDM_BERRCMETER_LMODE 0xF2100002 ++#define F367_OFDM_BERRCMETER_RESET 0xF2100001 ++ ++/* RCFSPYCFG */ ++#define R367_OFDM_RCFSPYCFG 0xF211 ++#define F367_OFDM_FECSPYRC_INPUT 0xF21100C0 ++#define F367_OFDM_RCRST_ON_ERROR 0xF2110020 ++#define F367_OFDM_RCONE_SHOT 0xF2110010 ++#define F367_OFDM_RCI2C_MODE 0xF211000C ++#define F367_OFDM_SPYRC_HSTERESIS 0xF2110003 ++ ++/* RCFSPYDATA */ ++#define R367_OFDM_RCFSPYDATA 0xF212 ++#define F367_OFDM_SPYRC_STUFFING 0xF2120080 ++#define F367_OFDM_RCNOERR_PKTJITTER 0xF2120040 ++#define F367_OFDM_SPYRC_CNULLPKT 0xF2120020 ++#define F367_OFDM_SPYRC_OUTDATA_MODE 0xF212001F ++ ++/* RCFSPYOUT */ ++#define R367_OFDM_RCFSPYOUT 0xF213 ++#define F367_OFDM_FSPYRC_DIRECT 0xF2130080 ++#define F367_OFDM_RCFSPYOUT_6 0xF2130040 ++#define F367_OFDM_SPYRC_OUTDATA_BUS 0xF2130038 ++#define F367_OFDM_RCSTUFF_MODE 0xF2130007 ++ ++/* RCFSTATUS */ ++#define R367_OFDM_RCFSTATUS 0xF214 ++#define F367_OFDM_SPYRC_ENDSIM 0xF2140080 ++#define F367_OFDM_RCVALID_SIM 0xF2140040 ++#define F367_OFDM_RCFOUND_SIGNAL 0xF2140020 ++#define F367_OFDM_RCDSS_SYNCBYTE 0xF2140010 ++#define F367_OFDM_RCRESULT_STATE 0xF214000F ++ ++/* RCFGOODPACK */ ++#define R367_OFDM_RCFGOODPACK 0xF215 ++#define F367_OFDM_RCGOOD_PACKET 0xF21500FF ++ ++/* RCFPACKCNT */ ++#define R367_OFDM_RCFPACKCNT 0xF216 ++#define F367_OFDM_RCPACKET_COUNTER 0xF21600FF ++ ++/* RCFSPYMISC */ ++#define R367_OFDM_RCFSPYMISC 0xF217 ++#define F367_OFDM_RCLABEL_COUNTER 0xF21700FF ++ ++/* RCFBERCPT4 */ ++#define R367_OFDM_RCFBERCPT4 0xF218 ++#define F367_OFDM_FBERRCMETER_CPT_MMMMSB 0xF21800FF ++ ++/* RCFBERCPT3 */ ++#define R367_OFDM_RCFBERCPT3 0xF219 ++#define F367_OFDM_FBERRCMETER_CPT_MMMSB 0xF21900FF ++ ++/* RCFBERCPT2 */ ++#define R367_OFDM_RCFBERCPT2 0xF21A ++#define F367_OFDM_FBERRCMETER_CPT_MMSB 0xF21A00FF ++ ++/* RCFBERCPT1 */ ++#define R367_OFDM_RCFBERCPT1 0xF21B ++#define F367_OFDM_FBERRCMETER_CPT_MSB 0xF21B00FF ++ ++/* RCFBERCPT0 */ ++#define R367_OFDM_RCFBERCPT0 0xF21C ++#define F367_OFDM_FBERRCMETER_CPT_LSB 0xF21C00FF ++ ++/* RCFBERERR2 */ ++#define R367_OFDM_RCFBERERR2 0xF21D ++#define F367_OFDM_FBERRCMETER_ERR_HI 0xF21D00FF ++ ++/* RCFBERERR1 */ ++#define R367_OFDM_RCFBERERR1 0xF21E ++#define F367_OFDM_FBERRCMETER_ERR 0xF21E00FF ++ ++/* RCFBERERR0 */ ++#define R367_OFDM_RCFBERERR0 0xF21F ++#define F367_OFDM_FBERRCMETER_ERR_LO 0xF21F00FF ++ ++/* RCFSTATESM */ ++#define R367_OFDM_RCFSTATESM 0xF220 ++#define F367_OFDM_RCRSTATE_F 0xF2200080 ++#define F367_OFDM_RCRSTATE_E 0xF2200040 ++#define F367_OFDM_RCRSTATE_D 0xF2200020 ++#define F367_OFDM_RCRSTATE_C 0xF2200010 ++#define F367_OFDM_RCRSTATE_B 0xF2200008 ++#define F367_OFDM_RCRSTATE_A 0xF2200004 ++#define F367_OFDM_RCRSTATE_9 0xF2200002 ++#define F367_OFDM_RCRSTATE_8 0xF2200001 ++ ++/* RCFSTATESL */ ++#define R367_OFDM_RCFSTATESL 0xF221 ++#define F367_OFDM_RCRSTATE_7 0xF2210080 ++#define F367_OFDM_RCRSTATE_6 0xF2210040 ++#define F367_OFDM_RCRSTATE_5 0xF2210020 ++#define F367_OFDM_RCRSTATE_4 0xF2210010 ++#define F367_OFDM_RCRSTATE_3 0xF2210008 ++#define F367_OFDM_RCRSTATE_2 0xF2210004 ++#define F367_OFDM_RCRSTATE_1 0xF2210002 ++#define F367_OFDM_RCRSTATE_0 0xF2210001 ++ ++/* RCFSPYBER */ ++#define R367_OFDM_RCFSPYBER 0xF222 ++#define F367_OFDM_RCFSPYBER_7 0xF2220080 ++#define F367_OFDM_SPYRCOBS_XORREAD 0xF2220040 ++#define F367_OFDM_FSPYRCBER_OBSMODE 0xF2220020 ++#define F367_OFDM_FSPYRCBER_SYNCBYT 0xF2220010 ++#define F367_OFDM_FSPYRCBER_UNSYNC 0xF2220008 ++#define F367_OFDM_FSPYRCBER_CTIME 0xF2220007 ++ ++/* RCFSPYDISTM */ ++#define R367_OFDM_RCFSPYDISTM 0xF223 ++#define F367_OFDM_RCPKTTIME_DISTANCE_HI 0xF22300FF ++ ++/* RCFSPYDISTL */ ++#define R367_OFDM_RCFSPYDISTL 0xF224 ++#define F367_OFDM_RCPKTTIME_DISTANCE_LO 0xF22400FF ++ ++/* RCFSPYOBS7 */ ++#define R367_OFDM_RCFSPYOBS7 0xF228 ++#define F367_OFDM_RCSPYOBS_SPYFAIL 0xF2280080 ++#define F367_OFDM_RCSPYOBS_SPYFAIL1 0xF2280040 ++#define F367_OFDM_RCSPYOBS_ERROR 0xF2280020 ++#define F367_OFDM_RCSPYOBS_STROUT 0xF2280010 ++#define F367_OFDM_RCSPYOBS_RESULTSTATE1 0xF228000F ++ ++/* RCFSPYOBS6 */ ++#define R367_OFDM_RCFSPYOBS6 0xF229 ++#define F367_OFDM_RCSPYOBS_RESULTSTATE0 0xF22900F0 ++#define F367_OFDM_RCSPYOBS_RESULTSTATEM1 0xF229000F ++ ++/* RCFSPYOBS5 */ ++#define R367_OFDM_RCFSPYOBS5 0xF22A ++#define F367_OFDM_RCSPYOBS_BYTEOFPACKET1 0xF22A00FF ++ ++/* RCFSPYOBS4 */ ++#define R367_OFDM_RCFSPYOBS4 0xF22B ++#define F367_OFDM_RCSPYOBS_BYTEVALUE1 0xF22B00FF ++ ++/* RCFSPYOBS3 */ ++#define R367_OFDM_RCFSPYOBS3 0xF22C ++#define F367_OFDM_RCSPYOBS_DATA1 0xF22C00FF ++ ++/* RCFSPYOBS2 */ ++#define R367_OFDM_RCFSPYOBS2 0xF22D ++#define F367_OFDM_RCSPYOBS_DATA0 0xF22D00FF ++ ++/* RCFSPYOBS1 */ ++#define R367_OFDM_RCFSPYOBS1 0xF22E ++#define F367_OFDM_RCSPYOBS_DATAM1 0xF22E00FF ++ ++/* RCFSPYOBS0 */ ++#define R367_OFDM_RCFSPYOBS0 0xF22F ++#define F367_OFDM_RCSPYOBS_DATAM2 0xF22F00FF ++ ++/* TSGENERAL */ ++#define R367_TSGENERAL 0xF230 ++#define F367_TSGENERAL_7 0xF2300080 ++#define F367_TSGENERAL_6 0xF2300040 ++#define F367_TSFIFO_BCLK1ALL 0xF2300020 ++#define F367_TSGENERAL_4 0xF2300010 ++#define F367_MUXSTREAM_OUTMODE 0xF2300008 ++#define F367_TSFIFO_PERMPARAL 0xF2300006 ++#define F367_RST_REEDSOLO 0xF2300001 ++ ++/* RC1SPEED */ ++#define R367_RC1SPEED 0xF231 ++#define F367_TSRCFIFO1_OUTSPEED 0xF23100FF ++ ++/* TSGSTATUS */ ++#define R367_TSGSTATUS 0xF232 ++#define F367_TSGSTATUS_7 0xF2320080 ++#define F367_TSGSTATUS_6 0xF2320040 ++#define F367_RSMEM_FULL 0xF2320020 ++#define F367_RS_MULTCALC 0xF2320010 ++#define F367_RSIN_OVERTIME 0xF2320008 ++#define F367_TSFIFO3_DEMODSEL 0xF2320004 ++#define F367_TSFIFO2_DEMODSEL 0xF2320002 ++#define F367_TSFIFO1_DEMODSEL 0xF2320001 ++ ++ ++/* FECM */ ++#define R367_OFDM_FECM 0xF233 ++#define F367_OFDM_DSS_DVB 0xF2330080 ++#define F367_OFDM_DEMOD_BYPASS 0xF2330040 ++#define F367_OFDM_CMP_SLOWMODE 0xF2330020 ++#define F367_OFDM_DSS_SRCH 0xF2330010 ++#define F367_OFDM_FECM_3 0xF2330008 ++#define F367_OFDM_DIFF_MODEVIT 0xF2330004 ++#define F367_OFDM_SYNCVIT 0xF2330002 ++#define F367_OFDM_I2CSYM 0xF2330001 ++ ++/* VTH12 */ ++#define R367_OFDM_VTH12 0xF234 ++#define F367_OFDM_VTH_12 0xF23400FF ++ ++/* VTH23 */ ++#define R367_OFDM_VTH23 0xF235 ++#define F367_OFDM_VTH_23 0xF23500FF ++ ++/* VTH34 */ ++#define R367_OFDM_VTH34 0xF236 ++#define F367_OFDM_VTH_34 0xF23600FF ++ ++/* VTH56 */ ++#define R367_OFDM_VTH56 0xF237 ++#define F367_OFDM_VTH_56 0xF23700FF ++ ++/* VTH67 */ ++#define R367_OFDM_VTH67 0xF238 ++#define F367_OFDM_VTH_67 0xF23800FF ++ ++/* VTH78 */ ++#define R367_OFDM_VTH78 0xF239 ++#define F367_OFDM_VTH_78 0xF23900FF ++ ++/* VITCURPUN */ ++#define R367_OFDM_VITCURPUN 0xF23A ++#define F367_OFDM_VIT_MAPPING 0xF23A00E0 ++#define F367_OFDM_VIT_CURPUN 0xF23A001F ++ ++/* VERROR */ ++#define R367_OFDM_VERROR 0xF23B ++#define F367_OFDM_REGERR_VIT 0xF23B00FF ++ ++/* PRVIT */ ++#define R367_OFDM_PRVIT 0xF23C ++#define F367_OFDM_PRVIT_7 0xF23C0080 ++#define F367_OFDM_DIS_VTHLOCK 0xF23C0040 ++#define F367_OFDM_E7_8VIT 0xF23C0020 ++#define F367_OFDM_E6_7VIT 0xF23C0010 ++#define F367_OFDM_E5_6VIT 0xF23C0008 ++#define F367_OFDM_E3_4VIT 0xF23C0004 ++#define F367_OFDM_E2_3VIT 0xF23C0002 ++#define F367_OFDM_E1_2VIT 0xF23C0001 ++ ++/* VAVSRVIT */ ++#define R367_OFDM_VAVSRVIT 0xF23D ++#define F367_OFDM_AMVIT 0xF23D0080 ++#define F367_OFDM_FROZENVIT 0xF23D0040 ++#define F367_OFDM_SNVIT 0xF23D0030 ++#define F367_OFDM_TOVVIT 0xF23D000C ++#define F367_OFDM_HYPVIT 0xF23D0003 ++ ++/* VSTATUSVIT */ ++#define R367_OFDM_VSTATUSVIT 0xF23E ++#define F367_OFDM_VITERBI_ON 0xF23E0080 ++#define F367_OFDM_END_LOOPVIT 0xF23E0040 ++#define F367_OFDM_VITERBI_DEPRF 0xF23E0020 ++#define F367_OFDM_PRFVIT 0xF23E0010 ++#define F367_OFDM_LOCKEDVIT 0xF23E0008 ++#define F367_OFDM_VITERBI_DELOCK 0xF23E0004 ++#define F367_OFDM_VIT_DEMODSEL 0xF23E0002 ++#define F367_OFDM_VITERBI_COMPOUT 0xF23E0001 ++ ++/* VTHINUSE */ ++#define R367_OFDM_VTHINUSE 0xF23F ++#define F367_OFDM_VIT_INUSE 0xF23F00FF ++ ++/* KDIV12 */ ++#define R367_OFDM_KDIV12 0xF240 ++#define F367_OFDM_KDIV12_MANUAL 0xF2400080 ++#define F367_OFDM_K_DIVIDER_12 0xF240007F ++ ++/* KDIV23 */ ++#define R367_OFDM_KDIV23 0xF241 ++#define F367_OFDM_KDIV23_MANUAL 0xF2410080 ++#define F367_OFDM_K_DIVIDER_23 0xF241007F ++ ++/* KDIV34 */ ++#define R367_OFDM_KDIV34 0xF242 ++#define F367_OFDM_KDIV34_MANUAL 0xF2420080 ++#define F367_OFDM_K_DIVIDER_34 0xF242007F ++ ++/* KDIV56 */ ++#define R367_OFDM_KDIV56 0xF243 ++#define F367_OFDM_KDIV56_MANUAL 0xF2430080 ++#define F367_OFDM_K_DIVIDER_56 0xF243007F ++ ++/* KDIV67 */ ++#define R367_OFDM_KDIV67 0xF244 ++#define F367_OFDM_KDIV67_MANUAL 0xF2440080 ++#define F367_OFDM_K_DIVIDER_67 0xF244007F ++ ++/* KDIV78 */ ++#define R367_OFDM_KDIV78 0xF245 ++#define F367_OFDM_KDIV78_MANUAL 0xF2450080 ++#define F367_OFDM_K_DIVIDER_78 0xF245007F ++ ++/* SIGPOWER */ ++#define R367_OFDM_SIGPOWER 0xF246 ++#define F367_OFDM_SIGPOWER_MANUAL 0xF2460080 ++#define F367_OFDM_SIG_POWER 0xF246007F ++ ++/* DEMAPVIT */ ++#define R367_OFDM_DEMAPVIT 0xF247 ++#define F367_OFDM_DEMAPVIT_7 0xF2470080 ++#define F367_OFDM_K_DIVIDER_VIT 0xF247007F ++ ++/* VITSCALE */ ++#define R367_OFDM_VITSCALE 0xF248 ++#define F367_OFDM_NVTH_NOSRANGE 0xF2480080 ++#define F367_OFDM_VERROR_MAXMODE 0xF2480040 ++#define F367_OFDM_KDIV_MODE 0xF2480030 ++#define F367_OFDM_NSLOWSN_LOCKED 0xF2480008 ++#define F367_OFDM_DELOCK_PRFLOSS 0xF2480004 ++#define F367_OFDM_DIS_RSFLOCK 0xF2480002 ++#define F367_OFDM_VITSCALE_0 0xF2480001 ++ ++/* FFEC1PRG */ ++#define R367_OFDM_FFEC1PRG 0xF249 ++#define F367_OFDM_FDSS_DVB 0xF2490080 ++#define F367_OFDM_FDSS_SRCH 0xF2490040 ++#define F367_OFDM_FFECPROG_5 0xF2490020 ++#define F367_OFDM_FFECPROG_4 0xF2490010 ++#define F367_OFDM_FFECPROG_3 0xF2490008 ++#define F367_OFDM_FFECPROG_2 0xF2490004 ++#define F367_OFDM_FTS1_DISABLE 0xF2490002 ++#define F367_OFDM_FTS2_DISABLE 0xF2490001 ++ ++/* FVITCURPUN */ ++#define R367_OFDM_FVITCURPUN 0xF24A ++#define F367_OFDM_FVIT_MAPPING 0xF24A00E0 ++#define F367_OFDM_FVIT_CURPUN 0xF24A001F ++ ++/* FVERROR */ ++#define R367_OFDM_FVERROR 0xF24B ++#define F367_OFDM_FREGERR_VIT 0xF24B00FF ++ ++/* FVSTATUSVIT */ ++#define R367_OFDM_FVSTATUSVIT 0xF24C ++#define F367_OFDM_FVITERBI_ON 0xF24C0080 ++#define F367_OFDM_F1END_LOOPVIT 0xF24C0040 ++#define F367_OFDM_FVITERBI_DEPRF 0xF24C0020 ++#define F367_OFDM_FPRFVIT 0xF24C0010 ++#define F367_OFDM_FLOCKEDVIT 0xF24C0008 ++#define F367_OFDM_FVITERBI_DELOCK 0xF24C0004 ++#define F367_OFDM_FVIT_DEMODSEL 0xF24C0002 ++#define F367_OFDM_FVITERBI_COMPOUT 0xF24C0001 ++ ++/* DEBUG_LT1 */ ++#define R367_OFDM_DEBUG_LT1 0xF24D ++#define F367_OFDM_DBG_LT1 0xF24D00FF ++ ++/* DEBUG_LT2 */ ++#define R367_OFDM_DEBUG_LT2 0xF24E ++#define F367_OFDM_DBG_LT2 0xF24E00FF ++ ++/* DEBUG_LT3 */ ++#define R367_OFDM_DEBUG_LT3 0xF24F ++#define F367_OFDM_DBG_LT3 0xF24F00FF ++ ++ /* TSTSFMET */ ++#define R367_OFDM_TSTSFMET 0xF250 ++#define F367_OFDM_TSTSFEC_METRIQUES 0xF25000FF ++ ++ /* SELOUT */ ++#define R367_OFDM_SELOUT 0xF252 ++#define F367_OFDM_EN_SYNC 0xF2520080 ++#define F367_OFDM_EN_TBUSDEMAP 0xF2520040 ++#define F367_OFDM_SELOUT_5 0xF2520020 ++#define F367_OFDM_SELOUT_4 0xF2520010 ++#define F367_OFDM_TSTSYNCHRO_MODE 0xF2520002 ++ ++ /* TSYNC */ ++#define R367_OFDM_TSYNC 0xF253 ++#define F367_OFDM_CURPUN_INCMODE 0xF2530080 ++#define F367_OFDM_CERR_TSTMODE 0xF2530040 ++#define F367_OFDM_SHIFTSOF_MODE 0xF2530030 ++#define F367_OFDM_SLOWPHA_MODE 0xF2530008 ++#define F367_OFDM_PXX_BYPALL 0xF2530004 ++#define F367_OFDM_FROTA45_FIRST 0xF2530002 ++#define F367_OFDM_TST_BCHERROR 0xF2530001 ++ ++ /* TSTERR */ ++#define R367_OFDM_TSTERR 0xF254 ++#define F367_OFDM_TST_LONGPKT 0xF2540080 ++#define F367_OFDM_TST_ISSYION 0xF2540040 ++#define F367_OFDM_TST_NPDON 0xF2540020 ++#define F367_OFDM_TSTERR_4 0xF2540010 ++#define F367_OFDM_TRACEBACK_MODE 0xF2540008 ++#define F367_OFDM_TST_RSPARITY 0xF2540004 ++#define F367_OFDM_METRIQUE_MODE 0xF2540003 ++ ++ /* TSFSYNC */ ++#define R367_OFDM_TSFSYNC 0xF255 ++#define F367_OFDM_EN_SFECSYNC 0xF2550080 ++#define F367_OFDM_EN_SFECDEMAP 0xF2550040 ++#define F367_OFDM_SFCERR_TSTMODE 0xF2550020 ++#define F367_OFDM_SFECPXX_BYPALL 0xF2550010 ++#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F ++ ++ /* TSTSFERR */ ++#define R367_OFDM_TSTSFERR 0xF256 ++#define F367_OFDM_TSTSTERR_7 0xF2560080 ++#define F367_OFDM_TSTSTERR_6 0xF2560040 ++#define F367_OFDM_TSTSTERR_5 0xF2560020 ++#define F367_OFDM_TSTSTERR_4 0xF2560010 ++#define F367_OFDM_SFECTRACEBACK_MODE 0xF2560008 ++#define F367_OFDM_SFEC_NCONVPROG 0xF2560004 ++#define F367_OFDM_SFECMETRIQUE_MODE 0xF2560003 ++ ++ /* TSTTSSF1 */ ++#define R367_OFDM_TSTTSSF1 0xF258 ++#define F367_OFDM_TSTERSSF 0xF2580080 ++#define F367_OFDM_TSTTSSFEN 0xF2580040 ++#define F367_OFDM_SFEC_OUTMODE 0xF2580030 ++#define F367_OFDM_XLSF_NOFTHRESHOLD 0xF2580008 ++#define F367_OFDM_TSTTSSF_STACKSEL 0xF2580007 ++ ++ /* TSTTSSF2 */ ++#define R367_OFDM_TSTTSSF2 0xF259 ++#define F367_OFDM_DILSF_DBBHEADER 0xF2590080 ++#define F367_OFDM_TSTTSSF_DISBUG 0xF2590040 ++#define F367_OFDM_TSTTSSF_NOBADSTART 0xF2590020 ++#define F367_OFDM_TSTTSSF_SELECT 0xF259001F ++ ++ /* TSTTSSF3 */ ++#define R367_OFDM_TSTTSSF3 0xF25A ++#define F367_OFDM_TSTTSSF3_7 0xF25A0080 ++#define F367_OFDM_TSTTSSF3_6 0xF25A0040 ++#define F367_OFDM_TSTTSSF3_5 0xF25A0020 ++#define F367_OFDM_TSTTSSF3_4 0xF25A0010 ++#define F367_OFDM_TSTTSSF3_3 0xF25A0008 ++#define F367_OFDM_TSTTSSF3_2 0xF25A0004 ++#define F367_OFDM_TSTTSSF3_1 0xF25A0002 ++#define F367_OFDM_DISSF_CLKENABLE 0xF25A0001 ++ ++ /* TSTTS1 */ ++#define R367_OFDM_TSTTS1 0xF25C ++#define F367_OFDM_TSTERS 0xF25C0080 ++#define F367_OFDM_TSFIFO_DSSSYNCB 0xF25C0040 ++#define F367_OFDM_TSTTS_FSPYBEFRS 0xF25C0020 ++#define F367_OFDM_NFORCE_SYNCBYTE 0xF25C0010 ++#define F367_OFDM_XL_NOFTHRESHOLD 0xF25C0008 ++#define F367_OFDM_TSTTS_FRFORCEPKT 0xF25C0004 ++#define F367_OFDM_DESCR_NOTAUTO 0xF25C0002 ++#define F367_OFDM_TSTTSEN 0xF25C0001 ++ ++ /* TSTTS2 */ ++#define R367_OFDM_TSTTS2 0xF25D ++#define F367_OFDM_DIL_DBBHEADER 0xF25D0080 ++#define F367_OFDM_TSTTS_NOBADXXX 0xF25D0040 ++#define F367_OFDM_TSFIFO_DELSPEEDUP 0xF25D0020 ++#define F367_OFDM_TSTTS_SELECT 0xF25D001F ++ ++ /* TSTTS3 */ ++#define R367_OFDM_TSTTS3 0xF25E ++#define F367_OFDM_TSTTS_NOPKTGAIN 0xF25E0080 ++#define F367_OFDM_TSTTS_NOPKTENE 0xF25E0040 ++#define F367_OFDM_TSTTS_ISOLATION 0xF25E0020 ++#define F367_OFDM_TSTTS_DISBUG 0xF25E0010 ++#define F367_OFDM_TSTTS_NOBADSTART 0xF25E0008 ++#define F367_OFDM_TSTTS_STACKSEL 0xF25E0007 ++ ++ /* TSTTS4 */ ++#define R367_OFDM_TSTTS4 0xF25F ++#define F367_OFDM_TSTTS4_7 0xF25F0080 ++#define F367_OFDM_TSTTS4_6 0xF25F0040 ++#define F367_OFDM_TSTTS4_5 0xF25F0020 ++#define F367_OFDM_TSTTS_DISDSTATE 0xF25F0010 ++#define F367_OFDM_TSTTS_FASTNOSYNC 0xF25F0008 ++#define F367_OFDM_EXT_FECSPYIN 0xF25F0004 ++#define F367_OFDM_TSTTS_NODPZERO 0xF25F0002 ++#define F367_OFDM_TSTTS_NODIV3 0xF25F0001 ++ ++ /* TSTTSRC */ ++#define R367_OFDM_TSTTSRC 0xF26C ++#define F367_OFDM_TSTTSRC_7 0xF26C0080 ++#define F367_OFDM_TSRCFIFO_DSSSYNCB 0xF26C0040 ++#define F367_OFDM_TSRCFIFO_DPUNACTIVE 0xF26C0020 ++#define F367_OFDM_TSRCFIFO_DELSPEEDUP 0xF26C0010 ++#define F367_OFDM_TSTTSRC_NODIV3 0xF26C0008 ++#define F367_OFDM_TSTTSRC_FRFORCEPKT 0xF26C0004 ++#define F367_OFDM_SAT25_SDDORIGINE 0xF26C0002 ++#define F367_OFDM_TSTTSRC_INACTIVE 0xF26C0001 ++ ++ /* TSTTSRS */ ++#define R367_OFDM_TSTTSRS 0xF26D ++#define F367_OFDM_TSTTSRS_7 0xF26D0080 ++#define F367_OFDM_TSTTSRS_6 0xF26D0040 ++#define F367_OFDM_TSTTSRS_5 0xF26D0020 ++#define F367_OFDM_TSTTSRS_4 0xF26D0010 ++#define F367_OFDM_TSTTSRS_3 0xF26D0008 ++#define F367_OFDM_TSTTSRS_2 0xF26D0004 ++#define F367_OFDM_TSTRS_DISRS2 0xF26D0002 ++#define F367_OFDM_TSTRS_DISRS1 0xF26D0001 ++ ++/* TSSTATEM */ ++#define R367_OFDM_TSSTATEM 0xF270 ++#define F367_OFDM_TSDIL_ON 0xF2700080 ++#define F367_OFDM_TSSKIPRS_ON 0xF2700040 ++#define F367_OFDM_TSRS_ON 0xF2700020 ++#define F367_OFDM_TSDESCRAMB_ON 0xF2700010 ++#define F367_OFDM_TSFRAME_MODE 0xF2700008 ++#define F367_OFDM_TS_DISABLE 0xF2700004 ++#define F367_OFDM_TSACM_MODE 0xF2700002 ++#define F367_OFDM_TSOUT_NOSYNC 0xF2700001 ++ ++/* TSSTATEL */ ++#define R367_OFDM_TSSTATEL 0xF271 ++#define F367_OFDM_TSNOSYNCBYTE 0xF2710080 ++#define F367_OFDM_TSPARITY_ON 0xF2710040 ++#define F367_OFDM_TSSYNCOUTRS_ON 0xF2710020 ++#define F367_OFDM_TSDVBS2_MODE 0xF2710010 ++#define F367_OFDM_TSISSYI_ON 0xF2710008 ++#define F367_OFDM_TSNPD_ON 0xF2710004 ++#define F367_OFDM_TSCRC8_ON 0xF2710002 ++#define F367_OFDM_TSDSS_PACKET 0xF2710001 ++ ++/* TSCFGH */ ++#define R367_OFDM_TSCFGH 0xF272 ++#define F367_OFDM_TSFIFO_DVBCI 0xF2720080 ++#define F367_OFDM_TSFIFO_SERIAL 0xF2720040 ++#define F367_OFDM_TSFIFO_TEIUPDATE 0xF2720020 ++#define F367_OFDM_TSFIFO_DUTY50 0xF2720010 ++#define F367_OFDM_TSFIFO_HSGNLOUT 0xF2720008 ++#define F367_OFDM_TSFIFO_ERRMODE 0xF2720006 ++#define F367_OFDM_RST_HWARE 0xF2720001 ++ ++/* TSCFGM */ ++#define R367_OFDM_TSCFGM 0xF273 ++#define F367_OFDM_TSFIFO_MANSPEED 0xF27300C0 ++#define F367_OFDM_TSFIFO_PERMDATA 0xF2730020 ++#define F367_OFDM_TSFIFO_NONEWSGNL 0xF2730010 ++#define F367_OFDM_TSFIFO_BITSPEED 0xF2730008 ++#define F367_OFDM_NPD_SPECDVBS2 0xF2730004 ++#define F367_OFDM_TSFIFO_STOPCKDIS 0xF2730002 ++#define F367_OFDM_TSFIFO_INVDATA 0xF2730001 ++ ++/* TSCFGL */ ++#define R367_OFDM_TSCFGL 0xF274 ++#define F367_OFDM_TSFIFO_BCLKDEL1CK 0xF27400C0 ++#define F367_OFDM_BCHERROR_MODE 0xF2740030 ++#define F367_OFDM_TSFIFO_NSGNL2DATA 0xF2740008 ++#define F367_OFDM_TSFIFO_EMBINDVB 0xF2740004 ++#define F367_OFDM_TSFIFO_DPUNACT 0xF2740002 ++#define F367_OFDM_TSFIFO_NPDOFF 0xF2740001 ++ ++/* TSSYNC */ ++#define R367_OFDM_TSSYNC 0xF275 ++#define F367_OFDM_TSFIFO_PERMUTE 0xF2750080 ++#define F367_OFDM_TSFIFO_FISCR3B 0xF2750060 ++#define F367_OFDM_TSFIFO_SYNCMODE 0xF2750018 ++#define F367_OFDM_TSFIFO_SYNCSEL 0xF2750007 ++ ++/* TSINSDELH */ ++#define R367_OFDM_TSINSDELH 0xF276 ++#define F367_OFDM_TSDEL_SYNCBYTE 0xF2760080 ++#define F367_OFDM_TSDEL_XXHEADER 0xF2760040 ++#define F367_OFDM_TSDEL_BBHEADER 0xF2760020 ++#define F367_OFDM_TSDEL_DATAFIELD 0xF2760010 ++#define F367_OFDM_TSINSDEL_ISCR 0xF2760008 ++#define F367_OFDM_TSINSDEL_NPD 0xF2760004 ++#define F367_OFDM_TSINSDEL_RSPARITY 0xF2760002 ++#define F367_OFDM_TSINSDEL_CRC8 0xF2760001 ++ ++/* TSINSDELM */ ++#define R367_OFDM_TSINSDELM 0xF277 ++#define F367_OFDM_TSINS_BBPADDING 0xF2770080 ++#define F367_OFDM_TSINS_BCHFEC 0xF2770040 ++#define F367_OFDM_TSINS_LDPCFEC 0xF2770020 ++#define F367_OFDM_TSINS_EMODCOD 0xF2770010 ++#define F367_OFDM_TSINS_TOKEN 0xF2770008 ++#define F367_OFDM_TSINS_XXXERR 0xF2770004 ++#define F367_OFDM_TSINS_MATYPE 0xF2770002 ++#define F367_OFDM_TSINS_UPL 0xF2770001 ++ ++/* TSINSDELL */ ++#define R367_OFDM_TSINSDELL 0xF278 ++#define F367_OFDM_TSINS_DFL 0xF2780080 ++#define F367_OFDM_TSINS_SYNCD 0xF2780040 ++#define F367_OFDM_TSINS_BLOCLEN 0xF2780020 ++#define F367_OFDM_TSINS_SIGPCOUNT 0xF2780010 ++#define F367_OFDM_TSINS_FIFO 0xF2780008 ++#define F367_OFDM_TSINS_REALPACK 0xF2780004 ++#define F367_OFDM_TSINS_TSCONFIG 0xF2780002 ++#define F367_OFDM_TSINS_LATENCY 0xF2780001 ++ ++/* TSDIVN */ ++#define R367_OFDM_TSDIVN 0xF279 ++#define F367_OFDM_TSFIFO_LOWSPEED 0xF2790080 ++#define F367_OFDM_BYTE_OVERSAMPLING 0xF2790070 ++#define F367_OFDM_TSMANUAL_PACKETNBR 0xF279000F ++ ++/* TSDIVPM */ ++#define R367_OFDM_TSDIVPM 0xF27A ++#define F367_OFDM_TSMANUAL_P_HI 0xF27A00FF ++ ++/* TSDIVPL */ ++#define R367_OFDM_TSDIVPL 0xF27B ++#define F367_OFDM_TSMANUAL_P_LO 0xF27B00FF ++ ++/* TSDIVQM */ ++#define R367_OFDM_TSDIVQM 0xF27C ++#define F367_OFDM_TSMANUAL_Q_HI 0xF27C00FF ++ ++/* TSDIVQL */ ++#define R367_OFDM_TSDIVQL 0xF27D ++#define F367_OFDM_TSMANUAL_Q_LO 0xF27D00FF ++ ++/* TSDILSTKM */ ++#define R367_OFDM_TSDILSTKM 0xF27E ++#define F367_OFDM_TSFIFO_DILSTK_HI 0xF27E00FF ++ ++/* TSDILSTKL */ ++#define R367_OFDM_TSDILSTKL 0xF27F ++#define F367_OFDM_TSFIFO_DILSTK_LO 0xF27F00FF ++ ++/* TSSPEED */ ++#define R367_OFDM_TSSPEED 0xF280 ++#define F367_OFDM_TSFIFO_OUTSPEED 0xF28000FF ++ ++/* TSSTATUS */ ++#define R367_OFDM_TSSTATUS 0xF281 ++#define F367_OFDM_TSFIFO_LINEOK 0xF2810080 ++#define F367_OFDM_TSFIFO_ERROR 0xF2810040 ++#define F367_OFDM_TSFIFO_DATA7 0xF2810020 ++#define F367_OFDM_TSFIFO_NOSYNC 0xF2810010 ++#define F367_OFDM_ISCR_INITIALIZED 0xF2810008 ++#define F367_OFDM_ISCR_UPDATED 0xF2810004 ++#define F367_OFDM_SOFFIFO_UNREGUL 0xF2810002 ++#define F367_OFDM_DIL_READY 0xF2810001 ++ ++/* TSSTATUS2 */ ++#define R367_OFDM_TSSTATUS2 0xF282 ++#define F367_OFDM_TSFIFO_DEMODSEL 0xF2820080 ++#define F367_OFDM_TSFIFOSPEED_STORE 0xF2820040 ++#define F367_OFDM_DILXX_RESET 0xF2820020 ++#define F367_OFDM_TSSERIAL_IMPOSSIBLE 0xF2820010 ++#define F367_OFDM_TSFIFO_UNDERSPEED 0xF2820008 ++#define F367_OFDM_BITSPEED_EVENT 0xF2820004 ++#define F367_OFDM_UL_SCRAMBDETECT 0xF2820002 ++#define F367_OFDM_ULDTV67_FALSELOCK 0xF2820001 ++ ++/* TSBITRATEM */ ++#define R367_OFDM_TSBITRATEM 0xF283 ++#define F367_OFDM_TSFIFO_BITRATE_HI 0xF28300FF ++ ++/* TSBITRATEL */ ++#define R367_OFDM_TSBITRATEL 0xF284 ++#define F367_OFDM_TSFIFO_BITRATE_LO 0xF28400FF ++ ++/* TSPACKLENM */ ++#define R367_OFDM_TSPACKLENM 0xF285 ++#define F367_OFDM_TSFIFO_PACKCPT 0xF28500E0 ++#define F367_OFDM_DIL_RPLEN_HI 0xF285001F ++ ++/* TSPACKLENL */ ++#define R367_OFDM_TSPACKLENL 0xF286 ++#define F367_OFDM_DIL_RPLEN_LO 0xF28600FF ++ ++/* TSBLOCLENM */ ++#define R367_OFDM_TSBLOCLENM 0xF287 ++#define F367_OFDM_TSFIFO_PFLEN_HI 0xF28700FF ++ ++/* TSBLOCLENL */ ++#define R367_OFDM_TSBLOCLENL 0xF288 ++#define F367_OFDM_TSFIFO_PFLEN_LO 0xF28800FF ++ ++/* TSDLYH */ ++#define R367_OFDM_TSDLYH 0xF289 ++#define F367_OFDM_SOFFIFO_TSTIMEVALID 0xF2890080 ++#define F367_OFDM_SOFFIFO_SPEEDUP 0xF2890040 ++#define F367_OFDM_SOFFIFO_STOP 0xF2890020 ++#define F367_OFDM_SOFFIFO_REGULATED 0xF2890010 ++#define F367_OFDM_SOFFIFO_REALSBOFF_HI 0xF289000F ++ ++/* TSDLYM */ ++#define R367_OFDM_TSDLYM 0xF28A ++#define F367_OFDM_SOFFIFO_REALSBOFF_MED 0xF28A00FF ++ ++/* TSDLYL */ ++#define R367_OFDM_TSDLYL 0xF28B ++#define F367_OFDM_SOFFIFO_REALSBOFF_LO 0xF28B00FF ++ ++/* TSNPDAV */ ++#define R367_OFDM_TSNPDAV 0xF28C ++#define F367_OFDM_TSNPD_AVERAGE 0xF28C00FF ++ ++/* TSBUFSTATH */ ++#define R367_OFDM_TSBUFSTATH 0xF28D ++#define F367_OFDM_TSISCR_3BYTES 0xF28D0080 ++#define F367_OFDM_TSISCR_NEWDATA 0xF28D0040 ++#define F367_OFDM_TSISCR_BUFSTAT_HI 0xF28D003F ++ ++/* TSBUFSTATM */ ++#define R367_OFDM_TSBUFSTATM 0xF28E ++#define F367_OFDM_TSISCR_BUFSTAT_MED 0xF28E00FF ++ ++/* TSBUFSTATL */ ++#define R367_OFDM_TSBUFSTATL 0xF28F ++#define F367_OFDM_TSISCR_BUFSTAT_LO 0xF28F00FF ++ ++/* TSDEBUGM */ ++#define R367_OFDM_TSDEBUGM 0xF290 ++#define F367_OFDM_TSFIFO_ILLPACKET 0xF2900080 ++#define F367_OFDM_DIL_NOSYNC 0xF2900040 ++#define F367_OFDM_DIL_ISCR 0xF2900020 ++#define F367_OFDM_DILOUT_BSYNCB 0xF2900010 ++#define F367_OFDM_TSFIFO_EMPTYPKT 0xF2900008 ++#define F367_OFDM_TSFIFO_EMPTYRD 0xF2900004 ++#define F367_OFDM_SOFFIFO_STOPM 0xF2900002 ++#define F367_OFDM_SOFFIFO_SPEEDUPM 0xF2900001 ++ ++/* TSDEBUGL */ ++#define R367_OFDM_TSDEBUGL 0xF291 ++#define F367_OFDM_TSFIFO_PACKLENFAIL 0xF2910080 ++#define F367_OFDM_TSFIFO_SYNCBFAIL 0xF2910040 ++#define F367_OFDM_TSFIFO_VITLIBRE 0xF2910020 ++#define F367_OFDM_TSFIFO_BOOSTSPEEDM 0xF2910010 ++#define F367_OFDM_TSFIFO_UNDERSPEEDM 0xF2910008 ++#define F367_OFDM_TSFIFO_ERROR_EVNT 0xF2910004 ++#define F367_OFDM_TSFIFO_FULL 0xF2910002 ++#define F367_OFDM_TSFIFO_OVERFLOWM 0xF2910001 ++ ++/* TSDLYSETH */ ++#define R367_OFDM_TSDLYSETH 0xF292 ++#define F367_OFDM_SOFFIFO_OFFSET 0xF29200E0 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_HI 0xF292001F ++ ++/* TSDLYSETM */ ++#define R367_OFDM_TSDLYSETM 0xF293 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_MED 0xF29300FF ++ ++/* TSDLYSETL */ ++#define R367_OFDM_TSDLYSETL 0xF294 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_LO 0xF29400FF ++ ++/* TSOBSCFG */ ++#define R367_OFDM_TSOBSCFG 0xF295 ++#define F367_OFDM_TSFIFO_OBSCFG 0xF29500FF ++ ++/* TSOBSM */ ++#define R367_OFDM_TSOBSM 0xF296 ++#define F367_OFDM_TSFIFO_OBSDATA_HI 0xF29600FF ++ ++/* TSOBSL */ ++#define R367_OFDM_TSOBSL 0xF297 ++#define F367_OFDM_TSFIFO_OBSDATA_LO 0xF29700FF ++ ++/* ERRCTRL1 */ ++#define R367_OFDM_ERRCTRL1 0xF298 ++#define F367_OFDM_ERR_SRC1 0xF29800F0 ++#define F367_OFDM_ERRCTRL1_3 0xF2980008 ++#define F367_OFDM_NUM_EVT1 0xF2980007 ++ ++/* ERRCNT1H */ ++#define R367_OFDM_ERRCNT1H 0xF299 ++#define F367_OFDM_ERRCNT1_OLDVALUE 0xF2990080 ++#define F367_OFDM_ERR_CNT1 0xF299007F ++ ++/* ERRCNT1M */ ++#define R367_OFDM_ERRCNT1M 0xF29A ++#define F367_OFDM_ERR_CNT1_HI 0xF29A00FF ++ ++/* ERRCNT1L */ ++#define R367_OFDM_ERRCNT1L 0xF29B ++#define F367_OFDM_ERR_CNT1_LO 0xF29B00FF ++ ++/* ERRCTRL2 */ ++#define R367_OFDM_ERRCTRL2 0xF29C ++#define F367_OFDM_ERR_SRC2 0xF29C00F0 ++#define F367_OFDM_ERRCTRL2_3 0xF29C0008 ++#define F367_OFDM_NUM_EVT2 0xF29C0007 ++ ++/* ERRCNT2H */ ++#define R367_OFDM_ERRCNT2H 0xF29D ++#define F367_OFDM_ERRCNT2_OLDVALUE 0xF29D0080 ++#define F367_OFDM_ERR_CNT2_HI 0xF29D007F ++ ++/* ERRCNT2M */ ++#define R367_OFDM_ERRCNT2M 0xF29E ++#define F367_OFDM_ERR_CNT2_MED 0xF29E00FF ++ ++/* ERRCNT2L */ ++#define R367_OFDM_ERRCNT2L 0xF29F ++#define F367_OFDM_ERR_CNT2_LO 0xF29F00FF ++ ++/* FECSPY */ ++#define R367_OFDM_FECSPY 0xF2A0 ++#define F367_OFDM_SPY_ENABLE 0xF2A00080 ++#define F367_OFDM_NO_SYNCBYTE 0xF2A00040 ++#define F367_OFDM_SERIAL_MODE 0xF2A00020 ++#define F367_OFDM_UNUSUAL_PACKET 0xF2A00010 ++#define F367_OFDM_BERMETER_DATAMODE 0xF2A0000C ++#define F367_OFDM_BERMETER_LMODE 0xF2A00002 ++#define F367_OFDM_BERMETER_RESET 0xF2A00001 ++ ++/* FSPYCFG */ ++#define R367_OFDM_FSPYCFG 0xF2A1 ++#define F367_OFDM_FECSPY_INPUT 0xF2A100C0 ++#define F367_OFDM_RST_ON_ERROR 0xF2A10020 ++#define F367_OFDM_ONE_SHOT 0xF2A10010 ++#define F367_OFDM_I2C_MOD 0xF2A1000C ++#define F367_OFDM_SPY_HYSTERESIS 0xF2A10003 ++ ++/* FSPYDATA */ ++#define R367_OFDM_FSPYDATA 0xF2A2 ++#define F367_OFDM_SPY_STUFFING 0xF2A20080 ++#define F367_OFDM_NOERROR_PKTJITTER 0xF2A20040 ++#define F367_OFDM_SPY_CNULLPKT 0xF2A20020 ++#define F367_OFDM_SPY_OUTDATA_MODE 0xF2A2001F ++ ++/* FSPYOUT */ ++#define R367_OFDM_FSPYOUT 0xF2A3 ++#define F367_OFDM_FSPY_DIRECT 0xF2A30080 ++#define F367_OFDM_FSPYOUT_6 0xF2A30040 ++#define F367_OFDM_SPY_OUTDATA_BUS 0xF2A30038 ++#define F367_OFDM_STUFF_MODE 0xF2A30007 ++ ++/* FSTATUS */ ++#define R367_OFDM_FSTATUS 0xF2A4 ++#define F367_OFDM_SPY_ENDSIM 0xF2A40080 ++#define F367_OFDM_VALID_SIM 0xF2A40040 ++#define F367_OFDM_FOUND_SIGNAL 0xF2A40020 ++#define F367_OFDM_DSS_SYNCBYTE 0xF2A40010 ++#define F367_OFDM_RESULT_STATE 0xF2A4000F ++ ++/* FGOODPACK */ ++#define R367_OFDM_FGOODPACK 0xF2A5 ++#define F367_OFDM_FGOOD_PACKET 0xF2A500FF ++ ++/* FPACKCNT */ ++#define R367_OFDM_FPACKCNT 0xF2A6 ++#define F367_OFDM_FPACKET_COUNTER 0xF2A600FF ++ ++/* FSPYMISC */ ++#define R367_OFDM_FSPYMISC 0xF2A7 ++#define F367_OFDM_FLABEL_COUNTER 0xF2A700FF ++ ++/* FBERCPT4 */ ++#define R367_OFDM_FBERCPT4 0xF2A8 ++#define F367_OFDM_FBERMETER_CPT5 0xF2A800FF ++ ++/* FBERCPT3 */ ++#define R367_OFDM_FBERCPT3 0xF2A9 ++#define F367_OFDM_FBERMETER_CPT4 0xF2A900FF ++ ++/* FBERCPT2 */ ++#define R367_OFDM_FBERCPT2 0xF2AA ++#define F367_OFDM_FBERMETER_CPT3 0xF2AA00FF ++ ++/* FBERCPT1 */ ++#define R367_OFDM_FBERCPT1 0xF2AB ++#define F367_OFDM_FBERMETER_CPT2 0xF2AB00FF ++ ++/* FBERCPT0 */ ++#define R367_OFDM_FBERCPT0 0xF2AC ++#define F367_OFDM_FBERMETER_CPT1 0xF2AC00FF ++ ++/* FBERERR2 */ ++#define R367_OFDM_FBERERR2 0xF2AD ++#define F367_OFDM_FBERMETER_ERR_HI 0xF2AD00FF ++ ++/* FBERERR1 */ ++#define R367_OFDM_FBERERR1 0xF2AE ++#define F367_OFDM_FBERMETER_ERR_MED 0xF2AE00FF ++ ++/* FBERERR0 */ ++#define R367_OFDM_FBERERR0 0xF2AF ++#define F367_OFDM_FBERMETER_ERR_LO 0xF2AF00FF ++ ++/* FSTATESM */ ++#define R367_OFDM_FSTATESM 0xF2B0 ++#define F367_OFDM_RSTATE_F 0xF2B00080 ++#define F367_OFDM_RSTATE_E 0xF2B00040 ++#define F367_OFDM_RSTATE_D 0xF2B00020 ++#define F367_OFDM_RSTATE_C 0xF2B00010 ++#define F367_OFDM_RSTATE_B 0xF2B00008 ++#define F367_OFDM_RSTATE_A 0xF2B00004 ++#define F367_OFDM_RSTATE_9 0xF2B00002 ++#define F367_OFDM_RSTATE_8 0xF2B00001 ++ ++/* FSTATESL */ ++#define R367_OFDM_FSTATESL 0xF2B1 ++#define F367_OFDM_RSTATE_7 0xF2B10080 ++#define F367_OFDM_RSTATE_6 0xF2B10040 ++#define F367_OFDM_RSTATE_5 0xF2B10020 ++#define F367_OFDM_RSTATE_4 0xF2B10010 ++#define F367_OFDM_RSTATE_3 0xF2B10008 ++#define F367_OFDM_RSTATE_2 0xF2B10004 ++#define F367_OFDM_RSTATE_1 0xF2B10002 ++#define F367_OFDM_RSTATE_0 0xF2B10001 ++ ++/* FSPYBER */ ++#define R367_OFDM_FSPYBER 0xF2B2 ++#define F367_OFDM_FSPYBER_7 0xF2B20080 ++#define F367_OFDM_FSPYOBS_XORREAD 0xF2B20040 ++#define F367_OFDM_FSPYBER_OBSMODE 0xF2B20020 ++#define F367_OFDM_FSPYBER_SYNCBYTE 0xF2B20010 ++#define F367_OFDM_FSPYBER_UNSYNC 0xF2B20008 ++#define F367_OFDM_FSPYBER_CTIME 0xF2B20007 ++ ++/* FSPYDISTM */ ++#define R367_OFDM_FSPYDISTM 0xF2B3 ++#define F367_OFDM_PKTTIME_DISTANCE_HI 0xF2B300FF ++ ++/* FSPYDISTL */ ++#define R367_OFDM_FSPYDISTL 0xF2B4 ++#define F367_OFDM_PKTTIME_DISTANCE_LO 0xF2B400FF ++ ++/* FSPYOBS7 */ ++#define R367_OFDM_FSPYOBS7 0xF2B8 ++#define F367_OFDM_FSPYOBS_SPYFAIL 0xF2B80080 ++#define F367_OFDM_FSPYOBS_SPYFAIL1 0xF2B80040 ++#define F367_OFDM_FSPYOBS_ERROR 0xF2B80020 ++#define F367_OFDM_FSPYOBS_STROUT 0xF2B80010 ++#define F367_OFDM_FSPYOBS_RESULTSTATE1 0xF2B8000F ++ ++/* FSPYOBS6 */ ++#define R367_OFDM_FSPYOBS6 0xF2B9 ++#define F367_OFDM_FSPYOBS_RESULTSTATE0 0xF2B900F0 ++#define F367_OFDM_FSPYOBS_RESULTSTATEM1 0xF2B9000F ++ ++/* FSPYOBS5 */ ++#define R367_OFDM_FSPYOBS5 0xF2BA ++#define F367_OFDM_FSPYOBS_BYTEOFPACKET1 0xF2BA00FF ++ ++/* FSPYOBS4 */ ++#define R367_OFDM_FSPYOBS4 0xF2BB ++#define F367_OFDM_FSPYOBS_BYTEVALUE1 0xF2BB00FF ++ ++/* FSPYOBS3 */ ++#define R367_OFDM_FSPYOBS3 0xF2BC ++#define F367_OFDM_FSPYOBS_DATA1 0xF2BC00FF ++ ++/* FSPYOBS2 */ ++#define R367_OFDM_FSPYOBS2 0xF2BD ++#define F367_OFDM_FSPYOBS_DATA0 0xF2BD00FF ++ ++/* FSPYOBS1 */ ++#define R367_OFDM_FSPYOBS1 0xF2BE ++#define F367_OFDM_FSPYOBS_DATAM1 0xF2BE00FF ++ ++/* FSPYOBS0 */ ++#define R367_OFDM_FSPYOBS0 0xF2BF ++#define F367_OFDM_FSPYOBS_DATAM2 0xF2BF00FF ++ ++/* SFDEMAP */ ++#define R367_OFDM_SFDEMAP 0xF2C0 ++#define F367_OFDM_SFDEMAP_7 0xF2C00080 ++#define F367_OFDM_SFEC_K_DIVIDER_VIT 0xF2C0007F ++ ++/* SFERROR */ ++#define R367_OFDM_SFERROR 0xF2C1 ++#define F367_OFDM_SFEC_REGERR_VIT 0xF2C100FF ++ ++/* SFAVSR */ ++#define R367_OFDM_SFAVSR 0xF2C2 ++#define F367_OFDM_SFEC_SUMERRORS 0xF2C20080 ++#define F367_OFDM_SERROR_MAXMODE 0xF2C20040 ++#define F367_OFDM_SN_SFEC 0xF2C20030 ++#define F367_OFDM_KDIV_MODE_SFEC 0xF2C2000C ++#define F367_OFDM_SFAVSR_1 0xF2C20002 ++#define F367_OFDM_SFAVSR_0 0xF2C20001 ++ ++/* SFECSTATUS */ ++#define R367_OFDM_SFECSTATUS 0xF2C3 ++#define F367_OFDM_SFEC_ON 0xF2C30080 ++#define F367_OFDM_SFSTATUS_6 0xF2C30040 ++#define F367_OFDM_SFSTATUS_5 0xF2C30020 ++#define F367_OFDM_SFSTATUS_4 0xF2C30010 ++#define F367_OFDM_LOCKEDSFEC 0xF2C30008 ++#define F367_OFDM_SFEC_DELOCK 0xF2C30004 ++#define F367_OFDM_SFEC_DEMODSEL1 0xF2C30002 ++#define F367_OFDM_SFEC_OVFON 0xF2C30001 ++ ++/* SFKDIV12 */ ++#define R367_OFDM_SFKDIV12 0xF2C4 ++#define F367_OFDM_SFECKDIV12_MAN 0xF2C40080 ++#define F367_OFDM_SFEC_K_DIVIDER_12 0xF2C4007F ++ ++/* SFKDIV23 */ ++#define R367_OFDM_SFKDIV23 0xF2C5 ++#define F367_OFDM_SFECKDIV23_MAN 0xF2C50080 ++#define F367_OFDM_SFEC_K_DIVIDER_23 0xF2C5007F ++ ++/* SFKDIV34 */ ++#define R367_OFDM_SFKDIV34 0xF2C6 ++#define F367_OFDM_SFECKDIV34_MAN 0xF2C60080 ++#define F367_OFDM_SFEC_K_DIVIDER_34 0xF2C6007F ++ ++/* SFKDIV56 */ ++#define R367_OFDM_SFKDIV56 0xF2C7 ++#define F367_OFDM_SFECKDIV56_MAN 0xF2C70080 ++#define F367_OFDM_SFEC_K_DIVIDER_56 0xF2C7007F ++ ++/* SFKDIV67 */ ++#define R367_OFDM_SFKDIV67 0xF2C8 ++#define F367_OFDM_SFECKDIV67_MAN 0xF2C80080 ++#define F367_OFDM_SFEC_K_DIVIDER_67 0xF2C8007F ++ ++/* SFKDIV78 */ ++#define R367_OFDM_SFKDIV78 0xF2C9 ++#define F367_OFDM_SFECKDIV78_MAN 0xF2C90080 ++#define F367_OFDM_SFEC_K_DIVIDER_78 0xF2C9007F ++ ++/* SFDILSTKM */ ++#define R367_OFDM_SFDILSTKM 0xF2CA ++#define F367_OFDM_SFEC_PACKCPT 0xF2CA00E0 ++#define F367_OFDM_SFEC_DILSTK_HI 0xF2CA001F ++ ++/* SFDILSTKL */ ++#define R367_OFDM_SFDILSTKL 0xF2CB ++#define F367_OFDM_SFEC_DILSTK_LO 0xF2CB00FF ++ ++/* SFSTATUS */ ++#define R367_OFDM_SFSTATUS 0xF2CC ++#define F367_OFDM_SFEC_LINEOK 0xF2CC0080 ++#define F367_OFDM_SFEC_ERROR 0xF2CC0040 ++#define F367_OFDM_SFEC_DATA7 0xF2CC0020 ++#define F367_OFDM_SFEC_OVERFLOW 0xF2CC0010 ++#define F367_OFDM_SFEC_DEMODSEL2 0xF2CC0008 ++#define F367_OFDM_SFEC_NOSYNC 0xF2CC0004 ++#define F367_OFDM_SFEC_UNREGULA 0xF2CC0002 ++#define F367_OFDM_SFEC_READY 0xF2CC0001 ++ ++/* SFDLYH */ ++#define R367_OFDM_SFDLYH 0xF2CD ++#define F367_OFDM_SFEC_TSTIMEVALID 0xF2CD0080 ++#define F367_OFDM_SFEC_SPEEDUP 0xF2CD0040 ++#define F367_OFDM_SFEC_STOP 0xF2CD0020 ++#define F367_OFDM_SFEC_REGULATED 0xF2CD0010 ++#define F367_OFDM_SFEC_REALSYMBOFFSET 0xF2CD000F ++ ++/* SFDLYM */ ++#define R367_OFDM_SFDLYM 0xF2CE ++#define F367_OFDM_SFEC_REALSYMBOFFSET_HI 0xF2CE00FF ++ ++/* SFDLYL */ ++#define R367_OFDM_SFDLYL 0xF2CF ++#define F367_OFDM_SFEC_REALSYMBOFFSET_LO 0xF2CF00FF ++ ++/* SFDLYSETH */ ++#define R367_OFDM_SFDLYSETH 0xF2D0 ++#define F367_OFDM_SFEC_OFFSET 0xF2D000E0 ++#define F367_OFDM_SFECDLYSETH_4 0xF2D00010 ++#define F367_OFDM_RST_SFEC 0xF2D00008 ++#define F367_OFDM_SFECDLYSETH_2 0xF2D00004 ++#define F367_OFDM_SFEC_DISABLE 0xF2D00002 ++#define F367_OFDM_SFEC_UNREGUL 0xF2D00001 ++ ++/* SFDLYSETM */ ++#define R367_OFDM_SFDLYSETM 0xF2D1 ++#define F367_OFDM_SFECDLYSETM_7 0xF2D10080 ++#define F367_OFDM_SFEC_SYMBOFFSET_HI 0xF2D1007F ++ ++/* SFDLYSETL */ ++#define R367_OFDM_SFDLYSETL 0xF2D2 ++#define F367_OFDM_SFEC_SYMBOFFSET_LO 0xF2D200FF ++ ++/* SFOBSCFG */ ++#define R367_OFDM_SFOBSCFG 0xF2D3 ++#define F367_OFDM_SFEC_OBSCFG 0xF2D300FF ++ ++/* SFOBSM */ ++#define R367_OFDM_SFOBSM 0xF2D4 ++#define F367_OFDM_SFEC_OBSDATA_HI 0xF2D400FF ++ ++/* SFOBSL */ ++#define R367_OFDM_SFOBSL 0xF2D5 ++#define F367_OFDM_SFEC_OBSDATA_LO 0xF2D500FF ++ ++/* SFECINFO */ ++#define R367_OFDM_SFECINFO 0xF2D6 ++#define F367_OFDM_SFECINFO_7 0xF2D60080 ++#define F367_OFDM_SFEC_SYNCDLSB 0xF2D60070 ++#define F367_OFDM_SFCE_S1CPHASE 0xF2D6000F ++ ++/* SFERRCTRL */ ++#define R367_OFDM_SFERRCTRL 0xF2D8 ++#define F367_OFDM_SFEC_ERR_SOURCE 0xF2D800F0 ++#define F367_OFDM_SFERRCTRL_3 0xF2D80008 ++#define F367_OFDM_SFEC_NUM_EVENT 0xF2D80007 ++ ++/* SFERRCNTH */ ++#define R367_OFDM_SFERRCNTH 0xF2D9 ++#define F367_OFDM_SFERRC_OLDVALUE 0xF2D90080 ++#define F367_OFDM_SFEC_ERR_CNT 0xF2D9007F ++ ++/* SFERRCNTM */ ++#define R367_OFDM_SFERRCNTM 0xF2DA ++#define F367_OFDM_SFEC_ERR_CNT_HI 0xF2DA00FF ++ ++/* SFERRCNTL */ ++#define R367_OFDM_SFERRCNTL 0xF2DB ++#define F367_OFDM_SFEC_ERR_CNT_LO 0xF2DB00FF ++ ++/* SYMBRATEM */ ++#define R367_OFDM_SYMBRATEM 0xF2E0 ++#define F367_OFDM_DEFGEN_SYMBRATE_HI 0xF2E000FF ++ ++/* SYMBRATEL */ ++#define R367_OFDM_SYMBRATEL 0xF2E1 ++#define F367_OFDM_DEFGEN_SYMBRATE_LO 0xF2E100FF ++ ++/* SYMBSTATUS */ ++#define R367_OFDM_SYMBSTATUS 0xF2E2 ++#define F367_OFDM_SYMBDLINE2_OFF 0xF2E20080 ++#define F367_OFDM_SDDL_REINIT1 0xF2E20040 ++#define F367_OFDM_SDD_REINIT1 0xF2E20020 ++#define F367_OFDM_TOKENID_ERROR 0xF2E20010 ++#define F367_OFDM_SYMBRATE_OVERFLOW 0xF2E20008 ++#define F367_OFDM_SYMBRATE_UNDERFLOW 0xF2E20004 ++#define F367_OFDM_TOKENID_RSTEVENT 0xF2E20002 ++#define F367_OFDM_TOKENID_RESET1 0xF2E20001 ++ ++/* SYMBCFG */ ++#define R367_OFDM_SYMBCFG 0xF2E3 ++#define F367_OFDM_SYMBCFG_7 0xF2E30080 ++#define F367_OFDM_SYMBCFG_6 0xF2E30040 ++#define F367_OFDM_SYMBCFG_5 0xF2E30020 ++#define F367_OFDM_SYMBCFG_4 0xF2E30010 ++#define F367_OFDM_SYMRATE_FSPEED 0xF2E3000C ++#define F367_OFDM_SYMRATE_SSPEED 0xF2E30003 ++ ++/* SYMBFIFOM */ ++#define R367_OFDM_SYMBFIFOM 0xF2E4 ++#define F367_OFDM_SYMBFIFOM_7 0xF2E40080 ++#define F367_OFDM_SYMBFIFOM_6 0xF2E40040 ++#define F367_OFDM_DEFGEN_SYMFIFO_HI 0xF2E4003F ++ ++/* SYMBFIFOL */ ++#define R367_OFDM_SYMBFIFOL 0xF2E5 ++#define F367_OFDM_DEFGEN_SYMFIFO_LO 0xF2E500FF ++ ++/* SYMBOFFSM */ ++#define R367_OFDM_SYMBOFFSM 0xF2E6 ++#define F367_OFDM_TOKENID_RESET2 0xF2E60080 ++#define F367_OFDM_SDDL_REINIT2 0xF2E60040 ++#define F367_OFDM_SDD_REINIT2 0xF2E60020 ++#define F367_OFDM_SYMBOFFSM_4 0xF2E60010 ++#define F367_OFDM_SYMBOFFSM_3 0xF2E60008 ++#define F367_OFDM_DEFGEN_SYMBOFFSET_HI 0xF2E60007 ++ ++/* SYMBOFFSL */ ++#define R367_OFDM_SYMBOFFSL 0xF2E7 ++#define F367_OFDM_DEFGEN_SYMBOFFSET_LO 0xF2E700FF ++ ++/* DEBUG_LT4 */ ++#define R367_DEBUG_LT4 0xF400 ++#define F367_F_DEBUG_LT4 0xF40000FF ++ ++/* DEBUG_LT5 */ ++#define R367_DEBUG_LT5 0xF401 ++#define F367_F_DEBUG_LT5 0xF40100FF ++ ++/* DEBUG_LT6 */ ++#define R367_DEBUG_LT6 0xF402 ++#define F367_F_DEBUG_LT6 0xF40200FF ++ ++/* DEBUG_LT7 */ ++#define R367_DEBUG_LT7 0xF403 ++#define F367_F_DEBUG_LT7 0xF40300FF ++ ++/* DEBUG_LT8 */ ++#define R367_DEBUG_LT8 0xF404 ++#define F367_F_DEBUG_LT8 0xF40400FF ++ ++/* DEBUG_LT9 */ ++#define R367_DEBUG_LT9 0xF405 ++#define F367_F_DEBUG_LT9 0xF40500FF ++ ++/* CTRL_1 */ ++#define R367_QAM_CTRL_1 0xF402 ++#define F367_QAM_SOFT_RST 0xF4020080 ++#define F367_QAM_EQU_RST 0xF4020008 ++#define F367_QAM_CRL_RST 0xF4020004 ++#define F367_QAM_TRL_RST 0xF4020002 ++#define F367_QAM_AGC_RST 0xF4020001 ++ ++/* CTRL_2 */ ++#define R367_QAM_CTRL_2 0xF403 ++#define F367_QAM_DEINT_RST 0xF4030008 ++#define F367_QAM_RS_RST 0xF4030004 ++ ++/* IT_STATUS1 */ ++#define R367_QAM_IT_STATUS1 0xF408 ++#define F367_QAM_SWEEP_OUT 0xF4080080 ++#define F367_QAM_FSM_CRL 0xF4080040 ++#define F367_QAM_CRL_LOCK 0xF4080020 ++#define F367_QAM_MFSM 0xF4080010 ++#define F367_QAM_TRL_LOCK 0xF4080008 ++#define F367_QAM_TRL_AGC_LIMIT 0xF4080004 ++#define F367_QAM_ADJ_AGC_LOCK 0xF4080002 ++#define F367_QAM_AGC_QAM_LOCK 0xF4080001 ++ ++/* IT_STATUS2 */ ++#define R367_QAM_IT_STATUS2 0xF409 ++#define F367_QAM_TSMF_CNT 0xF4090080 ++#define F367_QAM_TSMF_EOF 0xF4090040 ++#define F367_QAM_TSMF_RDY 0xF4090020 ++#define F367_QAM_FEC_NOCORR 0xF4090010 ++#define F367_QAM_SYNCSTATE 0xF4090008 ++#define F367_QAM_DEINT_LOCK 0xF4090004 ++#define F367_QAM_FADDING_FRZ 0xF4090002 ++#define F367_QAM_TAPMON_ALARM 0xF4090001 ++ ++/* IT_EN1 */ ++#define R367_QAM_IT_EN1 0xF40A ++#define F367_QAM_SWEEP_OUTE 0xF40A0080 ++#define F367_QAM_FSM_CRLE 0xF40A0040 ++#define F367_QAM_CRL_LOCKE 0xF40A0020 ++#define F367_QAM_MFSME 0xF40A0010 ++#define F367_QAM_TRL_LOCKE 0xF40A0008 ++#define F367_QAM_TRL_AGC_LIMITE 0xF40A0004 ++#define F367_QAM_ADJ_AGC_LOCKE 0xF40A0002 ++#define F367_QAM_AGC_LOCKE 0xF40A0001 ++ ++/* IT_EN2 */ ++#define R367_QAM_IT_EN2 0xF40B ++#define F367_QAM_TSMF_CNTE 0xF40B0080 ++#define F367_QAM_TSMF_EOFE 0xF40B0040 ++#define F367_QAM_TSMF_RDYE 0xF40B0020 ++#define F367_QAM_FEC_NOCORRE 0xF40B0010 ++#define F367_QAM_SYNCSTATEE 0xF40B0008 ++#define F367_QAM_DEINT_LOCKE 0xF40B0004 ++#define F367_QAM_FADDING_FRZE 0xF40B0002 ++#define F367_QAM_TAPMON_ALARME 0xF40B0001 ++ ++/* CTRL_STATUS */ ++#define R367_QAM_CTRL_STATUS 0xF40C ++#define F367_QAM_QAMFEC_LOCK 0xF40C0004 ++#define F367_QAM_TSMF_LOCK 0xF40C0002 ++#define F367_QAM_TSMF_ERROR 0xF40C0001 ++ ++/* TEST_CTL */ ++#define R367_QAM_TEST_CTL 0xF40F ++#define F367_QAM_TST_BLK_SEL 0xF40F0060 ++#define F367_QAM_TST_BUS_SEL 0xF40F001F ++ ++/* AGC_CTL */ ++#define R367_QAM_AGC_CTL 0xF410 ++#define F367_QAM_AGC_LCK_TH 0xF41000F0 ++#define F367_QAM_AGC_ACCUMRSTSEL 0xF4100007 ++ ++/* AGC_IF_CFG */ ++#define R367_QAM_AGC_IF_CFG 0xF411 ++#define F367_QAM_AGC_IF_BWSEL 0xF41100F0 ++#define F367_QAM_AGC_IF_FREEZE 0xF4110002 ++ ++/* AGC_RF_CFG */ ++#define R367_QAM_AGC_RF_CFG 0xF412 ++#define F367_QAM_AGC_RF_BWSEL 0xF4120070 ++#define F367_QAM_AGC_RF_FREEZE 0xF4120002 ++ ++/* AGC_PWM_CFG */ ++#define R367_QAM_AGC_PWM_CFG 0xF413 ++#define F367_QAM_AGC_RF_PWM_TST 0xF4130080 ++#define F367_QAM_AGC_RF_PWM_INV 0xF4130040 ++#define F367_QAM_AGC_IF_PWM_TST 0xF4130008 ++#define F367_QAM_AGC_IF_PWM_INV 0xF4130004 ++#define F367_QAM_AGC_PWM_CLKDIV 0xF4130003 ++ ++/* AGC_PWR_REF_L */ ++#define R367_QAM_AGC_PWR_REF_L 0xF414 ++#define F367_QAM_AGC_PWRREF_LO 0xF41400FF ++ ++/* AGC_PWR_REF_H */ ++#define R367_QAM_AGC_PWR_REF_H 0xF415 ++#define F367_QAM_AGC_PWRREF_HI 0xF4150003 ++ ++/* AGC_RF_TH_L */ ++#define R367_QAM_AGC_RF_TH_L 0xF416 ++#define F367_QAM_AGC_RF_TH_LO 0xF41600FF ++ ++/* AGC_RF_TH_H */ ++#define R367_QAM_AGC_RF_TH_H 0xF417 ++#define F367_QAM_AGC_RF_TH_HI 0xF417000F ++ ++/* AGC_IF_LTH_L */ ++#define R367_QAM_AGC_IF_LTH_L 0xF418 ++#define F367_QAM_AGC_IF_THLO_LO 0xF41800FF ++ ++/* AGC_IF_LTH_H */ ++#define R367_QAM_AGC_IF_LTH_H 0xF419 ++#define F367_QAM_AGC_IF_THLO_HI 0xF419000F ++ ++/* AGC_IF_HTH_L */ ++#define R367_QAM_AGC_IF_HTH_L 0xF41A ++#define F367_QAM_AGC_IF_THHI_LO 0xF41A00FF ++ ++/* AGC_IF_HTH_H */ ++#define R367_QAM_AGC_IF_HTH_H 0xF41B ++#define F367_QAM_AGC_IF_THHI_HI 0xF41B000F ++ ++/* AGC_PWR_RD_L */ ++#define R367_QAM_AGC_PWR_RD_L 0xF41C ++#define F367_QAM_AGC_PWR_WORD_LO 0xF41C00FF ++ ++/* AGC_PWR_RD_M */ ++#define R367_QAM_AGC_PWR_RD_M 0xF41D ++#define F367_QAM_AGC_PWR_WORD_ME 0xF41D00FF ++ ++/* AGC_PWR_RD_H */ ++#define R367_QAM_AGC_PWR_RD_H 0xF41E ++#define F367_QAM_AGC_PWR_WORD_HI 0xF41E0003 ++ ++/* AGC_PWM_IFCMD_L */ ++#define R367_QAM_AGC_PWM_IFCMD_L 0xF420 ++#define F367_QAM_AGC_IF_PWMCMD_LO 0xF42000FF ++ ++/* AGC_PWM_IFCMD_H */ ++#define R367_QAM_AGC_PWM_IFCMD_H 0xF421 ++#define F367_QAM_AGC_IF_PWMCMD_HI 0xF421000F ++ ++/* AGC_PWM_RFCMD_L */ ++#define R367_QAM_AGC_PWM_RFCMD_L 0xF422 ++#define F367_QAM_AGC_RF_PWMCMD_LO 0xF42200FF ++ ++/* AGC_PWM_RFCMD_H */ ++#define R367_QAM_AGC_PWM_RFCMD_H 0xF423 ++#define F367_QAM_AGC_RF_PWMCMD_HI 0xF423000F ++ ++/* IQDEM_CFG */ ++#define R367_QAM_IQDEM_CFG 0xF424 ++#define F367_QAM_IQDEM_CLK_SEL 0xF4240004 ++#define F367_QAM_IQDEM_INVIQ 0xF4240002 ++#define F367_QAM_IQDEM_A2DTYPE 0xF4240001 ++ ++/* MIX_NCO_LL */ ++#define R367_QAM_MIX_NCO_LL 0xF425 ++#define F367_QAM_MIX_NCO_INC_LL 0xF42500FF ++ ++/* MIX_NCO_HL */ ++#define R367_QAM_MIX_NCO_HL 0xF426 ++#define F367_QAM_MIX_NCO_INC_HL 0xF42600FF ++ ++/* MIX_NCO_HH */ ++#define R367_QAM_MIX_NCO_HH 0xF427 ++#define F367_QAM_MIX_NCO_INVCNST 0xF4270080 ++#define F367_QAM_MIX_NCO_INC_HH 0xF427007F ++ ++/* SRC_NCO_LL */ ++#define R367_QAM_SRC_NCO_LL 0xF428 ++#define F367_QAM_SRC_NCO_INC_LL 0xF42800FF ++ ++/* SRC_NCO_LH */ ++#define R367_QAM_SRC_NCO_LH 0xF429 ++#define F367_QAM_SRC_NCO_INC_LH 0xF42900FF ++ ++/* SRC_NCO_HL */ ++#define R367_QAM_SRC_NCO_HL 0xF42A ++#define F367_QAM_SRC_NCO_INC_HL 0xF42A00FF ++ ++/* SRC_NCO_HH */ ++#define R367_QAM_SRC_NCO_HH 0xF42B ++#define F367_QAM_SRC_NCO_INC_HH 0xF42B007F ++ ++/* IQDEM_GAIN_SRC_L */ ++#define R367_QAM_IQDEM_GAIN_SRC_L 0xF42C ++#define F367_QAM_GAIN_SRC_LO 0xF42C00FF ++ ++/* IQDEM_GAIN_SRC_H */ ++#define R367_QAM_IQDEM_GAIN_SRC_H 0xF42D ++#define F367_QAM_GAIN_SRC_HI 0xF42D0003 ++ ++/* IQDEM_DCRM_CFG_LL */ ++#define R367_QAM_IQDEM_DCRM_CFG_LL 0xF430 ++#define F367_QAM_DCRM0_DCIN_L 0xF43000FF ++ ++/* IQDEM_DCRM_CFG_LH */ ++#define R367_QAM_IQDEM_DCRM_CFG_LH 0xF431 ++#define F367_QAM_DCRM1_I_DCIN_L 0xF43100FC ++#define F367_QAM_DCRM0_DCIN_H 0xF4310003 ++ ++/* IQDEM_DCRM_CFG_HL */ ++#define R367_QAM_IQDEM_DCRM_CFG_HL 0xF432 ++#define F367_QAM_DCRM1_Q_DCIN_L 0xF43200F0 ++#define F367_QAM_DCRM1_I_DCIN_H 0xF432000F ++ ++/* IQDEM_DCRM_CFG_HH */ ++#define R367_QAM_IQDEM_DCRM_CFG_HH 0xF433 ++#define F367_QAM_DCRM1_FRZ 0xF4330080 ++#define F367_QAM_DCRM0_FRZ 0xF4330040 ++#define F367_QAM_DCRM1_Q_DCIN_H 0xF433003F ++ ++/* IQDEM_ADJ_COEFF0 */ ++#define R367_QAM_IQDEM_ADJ_COEFF0 0xF434 ++#define F367_QAM_ADJIIR_COEFF10_L 0xF43400FF ++ ++/* IQDEM_ADJ_COEFF1 */ ++#define R367_QAM_IQDEM_ADJ_COEFF1 0xF435 ++#define F367_QAM_ADJIIR_COEFF11_L 0xF43500FC ++#define F367_QAM_ADJIIR_COEFF10_H 0xF4350003 ++ ++/* IQDEM_ADJ_COEFF2 */ ++#define R367_QAM_IQDEM_ADJ_COEFF2 0xF436 ++#define F367_QAM_ADJIIR_COEFF12_L 0xF43600F0 ++#define F367_QAM_ADJIIR_COEFF11_H 0xF436000F ++ ++/* IQDEM_ADJ_COEFF3 */ ++#define R367_QAM_IQDEM_ADJ_COEFF3 0xF437 ++#define F367_QAM_ADJIIR_COEFF20_L 0xF43700C0 ++#define F367_QAM_ADJIIR_COEFF12_H 0xF437003F ++ ++/* IQDEM_ADJ_COEFF4 */ ++#define R367_QAM_IQDEM_ADJ_COEFF4 0xF438 ++#define F367_QAM_ADJIIR_COEFF20_H 0xF43800FF ++ ++/* IQDEM_ADJ_COEFF5 */ ++#define R367_QAM_IQDEM_ADJ_COEFF5 0xF439 ++#define F367_QAM_ADJIIR_COEFF21_L 0xF43900FF ++ ++/* IQDEM_ADJ_COEFF6 */ ++#define R367_QAM_IQDEM_ADJ_COEFF6 0xF43A ++#define F367_QAM_ADJIIR_COEFF22_L 0xF43A00FC ++#define F367_QAM_ADJIIR_COEFF21_H 0xF43A0003 ++ ++/* IQDEM_ADJ_COEFF7 */ ++#define R367_QAM_IQDEM_ADJ_COEFF7 0xF43B ++#define F367_QAM_ADJIIR_COEFF22_H 0xF43B000F ++ ++/* IQDEM_ADJ_EN */ ++#define R367_QAM_IQDEM_ADJ_EN 0xF43C ++#define F367_QAM_ALLPASSFILT_EN 0xF43C0008 ++#define F367_QAM_ADJ_AGC_EN 0xF43C0004 ++#define F367_QAM_ADJ_COEFF_FRZ 0xF43C0002 ++#define F367_QAM_ADJ_EN 0xF43C0001 ++ ++/* IQDEM_ADJ_AGC_REF */ ++#define R367_QAM_IQDEM_ADJ_AGC_REF 0xF43D ++#define F367_QAM_ADJ_AGC_REF 0xF43D00FF ++ ++/* ALLPASSFILT1 */ ++#define R367_QAM_ALLPASSFILT1 0xF440 ++#define F367_QAM_ALLPASSFILT_COEFF1_LO 0xF44000FF ++ ++/* ALLPASSFILT2 */ ++#define R367_QAM_ALLPASSFILT2 0xF441 ++#define F367_QAM_ALLPASSFILT_COEFF1_ME 0xF44100FF ++ ++/* ALLPASSFILT3 */ ++#define R367_QAM_ALLPASSFILT3 0xF442 ++#define F367_QAM_ALLPASSFILT_COEFF2_LO 0xF44200C0 ++#define F367_QAM_ALLPASSFILT_COEFF1_HI 0xF442003F ++ ++/* ALLPASSFILT4 */ ++#define R367_QAM_ALLPASSFILT4 0xF443 ++#define F367_QAM_ALLPASSFILT_COEFF2_MEL 0xF44300FF ++ ++/* ALLPASSFILT5 */ ++#define R367_QAM_ALLPASSFILT5 0xF444 ++#define F367_QAM_ALLPASSFILT_COEFF2_MEH 0xF44400FF ++ ++/* ALLPASSFILT6 */ ++#define R367_QAM_ALLPASSFILT6 0xF445 ++#define F367_QAM_ALLPASSFILT_COEFF3_LO 0xF44500F0 ++#define F367_QAM_ALLPASSFILT_COEFF2_HI 0xF445000F ++ ++/* ALLPASSFILT7 */ ++#define R367_QAM_ALLPASSFILT7 0xF446 ++#define F367_QAM_ALLPASSFILT_COEFF3_MEL 0xF44600FF ++ ++/* ALLPASSFILT8 */ ++#define R367_QAM_ALLPASSFILT8 0xF447 ++#define F367_QAM_ALLPASSFILT_COEFF3_MEH 0xF44700FF ++ ++/* ALLPASSFILT9 */ ++#define R367_QAM_ALLPASSFILT9 0xF448 ++#define F367_QAM_ALLPASSFILT_COEFF4_LO 0xF44800FC ++#define F367_QAM_ALLPASSFILT_COEFF3_HI 0xF4480003 ++ ++/* ALLPASSFILT10 */ ++#define R367_QAM_ALLPASSFILT10 0xF449 ++#define F367_QAM_ALLPASSFILT_COEFF4_ME 0xF44900FF ++ ++/* ALLPASSFILT11 */ ++#define R367_QAM_ALLPASSFILT11 0xF44A ++#define F367_QAM_ALLPASSFILT_COEFF4_HI 0xF44A00FF ++ ++/* TRL_AGC_CFG */ ++#define R367_QAM_TRL_AGC_CFG 0xF450 ++#define F367_QAM_TRL_AGC_FREEZE 0xF4500080 ++#define F367_QAM_TRL_AGC_REF 0xF450007F ++ ++/* TRL_LPF_CFG */ ++#define R367_QAM_TRL_LPF_CFG 0xF454 ++#define F367_QAM_NYQPOINT_INV 0xF4540040 ++#define F367_QAM_TRL_SHIFT 0xF4540030 ++#define F367_QAM_NYQ_COEFF_SEL 0xF454000C ++#define F367_QAM_TRL_LPF_FREEZE 0xF4540002 ++#define F367_QAM_TRL_LPF_CRT 0xF4540001 ++ ++/* TRL_LPF_ACQ_GAIN */ ++#define R367_QAM_TRL_LPF_ACQ_GAIN 0xF455 ++#define F367_QAM_TRL_GDIR_ACQ 0xF4550070 ++#define F367_QAM_TRL_GINT_ACQ 0xF4550007 ++ ++/* TRL_LPF_TRK_GAIN */ ++#define R367_QAM_TRL_LPF_TRK_GAIN 0xF456 ++#define F367_QAM_TRL_GDIR_TRK 0xF4560070 ++#define F367_QAM_TRL_GINT_TRK 0xF4560007 ++ ++/* TRL_LPF_OUT_GAIN */ ++#define R367_QAM_TRL_LPF_OUT_GAIN 0xF457 ++#define F367_QAM_TRL_GAIN_OUT 0xF4570007 ++ ++/* TRL_LOCKDET_LTH */ ++#define R367_QAM_TRL_LOCKDET_LTH 0xF458 ++#define F367_QAM_TRL_LCK_THLO 0xF4580007 ++ ++/* TRL_LOCKDET_HTH */ ++#define R367_QAM_TRL_LOCKDET_HTH 0xF459 ++#define F367_QAM_TRL_LCK_THHI 0xF45900FF ++ ++/* TRL_LOCKDET_TRGVAL */ ++#define R367_QAM_TRL_LOCKDET_TRGVAL 0xF45A ++#define F367_QAM_TRL_LCK_TRG 0xF45A00FF ++ ++/* IQ_QAM */ ++#define R367_QAM_IQ_QAM 0xF45C ++#define F367_QAM_IQ_INPUT 0xF45C0008 ++#define F367_QAM_DETECT_MODE 0xF45C0007 ++ ++/* FSM_STATE */ ++#define R367_QAM_FSM_STATE 0xF460 ++#define F367_QAM_CRL_DFE 0xF4600080 ++#define F367_QAM_DFE_START 0xF4600040 ++#define F367_QAM_CTRLG_START 0xF4600030 ++#define F367_QAM_FSM_FORCESTATE 0xF460000F ++ ++/* FSM_CTL */ ++#define R367_QAM_FSM_CTL 0xF461 ++#define F367_QAM_FEC2_EN 0xF4610040 ++#define F367_QAM_SIT_EN 0xF4610020 ++#define F367_QAM_TRL_AHEAD 0xF4610010 ++#define F367_QAM_TRL2_EN 0xF4610008 ++#define F367_QAM_FSM_EQA1_EN 0xF4610004 ++#define F367_QAM_FSM_BKP_DIS 0xF4610002 ++#define F367_QAM_FSM_FORCE_EN 0xF4610001 ++ ++/* FSM_STS */ ++#define R367_QAM_FSM_STS 0xF462 ++#define F367_QAM_FSM_STATUS 0xF462000F ++ ++/* FSM_SNR0_HTH */ ++#define R367_QAM_FSM_SNR0_HTH 0xF463 ++#define F367_QAM_SNR0_HTH 0xF46300FF ++ ++/* FSM_SNR1_HTH */ ++#define R367_QAM_FSM_SNR1_HTH 0xF464 ++#define F367_QAM_SNR1_HTH 0xF46400FF ++ ++/* FSM_SNR2_HTH */ ++#define R367_QAM_FSM_SNR2_HTH 0xF465 ++#define F367_QAM_SNR2_HTH 0xF46500FF ++ ++/* FSM_SNR0_LTH */ ++#define R367_QAM_FSM_SNR0_LTH 0xF466 ++#define F367_QAM_SNR0_LTH 0xF46600FF ++ ++/* FSM_SNR1_LTH */ ++#define R367_QAM_FSM_SNR1_LTH 0xF467 ++#define F367_QAM_SNR1_LTH 0xF46700FF ++ ++/* FSM_EQA1_HTH */ ++#define R367_QAM_FSM_EQA1_HTH 0xF468 ++#define F367_QAM_SNR3_HTH_LO 0xF46800F0 ++#define F367_QAM_EQA1_HTH 0xF468000F ++ ++/* FSM_TEMPO */ ++#define R367_QAM_FSM_TEMPO 0xF469 ++#define F367_QAM_SIT 0xF46900C0 ++#define F367_QAM_WST 0xF4690038 ++#define F367_QAM_ELT 0xF4690006 ++#define F367_QAM_SNR3_HTH_HI 0xF4690001 ++ ++/* FSM_CONFIG */ ++#define R367_QAM_FSM_CONFIG 0xF46A ++#define F367_QAM_FEC2_DFEOFF 0xF46A0004 ++#define F367_QAM_PRIT_STATE 0xF46A0002 ++#define F367_QAM_MODMAP_STATE 0xF46A0001 ++ ++/* EQU_I_TESTTAP_L */ ++#define R367_QAM_EQU_I_TESTTAP_L 0xF474 ++#define F367_QAM_I_TEST_TAP_L 0xF47400FF ++ ++/* EQU_I_TESTTAP_M */ ++#define R367_QAM_EQU_I_TESTTAP_M 0xF475 ++#define F367_QAM_I_TEST_TAP_M 0xF47500FF ++ ++/* EQU_I_TESTTAP_H */ ++#define R367_QAM_EQU_I_TESTTAP_H 0xF476 ++#define F367_QAM_I_TEST_TAP_H 0xF476001F ++ ++/* EQU_TESTAP_CFG */ ++#define R367_QAM_EQU_TESTAP_CFG 0xF477 ++#define F367_QAM_TEST_FFE_DFE_SEL 0xF4770040 ++#define F367_QAM_TEST_TAP_SELECT 0xF477003F ++ ++/* EQU_Q_TESTTAP_L */ ++#define R367_QAM_EQU_Q_TESTTAP_L 0xF478 ++#define F367_QAM_Q_TEST_TAP_L 0xF47800FF ++ ++/* EQU_Q_TESTTAP_M */ ++#define R367_QAM_EQU_Q_TESTTAP_M 0xF479 ++#define F367_QAM_Q_TEST_TAP_M 0xF47900FF ++ ++/* EQU_Q_TESTTAP_H */ ++#define R367_QAM_EQU_Q_TESTTAP_H 0xF47A ++#define F367_QAM_Q_TEST_TAP_H 0xF47A001F ++ ++/* EQU_TAP_CTRL */ ++#define R367_QAM_EQU_TAP_CTRL 0xF47B ++#define F367_QAM_MTAP_FRZ 0xF47B0010 ++#define F367_QAM_PRE_FREEZE 0xF47B0008 ++#define F367_QAM_DFE_TAPMON_EN 0xF47B0004 ++#define F367_QAM_FFE_TAPMON_EN 0xF47B0002 ++#define F367_QAM_MTAP_ONLY 0xF47B0001 ++ ++/* EQU_CTR_CRL_CONTROL_L */ ++#define R367_QAM_EQU_CTR_CRL_CONTROL_L 0xF47C ++#define F367_QAM_EQU_CTR_CRL_CONTROL_LO 0xF47C00FF ++ ++/* EQU_CTR_CRL_CONTROL_H */ ++#define R367_QAM_EQU_CTR_CRL_CONTROL_H 0xF47D ++#define F367_QAM_EQU_CTR_CRL_CONTROL_HI 0xF47D00FF ++ ++/* EQU_CTR_HIPOW_L */ ++#define R367_QAM_EQU_CTR_HIPOW_L 0xF47E ++#define F367_QAM_CTR_HIPOW_L 0xF47E00FF ++ ++/* EQU_CTR_HIPOW_H */ ++#define R367_QAM_EQU_CTR_HIPOW_H 0xF47F ++#define F367_QAM_CTR_HIPOW_H 0xF47F00FF ++ ++/* EQU_I_EQU_LO */ ++#define R367_QAM_EQU_I_EQU_LO 0xF480 ++#define F367_QAM_EQU_I_EQU_L 0xF48000FF ++ ++/* EQU_I_EQU_HI */ ++#define R367_QAM_EQU_I_EQU_HI 0xF481 ++#define F367_QAM_EQU_I_EQU_H 0xF4810003 ++ ++/* EQU_Q_EQU_LO */ ++#define R367_QAM_EQU_Q_EQU_LO 0xF482 ++#define F367_QAM_EQU_Q_EQU_L 0xF48200FF ++ ++/* EQU_Q_EQU_HI */ ++#define R367_QAM_EQU_Q_EQU_HI 0xF483 ++#define F367_QAM_EQU_Q_EQU_H 0xF4830003 ++ ++/* EQU_MAPPER */ ++#define R367_QAM_EQU_MAPPER 0xF484 ++#define F367_QAM_QUAD_AUTO 0xF4840080 ++#define F367_QAM_QUAD_INV 0xF4840040 ++#define F367_QAM_QAM_MODE 0xF4840007 ++ ++/* EQU_SWEEP_RATE */ ++#define R367_QAM_EQU_SWEEP_RATE 0xF485 ++#define F367_QAM_SNR_PER 0xF48500C0 ++#define F367_QAM_SWEEP_RATE 0xF485003F ++ ++/* EQU_SNR_LO */ ++#define R367_QAM_EQU_SNR_LO 0xF486 ++#define F367_QAM_SNR_LO 0xF48600FF ++ ++/* EQU_SNR_HI */ ++#define R367_QAM_EQU_SNR_HI 0xF487 ++#define F367_QAM_SNR_HI 0xF48700FF ++ ++/* EQU_GAMMA_LO */ ++#define R367_QAM_EQU_GAMMA_LO 0xF488 ++#define F367_QAM_GAMMA_LO 0xF48800FF ++ ++/* EQU_GAMMA_HI */ ++#define R367_QAM_EQU_GAMMA_HI 0xF489 ++#define F367_QAM_GAMMA_ME 0xF48900FF ++ ++/* EQU_ERR_GAIN */ ++#define R367_QAM_EQU_ERR_GAIN 0xF48A ++#define F367_QAM_EQA1MU 0xF48A0070 ++#define F367_QAM_CRL2MU 0xF48A000E ++#define F367_QAM_GAMMA_HI 0xF48A0001 ++ ++/* EQU_RADIUS */ ++#define R367_QAM_EQU_RADIUS 0xF48B ++#define F367_QAM_RADIUS 0xF48B00FF ++ ++/* EQU_FFE_MAINTAP */ ++#define R367_QAM_EQU_FFE_MAINTAP 0xF48C ++#define F367_QAM_FFE_MAINTAP_INIT 0xF48C00FF ++ ++/* EQU_FFE_LEAKAGE */ ++#define R367_QAM_EQU_FFE_LEAKAGE 0xF48E ++#define F367_QAM_LEAK_PER 0xF48E00F0 ++#define F367_QAM_EQU_OUTSEL 0xF48E0002 ++#define F367_QAM_PNT2DFE 0xF48E0001 ++ ++/* EQU_FFE_MAINTAP_POS */ ++#define R367_QAM_EQU_FFE_MAINTAP_POS 0xF48F ++#define F367_QAM_FFE_LEAK_EN 0xF48F0080 ++#define F367_QAM_DFE_LEAK_EN 0xF48F0040 ++#define F367_QAM_FFE_MAINTAP_POS 0xF48F003F ++ ++/* EQU_GAIN_WIDE */ ++#define R367_QAM_EQU_GAIN_WIDE 0xF490 ++#define F367_QAM_DFE_GAIN_WIDE 0xF49000F0 ++#define F367_QAM_FFE_GAIN_WIDE 0xF490000F ++ ++/* EQU_GAIN_NARROW */ ++#define R367_QAM_EQU_GAIN_NARROW 0xF491 ++#define F367_QAM_DFE_GAIN_NARROW 0xF49100F0 ++#define F367_QAM_FFE_GAIN_NARROW 0xF491000F ++ ++/* EQU_CTR_LPF_GAIN */ ++#define R367_QAM_EQU_CTR_LPF_GAIN 0xF492 ++#define F367_QAM_CTR_GTO 0xF4920080 ++#define F367_QAM_CTR_GDIR 0xF4920070 ++#define F367_QAM_SWEEP_EN 0xF4920008 ++#define F367_QAM_CTR_GINT 0xF4920007 ++ ++/* EQU_CRL_LPF_GAIN */ ++#define R367_QAM_EQU_CRL_LPF_GAIN 0xF493 ++#define F367_QAM_CRL_GTO 0xF4930080 ++#define F367_QAM_CRL_GDIR 0xF4930070 ++#define F367_QAM_SWEEP_DIR 0xF4930008 ++#define F367_QAM_CRL_GINT 0xF4930007 ++ ++/* EQU_GLOBAL_GAIN */ ++#define R367_QAM_EQU_GLOBAL_GAIN 0xF494 ++#define F367_QAM_CRL_GAIN 0xF49400F8 ++#define F367_QAM_CTR_INC_GAIN 0xF4940004 ++#define F367_QAM_CTR_FRAC 0xF4940003 ++ ++/* EQU_CRL_LD_SEN */ ++#define R367_QAM_EQU_CRL_LD_SEN 0xF495 ++#define F367_QAM_CTR_BADPOINT_EN 0xF4950080 ++#define F367_QAM_CTR_GAIN 0xF4950070 ++#define F367_QAM_LIMANEN 0xF4950008 ++#define F367_QAM_CRL_LD_SEN 0xF4950007 ++ ++/* EQU_CRL_LD_VAL */ ++#define R367_QAM_EQU_CRL_LD_VAL 0xF496 ++#define F367_QAM_CRL_BISTH_LIMIT 0xF4960080 ++#define F367_QAM_CARE_EN 0xF4960040 ++#define F367_QAM_CRL_LD_PER 0xF4960030 ++#define F367_QAM_CRL_LD_WST 0xF496000C ++#define F367_QAM_CRL_LD_TFS 0xF4960003 ++ ++/* EQU_CRL_TFR */ ++#define R367_QAM_EQU_CRL_TFR 0xF497 ++#define F367_QAM_CRL_LD_TFR 0xF49700FF ++ ++/* EQU_CRL_BISTH_LO */ ++#define R367_QAM_EQU_CRL_BISTH_LO 0xF498 ++#define F367_QAM_CRL_BISTH_LO 0xF49800FF ++ ++/* EQU_CRL_BISTH_HI */ ++#define R367_QAM_EQU_CRL_BISTH_HI 0xF499 ++#define F367_QAM_CRL_BISTH_HI 0xF49900FF ++ ++/* EQU_SWEEP_RANGE_LO */ ++#define R367_QAM_EQU_SWEEP_RANGE_LO 0xF49A ++#define F367_QAM_SWEEP_RANGE_LO 0xF49A00FF ++ ++/* EQU_SWEEP_RANGE_HI */ ++#define R367_QAM_EQU_SWEEP_RANGE_HI 0xF49B ++#define F367_QAM_SWEEP_RANGE_HI 0xF49B00FF ++ ++/* EQU_CRL_LIMITER */ ++#define R367_QAM_EQU_CRL_LIMITER 0xF49C ++#define F367_QAM_BISECTOR_EN 0xF49C0080 ++#define F367_QAM_PHEST128_EN 0xF49C0040 ++#define F367_QAM_CRL_LIM 0xF49C003F ++ ++/* EQU_MODULUS_MAP */ ++#define R367_QAM_EQU_MODULUS_MAP 0xF49D ++#define F367_QAM_PNT_DEPTH 0xF49D00E0 ++#define F367_QAM_MODULUS_CMP 0xF49D001F ++ ++/* EQU_PNT_GAIN */ ++#define R367_QAM_EQU_PNT_GAIN 0xF49E ++#define F367_QAM_PNT_EN 0xF49E0080 ++#define F367_QAM_MODULUSMAP_EN 0xF49E0040 ++#define F367_QAM_PNT_GAIN 0xF49E003F ++ ++/* FEC_AC_CTR_0 */ ++#define R367_QAM_FEC_AC_CTR_0 0xF4A8 ++#define F367_QAM_BE_BYPASS 0xF4A80020 ++#define F367_QAM_REFRESH47 0xF4A80010 ++#define F367_QAM_CT_NBST 0xF4A80008 ++#define F367_QAM_TEI_ENA 0xF4A80004 ++#define F367_QAM_DS_ENA 0xF4A80002 ++#define F367_QAM_TSMF_EN 0xF4A80001 ++ ++/* FEC_AC_CTR_1 */ ++#define R367_QAM_FEC_AC_CTR_1 0xF4A9 ++#define F367_QAM_DEINT_DEPTH 0xF4A900FF ++ ++/* FEC_AC_CTR_2 */ ++#define R367_QAM_FEC_AC_CTR_2 0xF4AA ++#define F367_QAM_DEINT_M 0xF4AA00F8 ++#define F367_QAM_DIS_UNLOCK 0xF4AA0004 ++#define F367_QAM_DESCR_MODE 0xF4AA0003 ++ ++/* FEC_AC_CTR_3 */ ++#define R367_QAM_FEC_AC_CTR_3 0xF4AB ++#define F367_QAM_DI_UNLOCK 0xF4AB0080 ++#define F367_QAM_DI_FREEZE 0xF4AB0040 ++#define F367_QAM_MISMATCH 0xF4AB0030 ++#define F367_QAM_ACQ_MODE 0xF4AB000C ++#define F367_QAM_TRK_MODE 0xF4AB0003 ++ ++/* FEC_STATUS */ ++#define R367_QAM_FEC_STATUS 0xF4AC ++#define F367_QAM_DEINT_SMCNTR 0xF4AC00E0 ++#define F367_QAM_DEINT_SYNCSTATE 0xF4AC0018 ++#define F367_QAM_DEINT_SYNLOST 0xF4AC0004 ++#define F367_QAM_DESCR_SYNCSTATE 0xF4AC0002 ++ ++/* RS_COUNTER_0 */ ++#define R367_QAM_RS_COUNTER_0 0xF4AE ++#define F367_QAM_BK_CT_L 0xF4AE00FF ++ ++/* RS_COUNTER_1 */ ++#define R367_QAM_RS_COUNTER_1 0xF4AF ++#define F367_QAM_BK_CT_H 0xF4AF00FF ++ ++/* RS_COUNTER_2 */ ++#define R367_QAM_RS_COUNTER_2 0xF4B0 ++#define F367_QAM_CORR_CT_L 0xF4B000FF ++ ++/* RS_COUNTER_3 */ ++#define R367_QAM_RS_COUNTER_3 0xF4B1 ++#define F367_QAM_CORR_CT_H 0xF4B100FF ++ ++/* RS_COUNTER_4 */ ++#define R367_QAM_RS_COUNTER_4 0xF4B2 ++#define F367_QAM_UNCORR_CT_L 0xF4B200FF ++ ++/* RS_COUNTER_5 */ ++#define R367_QAM_RS_COUNTER_5 0xF4B3 ++#define F367_QAM_UNCORR_CT_H 0xF4B300FF ++ ++/* BERT_0 */ ++#define R367_QAM_BERT_0 0xF4B4 ++#define F367_QAM_RS_NOCORR 0xF4B40004 ++#define F367_QAM_CT_HOLD 0xF4B40002 ++#define F367_QAM_CT_CLEAR 0xF4B40001 ++ ++/* BERT_1 */ ++#define R367_QAM_BERT_1 0xF4B5 ++#define F367_QAM_BERT_ON 0xF4B50020 ++#define F367_QAM_BERT_ERR_SRC 0xF4B50010 ++#define F367_QAM_BERT_ERR_MODE 0xF4B50008 ++#define F367_QAM_BERT_NBYTE 0xF4B50007 ++ ++/* BERT_2 */ ++#define R367_QAM_BERT_2 0xF4B6 ++#define F367_QAM_BERT_ERRCOUNT_L 0xF4B600FF ++ ++/* BERT_3 */ ++#define R367_QAM_BERT_3 0xF4B7 ++#define F367_QAM_BERT_ERRCOUNT_H 0xF4B700FF ++ ++/* OUTFORMAT_0 */ ++#define R367_QAM_OUTFORMAT_0 0xF4B8 ++#define F367_QAM_CLK_POLARITY 0xF4B80080 ++#define F367_QAM_FEC_TYPE 0xF4B80040 ++#define F367_QAM_SYNC_STRIP 0xF4B80008 ++#define F367_QAM_TS_SWAP 0xF4B80004 ++#define F367_QAM_OUTFORMAT 0xF4B80003 ++ ++/* OUTFORMAT_1 */ ++#define R367_QAM_OUTFORMAT_1 0xF4B9 ++#define F367_QAM_CI_DIVRANGE 0xF4B900FF ++ ++/* SMOOTHER_2 */ ++#define R367_QAM_SMOOTHER_2 0xF4BE ++#define F367_QAM_FIFO_BYPASS 0xF4BE0020 ++ ++/* TSMF_CTRL_0 */ ++#define R367_QAM_TSMF_CTRL_0 0xF4C0 ++#define F367_QAM_TS_NUMBER 0xF4C0001E ++#define F367_QAM_SEL_MODE 0xF4C00001 ++ ++/* TSMF_CTRL_1 */ ++#define R367_QAM_TSMF_CTRL_1 0xF4C1 ++#define F367_QAM_CHECK_ERROR_BIT 0xF4C10080 ++#define F367_QAM_CHCK_F_SYNC 0xF4C10040 ++#define F367_QAM_H_MODE 0xF4C10008 ++#define F367_QAM_D_V_MODE 0xF4C10004 ++#define F367_QAM_MODE 0xF4C10003 ++ ++/* TSMF_CTRL_3 */ ++#define R367_QAM_TSMF_CTRL_3 0xF4C3 ++#define F367_QAM_SYNC_IN_COUNT 0xF4C300F0 ++#define F367_QAM_SYNC_OUT_COUNT 0xF4C3000F ++ ++/* TS_ON_ID_0 */ ++#define R367_QAM_TS_ON_ID_0 0xF4C4 ++#define F367_QAM_TS_ID_L 0xF4C400FF ++ ++/* TS_ON_ID_1 */ ++#define R367_QAM_TS_ON_ID_1 0xF4C5 ++#define F367_QAM_TS_ID_H 0xF4C500FF ++ ++/* TS_ON_ID_2 */ ++#define R367_QAM_TS_ON_ID_2 0xF4C6 ++#define F367_QAM_ON_ID_L 0xF4C600FF ++ ++/* TS_ON_ID_3 */ ++#define R367_QAM_TS_ON_ID_3 0xF4C7 ++#define F367_QAM_ON_ID_H 0xF4C700FF ++ ++/* RE_STATUS_0 */ ++#define R367_QAM_RE_STATUS_0 0xF4C8 ++#define F367_QAM_RECEIVE_STATUS_L 0xF4C800FF ++ ++/* RE_STATUS_1 */ ++#define R367_QAM_RE_STATUS_1 0xF4C9 ++#define F367_QAM_RECEIVE_STATUS_LH 0xF4C900FF ++ ++/* RE_STATUS_2 */ ++#define R367_QAM_RE_STATUS_2 0xF4CA ++#define F367_QAM_RECEIVE_STATUS_HL 0xF4CA00FF ++ ++/* RE_STATUS_3 */ ++#define R367_QAM_RE_STATUS_3 0xF4CB ++#define F367_QAM_RECEIVE_STATUS_HH 0xF4CB003F ++ ++/* TS_STATUS_0 */ ++#define R367_QAM_TS_STATUS_0 0xF4CC ++#define F367_QAM_TS_STATUS_L 0xF4CC00FF ++ ++/* TS_STATUS_1 */ ++#define R367_QAM_TS_STATUS_1 0xF4CD ++#define F367_QAM_TS_STATUS_H 0xF4CD007F ++ ++/* TS_STATUS_2 */ ++#define R367_QAM_TS_STATUS_2 0xF4CE ++#define F367_QAM_ERROR 0xF4CE0080 ++#define F367_QAM_EMERGENCY 0xF4CE0040 ++#define F367_QAM_CRE_TS 0xF4CE0030 ++#define F367_QAM_VER 0xF4CE000E ++#define F367_QAM_M_LOCK 0xF4CE0001 ++ ++/* TS_STATUS_3 */ ++#define R367_QAM_TS_STATUS_3 0xF4CF ++#define F367_QAM_UPDATE_READY 0xF4CF0080 ++#define F367_QAM_END_FRAME_HEADER 0xF4CF0040 ++#define F367_QAM_CONTCNT 0xF4CF0020 ++#define F367_QAM_TS_IDENTIFIER_SEL 0xF4CF000F ++ ++/* T_O_ID_0 */ ++#define R367_QAM_T_O_ID_0 0xF4D0 ++#define F367_QAM_ON_ID_I_L 0xF4D000FF ++ ++/* T_O_ID_1 */ ++#define R367_QAM_T_O_ID_1 0xF4D1 ++#define F367_QAM_ON_ID_I_H 0xF4D100FF ++ ++/* T_O_ID_2 */ ++#define R367_QAM_T_O_ID_2 0xF4D2 ++#define F367_QAM_TS_ID_I_L 0xF4D200FF ++ ++/* T_O_ID_3 */ ++#define R367_QAM_T_O_ID_3 0xF4D3 ++#define F367_QAM_TS_ID_I_H 0xF4D300FF ++ +diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c +index 0b2a934..ba93e7b 100644 +--- a/drivers/media/dvb-frontends/stv090x.c ++++ b/drivers/media/dvb-frontends/stv090x.c +@@ -3562,6 +3562,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) + return 0; + } + ++#if 0 + static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) + { + struct stv090x_state *state = fe->demodulator_priv; +@@ -3612,6 +3613,27 @@ err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; + } ++#endif ++ ++static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct stv090x_state *state = fe->demodulator_priv; ++ u32 reg, h, m, l; ++ ++ /* Counter 1: S1: 0x75 BER, S2: 0x67 PER */ ++ reg = STV090x_READ_DEMOD(state, ERRCNT12); ++ h = STV090x_GETFIELD_Px(reg, ERR_CNT12_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT11); ++ m = STV090x_GETFIELD_Px(reg, ERR_CNT11_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT10); ++ l = STV090x_GETFIELD_Px(reg, ERR_CNT10_FIELD); ++ ++ *ber = ((h << 16) | (m << 8) | l); ++ ++ return 0; ++} + + static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) + { +@@ -3732,6 +3754,26 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) + return 0; + } + ++static int stv090x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct stv090x_state *state = fe->demodulator_priv; ++ u32 reg, h, m, l; ++ ++ /* Counter 2: 0xc1 TS error count */ ++ reg = STV090x_READ_DEMOD(state, ERRCNT22); ++ h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT21); ++ m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); ++ ++ reg = STV090x_READ_DEMOD(state, ERRCNT20); ++ l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); ++ ++ *ucblocks = ((h << 16) | (m << 8) | l); ++ ++ return 0; ++} ++ + static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) + { + struct stv090x_state *state = fe->demodulator_priv; +@@ -4914,9 +4956,10 @@ static struct dvb_frontend_ops stv090x_ops = { + + .search = stv090x_search, + .read_status = stv090x_read_status, +- .read_ber = stv090x_read_per, ++ .read_ber = stv090x_read_ber, + .read_signal_strength = stv090x_read_signal_strength, + .read_snr = stv090x_read_cnr, ++ .read_ucblocks = stv090x_read_ucblocks, + }; + + +diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c +new file mode 100644 +index 0000000..d247932 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910.c +@@ -0,0 +1,1371 @@ ++/* ++ * Driver for the ST STV0910 DVB-S/S2 demodulator. ++ * ++ * Copyright (C) 2014 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "stv0910.h" ++#include "stv0910_regs.h" ++ ++ ++#define TUNING_DELAY 200 ++#define BER_SRC_S 0x20 ++#define BER_SRC_S2 0x20 ++ ++LIST_HEAD(stvlist); ++ ++enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto }; ++ ++ ++enum DVBS2_FECType { DVBS2_64K, DVBS2_16K }; ++ ++enum DVBS2_ModCod { ++ DVBS2_DUMMY_PLF, DVBS2_QPSK_1_4, DVBS2_QPSK_1_3, DVBS2_QPSK_2_5, ++ DVBS2_QPSK_1_2, DVBS2_QPSK_3_5, DVBS2_QPSK_2_3, DVBS2_QPSK_3_4, ++ DVBS2_QPSK_4_5, DVBS2_QPSK_5_6, DVBS2_QPSK_8_9, DVBS2_QPSK_9_10, ++ DVBS2_8PSK_3_5, DVBS2_8PSK_2_3, DVBS2_8PSK_3_4, DVBS2_8PSK_5_6, ++ DVBS2_8PSK_8_9, DVBS2_8PSK_9_10, DVBS2_16APSK_2_3, DVBS2_16APSK_3_4, ++ DVBS2_16APSK_4_5, DVBS2_16APSK_5_6, DVBS2_16APSK_8_9, DVBS2_16APSK_9_10, ++ DVBS2_32APSK_3_4, DVBS2_32APSK_4_5, DVBS2_32APSK_5_6, DVBS2_32APSK_8_9, ++ DVBS2_32APSK_9_10 ++}; ++ ++enum FE_STV0910_ModCod { ++ FE_DUMMY_PLF, FE_QPSK_14, FE_QPSK_13, FE_QPSK_25, ++ FE_QPSK_12, FE_QPSK_35, FE_QPSK_23, FE_QPSK_34, ++ FE_QPSK_45, FE_QPSK_56, FE_QPSK_89, FE_QPSK_910, ++ FE_8PSK_35, FE_8PSK_23, FE_8PSK_34, FE_8PSK_56, ++ FE_8PSK_89, FE_8PSK_910, FE_16APSK_23, FE_16APSK_34, ++ FE_16APSK_45, FE_16APSK_56, FE_16APSK_89, FE_16APSK_910, ++ FE_32APSK_34, FE_32APSK_45, FE_32APSK_56, FE_32APSK_89, ++ FE_32APSK_910 ++}; ++ ++enum FE_STV0910_RollOff { FE_SAT_35, FE_SAT_25, FE_SAT_20, FE_SAT_15 }; ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++struct stv_base { ++ struct list_head stvlist; ++ ++ u8 adr; ++ struct i2c_adapter *i2c; ++ struct mutex i2c_lock; ++ struct mutex reg_lock; ++ int count; ++ ++ u32 extclk; ++ u32 mclk; ++}; ++ ++struct stv { ++ struct stv_base *base; ++ struct dvb_frontend fe; ++ int nr; ++ u16 regoff; ++ u8 i2crpt; ++ u8 tscfgh; ++ u8 tsspeed; ++ unsigned long tune_time; ++ ++ s32 SearchRange; ++ u32 Started; ++ u32 DemodLockTime; ++ enum ReceiveMode ReceiveMode; ++ u32 DemodTimeout; ++ u32 FecTimeout; ++ u32 FirstTimeLock; ++ u8 DEMOD; ++ u32 SymbolRate; ++ ++ u8 LastViterbiRate; ++ enum fe_code_rate PunctureRate; ++ enum FE_STV0910_ModCod ModCod; ++ enum DVBS2_FECType FECType; ++ u32 Pilots; ++ enum FE_STV0910_RollOff FERollOff; ++ ++ u32 LastBERNumerator; ++ u32 LastBERDenominator; ++ u8 BERScale; ++}; ++ ++struct SInitTable { ++ u16 Address; ++ u8 Data; ++}; ++ ++struct SLookupSNTable { ++ s16 SignalToNoise; ++ u16 RefValue; ++}; ++ ++static inline int i2c_write(struct i2c_adapter *adap, u8 adr, ++ u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, u16 reg, u8 val) ++{ ++ u8 msg[3] = {reg >> 8, reg & 0xff, val}; ++ ++ return i2c_write(adap, adr, msg, 3); ++} ++ ++static int write_reg(struct stv *state, u16 reg, u8 val) ++{ ++ return i2c_write_reg16(state->base->i2c, state->base->adr, reg, val); ++} ++ ++static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int read_reg(struct stv *state, u16 reg, u8 *val) ++{ ++ return i2c_read_reg16(state->base->i2c, state->base->adr, reg, val); ++} ++ ++ ++static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val, int len) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int read_regs(struct stv *state, u16 reg, u8 *val, int len) ++{ ++ return i2c_read_regs16(state->base->i2c, state->base->adr, ++ reg, val, len); ++} ++ ++struct SLookupSNTable S1_SN_Lookup[] = { ++ { 0, 9242 }, /*C/N= 0dB*/ ++ { 05, 9105 }, /*C/N=0.5dB*/ ++ { 10, 8950 }, /*C/N=1.0dB*/ ++ { 15, 8780 }, /*C/N=1.5dB*/ ++ { 20, 8566 }, /*C/N=2.0dB*/ ++ { 25, 8366 }, /*C/N=2.5dB*/ ++ { 30, 8146 }, /*C/N=3.0dB*/ ++ { 35, 7908 }, /*C/N=3.5dB*/ ++ { 40, 7666 }, /*C/N=4.0dB*/ ++ { 45, 7405 }, /*C/N=4.5dB*/ ++ { 50, 7136 }, /*C/N=5.0dB*/ ++ { 55, 6861 }, /*C/N=5.5dB*/ ++ { 60, 6576 }, /*C/N=6.0dB*/ ++ { 65, 6330 }, /*C/N=6.5dB*/ ++ { 70, 6048 }, /*C/N=7.0dB*/ ++ { 75, 5768 }, /*C/N=7.5dB*/ ++ { 80, 5492 }, /*C/N=8.0dB*/ ++ { 85, 5224 }, /*C/N=8.5dB*/ ++ { 90, 4959 }, /*C/N=9.0dB*/ ++ { 95, 4709 }, /*C/N=9.5dB*/ ++ { 100, 4467 }, /*C/N=10.0dB*/ ++ { 105, 4236 }, /*C/N=10.5dB*/ ++ { 110, 4013 }, /*C/N=11.0dB*/ ++ { 115, 3800 }, /*C/N=11.5dB*/ ++ { 120, 3598 }, /*C/N=12.0dB*/ ++ { 125, 3406 }, /*C/N=12.5dB*/ ++ { 130, 3225 }, /*C/N=13.0dB*/ ++ { 135, 3052 }, /*C/N=13.5dB*/ ++ { 140, 2889 }, /*C/N=14.0dB*/ ++ { 145, 2733 }, /*C/N=14.5dB*/ ++ { 150, 2587 }, /*C/N=15.0dB*/ ++ { 160, 2318 }, /*C/N=16.0dB*/ ++ { 170, 2077 }, /*C/N=17.0dB*/ ++ { 180, 1862 }, /*C/N=18.0dB*/ ++ { 190, 1670 }, /*C/N=19.0dB*/ ++ { 200, 1499 }, /*C/N=20.0dB*/ ++ { 210, 1347 }, /*C/N=21.0dB*/ ++ { 220, 1213 }, /*C/N=22.0dB*/ ++ { 230, 1095 }, /*C/N=23.0dB*/ ++ { 240, 992 }, /*C/N=24.0dB*/ ++ { 250, 900 }, /*C/N=25.0dB*/ ++ { 260, 826 }, /*C/N=26.0dB*/ ++ { 270, 758 }, /*C/N=27.0dB*/ ++ { 280, 702 }, /*C/N=28.0dB*/ ++ { 290, 653 }, /*C/N=29.0dB*/ ++ { 300, 613 }, /*C/N=30.0dB*/ ++ { 310, 579 }, /*C/N=31.0dB*/ ++ { 320, 550 }, /*C/N=32.0dB*/ ++ { 330, 526 }, /*C/N=33.0dB*/ ++ { 350, 490 }, /*C/N=33.0dB*/ ++ { 400, 445 }, /*C/N=40.0dB*/ ++ { 450, 430 }, /*C/N=45.0dB*/ ++ { 500, 426 }, /*C/N=50.0dB*/ ++ { 510, 425 } /*C/N=51.0dB*/ ++}; ++ ++struct SLookupSNTable S2_SN_Lookup[] = { ++ { -30, 13950 }, /*C/N=-2.5dB*/ ++ { -25, 13580 }, /*C/N=-2.5dB*/ ++ { -20, 13150 }, /*C/N=-2.0dB*/ ++ { -15, 12760 }, /*C/N=-1.5dB*/ ++ { -10, 12345 }, /*C/N=-1.0dB*/ ++ { -05, 11900 }, /*C/N=-0.5dB*/ ++ { 0, 11520 }, /*C/N= 0dB*/ ++ { 05, 11080 }, /*C/N= 0.5dB*/ ++ { 10, 10630 }, /*C/N= 1.0dB*/ ++ { 15, 10210 }, /*C/N= 1.5dB*/ ++ { 20, 9790 }, /*C/N= 2.0dB*/ ++ { 25, 9390 }, /*C/N= 2.5dB*/ ++ { 30, 8970 }, /*C/N= 3.0dB*/ ++ { 35, 8575 }, /*C/N= 3.5dB*/ ++ { 40, 8180 }, /*C/N= 4.0dB*/ ++ { 45, 7800 }, /*C/N= 4.5dB*/ ++ { 50, 7430 }, /*C/N= 5.0dB*/ ++ { 55, 7080 }, /*C/N= 5.5dB*/ ++ { 60, 6720 }, /*C/N= 6.0dB*/ ++ { 65, 6320 }, /*C/N= 6.5dB*/ ++ { 70, 6060 }, /*C/N= 7.0dB*/ ++ { 75, 5760 }, /*C/N= 7.5dB*/ ++ { 80, 5480 }, /*C/N= 8.0dB*/ ++ { 85, 5200 }, /*C/N= 8.5dB*/ ++ { 90, 4930 }, /*C/N= 9.0dB*/ ++ { 95, 4680 }, /*C/N= 9.5dB*/ ++ { 100, 4425 }, /*C/N=10.0dB*/ ++ { 105, 4210 }, /*C/N=10.5dB*/ ++ { 110, 3980 }, /*C/N=11.0dB*/ ++ { 115, 3765 }, /*C/N=11.5dB*/ ++ { 120, 3570 }, /*C/N=12.0dB*/ ++ { 125, 3315 }, /*C/N=12.5dB*/ ++ { 130, 3140 }, /*C/N=13.0dB*/ ++ { 135, 2980 }, /*C/N=13.5dB*/ ++ { 140, 2820 }, /*C/N=14.0dB*/ ++ { 145, 2670 }, /*C/N=14.5dB*/ ++ { 150, 2535 }, /*C/N=15.0dB*/ ++ { 160, 2270 }, /*C/N=16.0dB*/ ++ { 170, 2035 }, /*C/N=17.0dB*/ ++ { 180, 1825 }, /*C/N=18.0dB*/ ++ { 190, 1650 }, /*C/N=19.0dB*/ ++ { 200, 1485 }, /*C/N=20.0dB*/ ++ { 210, 1340 }, /*C/N=21.0dB*/ ++ { 220, 1212 }, /*C/N=22.0dB*/ ++ { 230, 1100 }, /*C/N=23.0dB*/ ++ { 240, 1000 }, /*C/N=24.0dB*/ ++ { 250, 910 }, /*C/N=25.0dB*/ ++ { 260, 836 }, /*C/N=26.0dB*/ ++ { 270, 772 }, /*C/N=27.0dB*/ ++ { 280, 718 }, /*C/N=28.0dB*/ ++ { 290, 671 }, /*C/N=29.0dB*/ ++ { 300, 635 }, /*C/N=30.0dB*/ ++ { 310, 602 }, /*C/N=31.0dB*/ ++ { 320, 575 }, /*C/N=32.0dB*/ ++ { 330, 550 }, /*C/N=33.0dB*/ ++ { 350, 517 }, /*C/N=35.0dB*/ ++ { 400, 480 }, /*C/N=40.0dB*/ ++ { 450, 466 }, /*C/N=45.0dB*/ ++ { 500, 464 }, /*C/N=50.0dB*/ ++ { 510, 463 }, /*C/N=51.0dB*/ ++}; ++ ++/********************************************************************* ++Tracking carrier loop carrier QPSK 1/4 to 8PSK 9/10 long Frame ++*********************************************************************/ ++static u8 S2CarLoop[] = { ++ /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff ++ 20MPon 20MPoff 30MPon 30MPoff*/ ++ /* FE_QPSK_14 */ ++ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, ++ /* FE_QPSK_13 */ ++ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, ++ /* FE_QPSK_25 */ ++ 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, ++ /* FE_QPSK_12 */ ++ 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_35 */ ++ 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_23 */ ++ 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, ++ /* FE_QPSK_34 */ ++ 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, ++ /* FE_QPSK_45 */ ++ 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, ++ /* FE_QPSK_56 */ ++ 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, ++ /* FE_QPSK_89 */ ++ 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, ++ /* FE_QPSK_910 */ ++ 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, ++ /* FE_8PSK_35 */ ++ 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, ++ /* FE_8PSK_23 */ ++ 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, ++ /* FE_8PSK_34 */ ++ 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, ++ /* FE_8PSK_56 */ ++ 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, ++ /* FE_8PSK_89 */ ++ 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, ++ /* FE_8PSK_910 */ ++ 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, ++ ++ /********************************************************************** ++ Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame ++ **********************************************************************/ ++ /*Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon ++ 20MPoff 30MPon 30MPoff*/ ++ /* FE_16APSK_23 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, ++ /* FE_16APSK_34 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, ++ /* FE_16APSK_45 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, ++ /* FE_16APSK_56 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, ++ /* FE_16APSK_89 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, ++ /* FE_16APSK_910 */ ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, ++ /* FE_32APSK_34 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_45 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_56 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_89 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++ /* FE_32APSK_910 */ ++ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, ++}; ++ ++static u8 get_optim_cloop(struct stv *state, ++ enum FE_STV0910_ModCod ModCod, u32 Pilots) ++{ ++ int i = 0; ++ if (ModCod >= FE_32APSK_910) ++ i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; ++ else if (ModCod >= FE_QPSK_14) ++ i = ((int)ModCod - (int)FE_QPSK_14) * 10; ++ ++ if (state->SymbolRate <= 3000000) ++ i += 0; ++ else if (state->SymbolRate <= 7000000) ++ i += 2; ++ else if (state->SymbolRate <= 15000000) ++ i += 4; ++ else if (state->SymbolRate <= 25000000) ++ i += 6; ++ else ++ i += 8; ++ ++ if (!Pilots) ++ i += 1; ++ ++ return S2CarLoop[i]; ++} ++ ++static int GetCurSymbolRate(struct stv *state, u32 *pSymbolRate) ++{ ++ int status = 0; ++ u8 SymbFreq0; ++ u8 SymbFreq1; ++ u8 SymbFreq2; ++ u8 SymbFreq3; ++ u8 TimOffs0; ++ u8 TimOffs1; ++ u8 TimOffs2; ++ u32 SymbolRate; ++ s32 TimingOffset; ++ ++ *pSymbolRate = 0; ++ if (!state->Started) ++ return status; ++ ++ read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &SymbFreq3); ++ read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &SymbFreq2); ++ read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &SymbFreq1); ++ read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &SymbFreq0); ++ read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &TimOffs2); ++ read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &TimOffs1); ++ read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &TimOffs0); ++ ++ SymbolRate = ((u32) SymbFreq3 << 24) | ((u32) SymbFreq2 << 16) | ++ ((u32) SymbFreq1 << 8) | (u32) SymbFreq0; ++ TimingOffset = ((u32) TimOffs2 << 16) | ((u32) TimOffs1 << 8) | ++ (u32) TimOffs0; ++ ++ if ((TimingOffset & (1<<23)) != 0) ++ TimingOffset |= 0xFF000000; /* Sign extent */ ++ ++ SymbolRate = (u32) (((u64) SymbolRate * state->base->mclk) >> 32); ++ TimingOffset = (s32) (((s64) SymbolRate * (s64) TimingOffset) >> 29); ++ ++ *pSymbolRate = SymbolRate + TimingOffset; ++ ++ return 0; ++} ++ ++static int GetSignalParameters(struct stv *state) ++{ ++ if (!state->Started) ++ return -1; ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ u8 tmp; ++ u8 rolloff; ++ ++ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); ++ state->ModCod = (enum FE_STV0910_ModCod) ((tmp & 0x7c) >> 2); ++ state->Pilots = (tmp & 0x01) != 0; ++ state->FECType = (enum DVBS2_FECType) ((tmp & 0x02) >> 1); ++ ++ read_reg(state, RSTV0910_P2_TMGOBS + state->regoff, &rolloff); ++ rolloff = rolloff >> 6; ++ state->FERollOff = (enum FE_STV0910_RollOff) rolloff; ++ ++ } else if (state->ReceiveMode == Mode_DVBS) { ++ /* todo */ ++ } ++ return 0; ++} ++ ++static int TrackingOptimization(struct stv *state) ++{ ++ u32 SymbolRate = 0; ++ u8 tmp; ++ ++ GetCurSymbolRate(state, &SymbolRate); ++ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); ++ tmp &= ~0xC0; ++ ++ switch (state->ReceiveMode) { ++ case Mode_DVBS: ++ tmp |= 0x40; break; ++ case Mode_DVBS2: ++ tmp |= 0x80; break; ++ default: ++ tmp |= 0xC0; break; ++ } ++ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ /* force to PRE BCH Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S2 | state->BERScale); ++ ++ if (state->FECType == DVBS2_64K) { ++ u8 aclc = get_optim_cloop(state, state->ModCod, ++ state->Pilots); ++ ++ if (state->ModCod <= FE_QPSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_8PSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S28 + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_16APSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S216A + ++ state->regoff, aclc); ++ } else if (state->ModCod <= FE_32APSK_910) { ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + ++ state->regoff, 0x2a); ++ write_reg(state, RSTV0910_P2_ACLC2S232A + ++ state->regoff, aclc); ++ } ++ } ++ } ++ if (state->ReceiveMode == Mode_DVBS) { ++ u8 tmp; ++ ++ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); ++ state->PunctureRate = FEC_NONE; ++ switch (tmp & 0x1F) { ++ case 0x0d: ++ state->PunctureRate = FEC_1_2; ++ break; ++ case 0x12: ++ state->PunctureRate = FEC_2_3; ++ break; ++ case 0x15: ++ state->PunctureRate = FEC_3_4; ++ break; ++ case 0x18: ++ state->PunctureRate = FEC_5_6; ++ break; ++ case 0x1A: ++ state->PunctureRate = FEC_7_8; ++ break; ++ } ++ } ++ return 0; ++} ++ ++static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise) ++{ ++ int i; ++ u8 Data0; ++ u8 Data1; ++ u16 Data; ++ int nLookup; ++ struct SLookupSNTable *Lookup; ++ ++ *SignalToNoise = 0; ++ ++ if (!state->Started) ++ return 0; ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, &Data1); ++ read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, &Data0); ++ nLookup = ARRAY_SIZE(S2_SN_Lookup); ++ Lookup = S2_SN_Lookup; ++ } else { ++ read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, &Data1); ++ read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, &Data0); ++ nLookup = ARRAY_SIZE(S1_SN_Lookup); ++ Lookup = S1_SN_Lookup; ++ } ++ Data = (((u16)Data1) << 8) | (u16) Data0; ++ if (Data > Lookup[0].RefValue) { ++ *SignalToNoise = Lookup[0].SignalToNoise; ++ } else if (Data <= Lookup[nLookup-1].RefValue) { ++ *SignalToNoise = Lookup[nLookup-1].SignalToNoise; ++ } else { ++ for (i = 0; i < nLookup - 1; i += 1) { ++ if (Data <= Lookup[i].RefValue && ++ Data > Lookup[i+1].RefValue) { ++ *SignalToNoise = ++ (s32)(Lookup[i].SignalToNoise) + ++ ((s32)(Data - Lookup[i].RefValue) * ++ (s32)(Lookup[i+1].SignalToNoise - ++ Lookup[i].SignalToNoise)) / ++ ((s32)(Lookup[i+1].RefValue) - ++ (s32)(Lookup[i].RefValue)); ++ break; ++ } ++ } ++ } ++ return 0; ++} ++ ++static int GetBitErrorRateS(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ u8 Regs[3]; ++ ++ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, ++ Regs, 3); ++ ++ if (status) ++ return -1; ++ ++ if ((Regs[0] & 0x80) == 0) { ++ state->LastBERDenominator = 1 << ((state->BERScale * 2) + ++ 10 + 3); ++ state->LastBERNumerator = ((u32) (Regs[0] & 0x7F) << 16) | ++ ((u32) Regs[1] << 8) | Regs[2]; ++ if (state->LastBERNumerator < 256 && state->BERScale < 6) { ++ state->BERScale += 1; ++ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + ++ state->regoff, ++ 0x20 | state->BERScale); ++ } else if (state->LastBERNumerator > 1024 && ++ state->BERScale > 2) { ++ state->BERScale -= 1; ++ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + ++ state->regoff, 0x20 | ++ state->BERScale); ++ } ++ } ++ *BERNumerator = state->LastBERNumerator; ++ *BERDenominator = state->LastBERDenominator; ++ return 0; ++} ++ ++static u32 DVBS2_nBCH(enum DVBS2_ModCod ModCod, enum DVBS2_FECType FECType) ++{ ++ static u32 nBCH[][2] = { ++ {16200, 3240}, /* QPSK_1_4, */ ++ {21600, 5400}, /* QPSK_1_3, */ ++ {25920, 6480}, /* QPSK_2_5, */ ++ {32400, 7200}, /* QPSK_1_2, */ ++ {38880, 9720}, /* QPSK_3_5, */ ++ {43200, 10800}, /* QPSK_2_3, */ ++ {48600, 11880}, /* QPSK_3_4, */ ++ {51840, 12600}, /* QPSK_4_5, */ ++ {54000, 13320}, /* QPSK_5_6, */ ++ {57600, 14400}, /* QPSK_8_9, */ ++ {58320, 16000}, /* QPSK_9_10, */ ++ {43200, 9720}, /* 8PSK_3_5, */ ++ {48600, 10800}, /* 8PSK_2_3, */ ++ {51840, 11880}, /* 8PSK_3_4, */ ++ {54000, 13320}, /* 8PSK_5_6, */ ++ {57600, 14400}, /* 8PSK_8_9, */ ++ {58320, 16000}, /* 8PSK_9_10, */ ++ {43200, 10800}, /* 16APSK_2_3, */ ++ {48600, 11880}, /* 16APSK_3_4, */ ++ {51840, 12600}, /* 16APSK_4_5, */ ++ {54000, 13320}, /* 16APSK_5_6, */ ++ {57600, 14400}, /* 16APSK_8_9, */ ++ {58320, 16000}, /* 16APSK_9_10 */ ++ {48600, 11880}, /* 32APSK_3_4, */ ++ {51840, 12600}, /* 32APSK_4_5, */ ++ {54000, 13320}, /* 32APSK_5_6, */ ++ {57600, 14400}, /* 32APSK_8_9, */ ++ {58320, 16000}, /* 32APSK_9_10 */ ++ }; ++ ++ if (ModCod >= DVBS2_QPSK_1_4 && ++ ModCod <= DVBS2_32APSK_9_10 && FECType <= DVBS2_16K) ++ return nBCH[FECType][ModCod]; ++ return 64800; ++} ++ ++static int GetBitErrorRateS2(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ u8 Regs[3]; ++ ++ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, ++ Regs, 3); ++ ++ if (status) ++ return -1; ++ ++ if ((Regs[0] & 0x80) == 0) { ++ state->LastBERDenominator = ++ DVBS2_nBCH((enum DVBS2_ModCod) state->ModCod, ++ state->FECType) << ++ (state->BERScale * 2); ++ state->LastBERNumerator = (((u32) Regs[0] & 0x7F) << 16) | ++ ((u32) Regs[1] << 8) | Regs[2]; ++ if (state->LastBERNumerator < 256 && state->BERScale < 6) { ++ state->BERScale += 1; ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ 0x20 | state->BERScale); ++ } else if (state->LastBERNumerator > 1024 && ++ state->BERScale > 2) { ++ state->BERScale -= 1; ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ 0x20 | state->BERScale); ++ } ++ } ++ *BERNumerator = state->LastBERNumerator; ++ *BERDenominator = state->LastBERDenominator; ++ return status; ++} ++ ++static int GetBitErrorRate(struct stv *state, u32 *BERNumerator, ++ u32 *BERDenominator) ++{ ++ *BERNumerator = 0; ++ *BERDenominator = 1; ++ ++ switch (state->ReceiveMode) { ++ case Mode_DVBS: ++ return GetBitErrorRateS(state, BERNumerator, BERDenominator); ++ break; ++ case Mode_DVBS2: ++ return GetBitErrorRateS2(state, BERNumerator, BERDenominator); ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++ ++static int set_mclock(struct stv *state, u32 MasterClock) ++{ ++ u32 idf = 1; ++ u32 odf = 4; ++ u32 quartz = state->base->extclk / 1000000; ++ u32 Fphi = MasterClock / 1000000; ++ u32 ndiv = (Fphi * odf * idf) / quartz; ++ u32 cp = 7; ++ u32 fvco; ++ ++ if (ndiv >= 7 && ndiv <= 71) ++ cp = 7; ++ else if (ndiv >= 72 && ndiv <= 79) ++ cp = 8; ++ else if (ndiv >= 80 && ndiv <= 87) ++ cp = 9; ++ else if (ndiv >= 88 && ndiv <= 95) ++ cp = 10; ++ else if (ndiv >= 96 && ndiv <= 103) ++ cp = 11; ++ else if (ndiv >= 104 && ndiv <= 111) ++ cp = 12; ++ else if (ndiv >= 112 && ndiv <= 119) ++ cp = 13; ++ else if (ndiv >= 120 && ndiv <= 127) ++ cp = 14; ++ else if (ndiv >= 128 && ndiv <= 135) ++ cp = 15; ++ else if (ndiv >= 136 && ndiv <= 143) ++ cp = 16; ++ else if (ndiv >= 144 && ndiv <= 151) ++ cp = 17; ++ else if (ndiv >= 152 && ndiv <= 159) ++ cp = 18; ++ else if (ndiv >= 160 && ndiv <= 167) ++ cp = 19; ++ else if (ndiv >= 168 && ndiv <= 175) ++ cp = 20; ++ else if (ndiv >= 176 && ndiv <= 183) ++ cp = 21; ++ else if (ndiv >= 184 && ndiv <= 191) ++ cp = 22; ++ else if (ndiv >= 192 && ndiv <= 199) ++ cp = 23; ++ else if (ndiv >= 200 && ndiv <= 207) ++ cp = 24; ++ else if (ndiv >= 208 && ndiv <= 215) ++ cp = 25; ++ else if (ndiv >= 216 && ndiv <= 223) ++ cp = 26; ++ else if (ndiv >= 224 && ndiv <= 225) ++ cp = 27; ++ ++ write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); ++ write_reg(state, RSTV0910_NCOARSE2, odf); ++ write_reg(state, RSTV0910_NCOARSE1, ndiv); ++ ++ fvco = (quartz * 2 * ndiv) / idf; ++ state->base->mclk = fvco / (2 * odf) * 1000000; ++ ++ pr_info("ndiv = %d, MasterClock = %d\n", ndiv, state->base->mclk); ++ return 0; ++} ++ ++static int Stop(struct stv *state) ++{ ++ if (state->Started) { ++ u8 tmp; ++ ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh | 0x01); ++ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); ++ tmp &= ~0x01; /*release reset DVBS2 packet delin*/ ++ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); ++ /* Blind optim*/ ++ write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); ++ /* Stop the demod */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); ++ state->Started = 0; ++ } ++ state->ReceiveMode = Mode_None; ++ return 0; ++} ++ ++ ++static int Start(struct stv *state, struct dtv_frontend_properties *p) ++{ ++ s32 Freq; ++ u8 regDMDCFGMD; ++ u16 symb; ++ ++ if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) ++ return -EINVAL; ++ ++ state->ReceiveMode = Mode_None; ++ state->DemodLockTime = 0; ++ ++ /* Demod Stop*/ ++ if (state->Started) ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); ++ ++ if (p->symbol_rate <= 1000000) { /*SR <=1Msps*/ ++ state->DemodTimeout = 3000; ++ state->FecTimeout = 2000; ++ } else if (p->symbol_rate <= 2000000) { /*1Msps < SR <=2Msps*/ ++ state->DemodTimeout = 2500; ++ state->FecTimeout = 1300; ++ } else if (p->symbol_rate <= 5000000) { /*2Msps< SR <=5Msps*/ ++ state->DemodTimeout = 1000; ++ state->FecTimeout = 650; ++ } else if (p->symbol_rate <= 10000000) { /*5Msps< SR <=10Msps*/ ++ state->DemodTimeout = 700; ++ state->FecTimeout = 350; ++ } else if (p->symbol_rate < 20000000) { /*10Msps< SR <=20Msps*/ ++ state->DemodTimeout = 400; ++ state->FecTimeout = 200; ++ } else { /*SR >=20Msps*/ ++ state->DemodTimeout = 300; ++ state->FecTimeout = 200; ++ } ++ ++ /* Set the Init Symbol rate*/ ++ symb = MulDiv32(p->symbol_rate, 65536, state->base->mclk); ++ write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, ++ ((symb >> 8) & 0x7F)); ++ write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); ++ ++ pr_info("symb = %u\n", symb); ++ ++ state->DEMOD |= 0x80; ++ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->DEMOD); ++ ++ /* FE_STV0910_SetSearchStandard */ ++ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®DMDCFGMD); ++ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ++ regDMDCFGMD |= 0xC0); ++ ++ /* Disable DSS */ ++ write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); ++ write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); ++ ++ /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/ ++ write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); ++ write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); ++ write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); ++ write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); ++ write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); ++ /* Reset demod */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); ++ ++ write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); ++ ++ Freq = (state->SearchRange / 2000) + 600; ++ if (p->symbol_rate <= 5000000) ++ Freq -= (600 + 80); ++ Freq = (Freq << 16) / (state->base->mclk / 1000); ++ ++ write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, ++ (Freq >> 8) & 0xff); ++ write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (Freq & 0xff)); ++ /*CFR Low Setting*/ ++ Freq = -Freq; ++ write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, ++ (Freq >> 8) & 0xff); ++ write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (Freq & 0xff)); ++ ++ /* init the demod frequency offset to 0 */ ++ write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); ++ write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); ++ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); ++ /* Trigger acq */ ++ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); ++ ++ state->DemodLockTime += TUNING_DELAY; ++ state->Started = 1; ++ ++ return 0; ++} ++ ++static int init_diseqc(struct stv *state) ++{ ++ u16 offs = state->nr ? 0x40 : 0; /* Address offset */ ++ u8 Freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); ++ ++ /* Disable receiver */ ++ write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ ++ write_reg(state, RSTV0910_P1_DISTXF22 + offs, Freq); ++ return 0; ++} ++ ++static int probe(struct stv *state) ++{ ++ u8 id; ++ ++ state->ReceiveMode = Mode_None; ++ state->Started = 0; ++ ++ if (read_reg(state, RSTV0910_MID, &id) < 0) ++ return -1; ++ ++ if (id != 0x51) ++ return -EINVAL; ++ pr_info("Found STV0910 id=0x%02x\n", id); ++ ++ /* Configure the I2C repeater to off */ ++ write_reg(state, RSTV0910_P1_I2CRPT, 0x24); ++ /* Configure the I2C repeater to off */ ++ write_reg(state, RSTV0910_P2_I2CRPT, 0x24); ++ /* Set the I2C to oversampling ratio */ ++ write_reg(state, RSTV0910_I2CCFG, 0x88); ++ ++ write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ ++ write_reg(state, RSTV0910_PADCFG, 0x05); /* RF AGC Pads Dev = 05 */ ++ write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ ++ write_reg(state, RSTV0910_TSGENERAL, 0x00); /* TSGENERAL */ ++ write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ ++ write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ ++ ++ ++ write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ ++ write_reg(state, RSTV0910_TSTRES0, 0x00); ++ ++ set_mclock(state, 135000000); ++ ++ /* TS output */ ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P1_TSCFGM , 0xC0); /* Manual speed */ ++ write_reg(state, RSTV0910_P1_TSCFGL , 0x20); ++ ++ /* Speed = 67.5 MHz */ ++ write_reg(state, RSTV0910_P1_TSSPEED , state->tsspeed); ++ ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P2_TSCFGM , 0xC0); /* Manual speed */ ++ write_reg(state, RSTV0910_P2_TSCFGL , 0x20); ++ ++ /* Speed = 67.5 MHz */ ++ write_reg(state, RSTV0910_P2_TSSPEED , state->tsspeed); ++ ++ /* Reset stream merger */ ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); ++ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); ++ ++ write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); ++ write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); ++ ++ init_diseqc(state); ++ return 0; ++} ++ ++ ++static int gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u8 i2crpt = state->i2crpt & ~0x86; ++ ++ if (enable) ++ mutex_lock(&state->base->i2c_lock); ++ ++ if (enable) ++ i2crpt |= 0x80; ++ else ++ i2crpt |= 0x02; ++ ++ if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : ++ RSTV0910_P1_I2CRPT, i2crpt) < 0) ++ return -EIO; ++ ++ state->i2crpt = i2crpt; ++ ++ if (!enable) ++ mutex_unlock(&state->base->i2c_lock); ++ return 0; ++} ++ ++static void release(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->demodulator_priv; ++ ++ state->base->count--; ++ if (state->base->count == 0) { ++ pr_info("remove STV base\n"); ++ list_del(&state->base->stvlist); ++ kfree(state->base); ++ } ++ kfree(state); ++} ++ ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ int stat = 0; ++ struct stv *state = fe->demodulator_priv; ++ u32 IF; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ ++ Stop(state); ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ if (fe->ops.tuner_ops.get_if_frequency) ++ fe->ops.tuner_ops.get_if_frequency(fe, &IF); ++ state->SymbolRate = p->symbol_rate; ++ stat = Start(state, p); ++ return stat; ++} ++ ++ ++static int read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u8 DmdState = 0; ++ u8 DStatus = 0; ++ enum ReceiveMode CurReceiveMode = Mode_None; ++ u32 FECLock = 0; ++ ++ read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState); ++ ++ if (DmdState & 0x40) { ++ read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &DStatus); ++ if (DStatus & 0x08) ++ CurReceiveMode = (DmdState & 0x20) ? ++ Mode_DVBS : Mode_DVBS2; ++ } ++ if (CurReceiveMode == Mode_None) { ++ *status = 0; ++ return 0; ++ } ++ ++ *status |= 0x0f; ++ if (state->ReceiveMode == Mode_None) { ++ state->ReceiveMode = CurReceiveMode; ++ state->DemodLockTime = jiffies; ++ state->FirstTimeLock = 0; ++ ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh); ++ usleep_range(3000, 4000); ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh | 0x01); ++ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, ++ state->tscfgh); ++ } ++ if (DmdState & 0x40) { ++ if (state->ReceiveMode == Mode_DVBS2) { ++ u8 PDELStatus; ++ read_reg(state, ++ RSTV0910_P2_PDELSTATUS1 + state->regoff, ++ &PDELStatus); ++ FECLock = (PDELStatus & 0x02) != 0; ++ } else { ++ u8 VStatus; ++ read_reg(state, ++ RSTV0910_P2_VSTATUSVIT + state->regoff, ++ &VStatus); ++ FECLock = (VStatus & 0x08) != 0; ++ } ++ } ++ ++ if (!FECLock) ++ return 0; ++ ++ *status |= 0x10; ++ ++ if (state->FirstTimeLock) { ++ u8 tmp; ++ ++ state->FirstTimeLock = 0; ++ GetSignalParameters(state); ++ ++ if (state->ReceiveMode == Mode_DVBS2) { ++ /* FSTV0910_P2_MANUALSX_ROLLOFF, ++ FSTV0910_P2_MANUALS2_ROLLOFF = 0 */ ++ state->DEMOD &= ~0x84; ++ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, ++ state->DEMOD); ++ read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ &tmp); ++ /*reset DVBS2 packet delinator error counter */ ++ tmp |= 0x40; ++ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ tmp); ++ /*reset DVBS2 packet delinator error counter */ ++ tmp &= ~0x40; ++ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, ++ tmp); ++ ++ state->BERScale = 2; ++ state->LastBERNumerator = 0; ++ state->LastBERDenominator = 1; ++ /* force to PRE BCH Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S2 | state->BERScale); ++ } else { ++ state->BERScale = 2; ++ state->LastBERNumerator = 0; ++ state->LastBERDenominator = 1; ++ /* force to PRE RS Rate */ ++ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, ++ BER_SRC_S | state->BERScale); ++ } ++ /*Reset the Total packet counter */ ++ write_reg(state, RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); ++ /*Reset the packet Error counter2 (and Set it to ++ infinit error count mode )*/ ++ write_reg(state, RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); ++ ++ TrackingOptimization(state); ++ } ++ return 0; ++} ++ ++static int tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, fe_status_t *status) ++{ ++ struct stv *state = fe->demodulator_priv; ++ int r; ++ ++ if (re_tune) { ++ r = set_parameters(fe); ++ if (r) ++ return r; ++ state->tune_time = jiffies; ++ } ++ if (*status & FE_HAS_LOCK) ++ return 0; ++ *delay = HZ; ++ ++ r = read_status(fe, status); ++ if (r) ++ return r; ++ return 0; ++} ++ ++ ++static int get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++static int set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u16 offs = state->nr ? 0x40 : 0; ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x38); ++ break; ++ case SEC_TONE_OFF: ++ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3a); ++ break; ++ default: ++ break; ++ } ++ return -EINVAL; ++} ++ ++static int send_master_cmd(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *cmd) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u16 offs = state->nr ? 0x40 : 0; ++ int i; ++ ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); ++ for (i = 0; i < cmd->msg_len; i++) ++ write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); ++ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); ++ return 0; ++} ++ ++static int recv_slave_reply(struct dvb_frontend *fe, ++ struct dvb_diseqc_slave_reply *reply) ++{ ++ return 0; ++} ++ ++static int send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) ++{ ++ return 0; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->demodulator_priv; ++ ++ pr_info("sleep %d\n", state->nr); ++ Stop(state); ++ return 0; ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct stv *state = fe->demodulator_priv; ++ s32 SNR; ++ ++ *snr = 0; ++ if (GetSignalToNoise(state, &SNR)) ++ return -EIO; ++ *snr = SNR; ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u32 n, d; ++ ++ GetBitErrorRate(state, &n, &d); ++ if (d) ++ *ber = n / d; ++ else ++ *ber = 0; ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct stv *state = fe->demodulator_priv; ++ u8 Agc1, Agc0; ++ ++ read_reg(state, RSTV0910_P2_AGCIQIN1 + state->regoff, &Agc1); ++ read_reg(state, RSTV0910_P2_AGCIQIN0 + state->regoff, &Agc0); ++ ++ *strength = ((255 - Agc1) * 3300) / 256; ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ /* struct stv *state = fe->demodulator_priv; */ ++ ++ ++ return 0; ++} ++ ++static struct dvb_frontend_ops stv0910_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, ++ .info = { ++ .name = "STV0910", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 0, ++ .frequency_tolerance = 0, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 70000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_2G_MODULATION ++ }, ++ .init = init, ++ .sleep = sleep, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ .get_frontend_algo = get_algo, ++ .tune = tune, ++ .read_status = read_status, ++ .set_tone = set_tone, ++ ++ .diseqc_send_master_cmd = send_master_cmd, ++ .diseqc_send_burst = send_burst, ++ .diseqc_recv_slave_reply = recv_slave_reply, ++ ++ .read_snr = read_snr, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_ucblocks = read_ucblocks, ++}; ++ ++static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) ++{ ++ struct stv_base *p; ++ ++ list_for_each_entry(p, &stvlist, stvlist) ++ if (p->i2c == i2c && p->adr == adr) ++ return p; ++ return NULL; ++} ++ ++struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, ++ int nr) ++{ ++ struct stv *state; ++ struct stv_base *base; ++ ++ state = kzalloc(sizeof(struct stv), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); ++ state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); ++ state->tsspeed = 0x40; ++ state->nr = nr; ++ state->regoff = state->nr ? 0 : 0x200; ++ state->SearchRange = 16000000; ++ state->DEMOD = 0x10; /* Inversion : Auto with reset to 0 */ ++ state->ReceiveMode = Mode_None; ++ ++ base = match_base(i2c, cfg->adr); ++ if (base) { ++ base->count++; ++ state->base = base; ++ } else { ++ base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); ++ if (!base) ++ goto fail; ++ base->i2c = i2c; ++ base->adr = cfg->adr; ++ base->count = 1; ++ base->extclk = cfg->clk ? cfg->clk : 30000000; ++ ++ mutex_init(&base->i2c_lock); ++ mutex_init(&base->reg_lock); ++ state->base = base; ++ if (probe(state) < 0) { ++ kfree(base); ++ goto fail; ++ } ++ list_add(&base->stvlist, &stvlist); ++ } ++ state->fe.ops = stv0910_ops; ++ state->fe.demodulator_priv = state; ++ state->nr = nr; ++ ++ return &state->fe; ++ ++fail: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(stv0910_attach); ++ ++MODULE_DESCRIPTION("STV0910 driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h +new file mode 100644 +index 0000000..a6fad29 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910.h +@@ -0,0 +1,31 @@ ++#ifndef _STV0910_H_ ++#define _STV0910_H_ ++ ++#include ++#include ++ ++struct stv0910_cfg { ++ u32 clk; ++ u8 adr; ++ u8 parallel; ++ u8 rptlvl; ++}; ++ ++#if defined(CONFIG_DVB_STV0910) || \ ++ (defined(CONFIG_DVB_STV0910_MODULE) && defined(MODULE)) ++ ++extern struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, int nr); ++#else ++ ++static inline struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, ++ struct stv0910_cfg *cfg, ++ int nr) ++{ ++ pr_warn("%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++#endif ++ ++#endif +diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h +new file mode 100644 +index 0000000..16e922f +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0910_regs.h +@@ -0,0 +1,3998 @@ ++// @DVB-S/DVB-S2 STMicroelectronics STV0900 register defintions ++// Author Manfred Völkel, August 2013 ++// (c) 2013 Digital Devices GmbH Germany. All rights reserved ++ ++// $Id: DD_STV0910Register.h 504 2013-09-02 23:02:14Z manfred $ ++ ++/* ======================================================================= ++-- Registers Declaration (Internal ST, All Applications ) ++-- ------------------------- ++-- Each register (RSTV0910__XXXXX) is defined by its address (2 bytes). ++-- ++-- Each field (FSTV0910__XXXXX)is defined as follow: ++-- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] ++ ======================================================================= */ ++ ++/*MID*/ ++#define RSTV0910_MID 0xf100 ++#define FSTV0910_MCHIP_IDENT 0xf10000f0 ++#define FSTV0910_MRELEASE 0xf100000f ++ ++/*DID*/ ++#define RSTV0910_DID 0xf101 ++#define FSTV0910_DEVICE_ID 0xf10100ff ++ ++/*DACR1*/ ++#define RSTV0910_DACR1 0xf113 ++#define FSTV0910_DAC_MODE 0xf11300e0 ++#define FSTV0910_DAC_VALUE1 0xf113000f ++ ++/*DACR2*/ ++#define RSTV0910_DACR2 0xf114 ++#define FSTV0910_DAC_VALUE0 0xf11400ff ++ ++/*PADCFG*/ ++#define RSTV0910_PADCFG 0xf11a ++#define FSTV0910_AGCRF2_OPD 0xf11a0008 ++#define FSTV0910_AGCRF2_XOR 0xf11a0004 ++#define FSTV0910_AGCRF1_OPD 0xf11a0002 ++#define FSTV0910_AGCRF1_XOR 0xf11a0001 ++ ++/*OUTCFG2*/ ++#define RSTV0910_OUTCFG2 0xf11b ++#define FSTV0910_TS2_ERROR_XOR 0xf11b0080 ++#define FSTV0910_TS2_DPN_XOR 0xf11b0040 ++#define FSTV0910_TS2_STROUT_XOR 0xf11b0020 ++#define FSTV0910_TS2_CLOCKOUT_XOR 0xf11b0010 ++#define FSTV0910_TS1_ERROR_XOR 0xf11b0008 ++#define FSTV0910_TS1_DPN_XOR 0xf11b0004 ++#define FSTV0910_TS1_STROUT_XOR 0xf11b0002 ++#define FSTV0910_TS1_CLOCKOUT_XOR 0xf11b0001 ++ ++/*OUTCFG*/ ++#define RSTV0910_OUTCFG 0xf11c ++#define FSTV0910_INV_DATA6 0xf11c0080 ++#define FSTV0910_TS2_OUTSER_HZ 0xf11c0020 ++#define FSTV0910_TS1_OUTSER_HZ 0xf11c0010 ++#define FSTV0910_TS2_OUTPAR_HZ 0xf11c0008 ++#define FSTV0910_TS1_OUTPAR_HZ 0xf11c0004 ++#define FSTV0910_TS_SERDATA0 0xf11c0002 ++ ++/*IRQSTATUS3*/ ++#define RSTV0910_IRQSTATUS3 0xf120 ++#define FSTV0910_SPLL_LOCK 0xf1200020 ++#define FSTV0910_SSTREAM_LCK_1 0xf1200010 ++#define FSTV0910_SSTREAM_LCK_2 0xf1200008 ++#define FSTV0910_SDVBS1_PRF_2 0xf1200002 ++#define FSTV0910_SDVBS1_PRF_1 0xf1200001 ++ ++/*IRQSTATUS2*/ ++#define RSTV0910_IRQSTATUS2 0xf121 ++#define FSTV0910_SSPY_ENDSIM_1 0xf1210080 ++#define FSTV0910_SSPY_ENDSIM_2 0xf1210040 ++#define FSTV0910_SPKTDEL_ERROR_2 0xf1210010 ++#define FSTV0910_SPKTDEL_LOCKB_2 0xf1210008 ++#define FSTV0910_SPKTDEL_LOCK_2 0xf1210004 ++#define FSTV0910_SPKTDEL_ERROR_1 0xf1210002 ++#define FSTV0910_SPKTDEL_LOCKB_1 0xf1210001 ++ ++/*IRQSTATUS1*/ ++#define RSTV0910_IRQSTATUS1 0xf122 ++#define FSTV0910_SPKTDEL_LOCK_1 0xf1220080 ++#define FSTV0910_SFEC_LOCKB_2 0xf1220040 ++#define FSTV0910_SFEC_LOCK_2 0xf1220020 ++#define FSTV0910_SFEC_LOCKB_1 0xf1220010 ++#define FSTV0910_SFEC_LOCK_1 0xf1220008 ++#define FSTV0910_SDEMOD_LOCKB_2 0xf1220004 ++#define FSTV0910_SDEMOD_LOCK_2 0xf1220002 ++#define FSTV0910_SDEMOD_IRQ_2 0xf1220001 ++ ++/*IRQSTATUS0*/ ++#define RSTV0910_IRQSTATUS0 0xf123 ++#define FSTV0910_SDEMOD_LOCKB_1 0xf1230080 ++#define FSTV0910_SDEMOD_LOCK_1 0xf1230040 ++#define FSTV0910_SDEMOD_IRQ_1 0xf1230020 ++#define FSTV0910_SBCH_ERRFLAG 0xf1230010 ++#define FSTV0910_SECW2_IRQ 0xf1230008 ++#define FSTV0910_SDISEQC2_IRQ 0xf1230004 ++#define FSTV0910_SECW1_IRQ 0xf1230002 ++#define FSTV0910_SDISEQC1_IRQ 0xf1230001 ++ ++/*IRQMASK3*/ ++#define RSTV0910_IRQMASK3 0xf124 ++#define FSTV0910_MPLL_LOCK 0xf1240020 ++#define FSTV0910_MSTREAM_LCK_1 0xf1240010 ++#define FSTV0910_MSTREAM_LCK_2 0xf1240008 ++#define FSTV0910_MDVBS1_PRF_2 0xf1240002 ++#define FSTV0910_MDVBS1_PRF_1 0xf1240001 ++ ++/*IRQMASK2*/ ++#define RSTV0910_IRQMASK2 0xf125 ++#define FSTV0910_MSPY_ENDSIM_1 0xf1250080 ++#define FSTV0910_MSPY_ENDSIM_2 0xf1250040 ++#define FSTV0910_MPKTDEL_ERROR_2 0xf1250010 ++#define FSTV0910_MPKTDEL_LOCKB_2 0xf1250008 ++#define FSTV0910_MPKTDEL_LOCK_2 0xf1250004 ++#define FSTV0910_MPKTDEL_ERROR_1 0xf1250002 ++#define FSTV0910_MPKTDEL_LOCKB_1 0xf1250001 ++ ++/*IRQMASK1*/ ++#define RSTV0910_IRQMASK1 0xf126 ++#define FSTV0910_MPKTDEL_LOCK_1 0xf1260080 ++#define FSTV0910_MFEC_LOCKB_2 0xf1260040 ++#define FSTV0910_MFEC_LOCK_2 0xf1260020 ++#define FSTV0910_MFEC_LOCKB_1 0xf1260010 ++#define FSTV0910_MFEC_LOCK_1 0xf1260008 ++#define FSTV0910_MDEMOD_LOCKB_2 0xf1260004 ++#define FSTV0910_MDEMOD_LOCK_2 0xf1260002 ++#define FSTV0910_MDEMOD_IRQ_2 0xf1260001 ++ ++/*IRQMASK0*/ ++#define RSTV0910_IRQMASK0 0xf127 ++#define FSTV0910_MDEMOD_LOCKB_1 0xf1270080 ++#define FSTV0910_MDEMOD_LOCK_1 0xf1270040 ++#define FSTV0910_MDEMOD_IRQ_1 0xf1270020 ++#define FSTV0910_MBCH_ERRFLAG 0xf1270010 ++#define FSTV0910_MECW2_IRQ 0xf1270008 ++#define FSTV0910_MDISEQC2_IRQ 0xf1270004 ++#define FSTV0910_MECW1_IRQ 0xf1270002 ++#define FSTV0910_MDISEQC1_IRQ 0xf1270001 ++ ++/*I2CCFG*/ ++#define RSTV0910_I2CCFG 0xf129 ++#define FSTV0910_I2C2_FASTMODE 0xf1290080 ++#define FSTV0910_STATUS_WR2 0xf1290040 ++#define FSTV0910_I2C2ADDR_INC 0xf1290030 ++#define FSTV0910_I2C_FASTMODE 0xf1290008 ++#define FSTV0910_STATUS_WR 0xf1290004 ++#define FSTV0910_I2CADDR_INC 0xf1290003 ++ ++/*P1_I2CRPT*/ ++#define RSTV0910_P1_I2CRPT 0xf12a ++#define FSTV0910_P1_I2CT_ON 0xf12a0080 ++#define FSTV0910_P1_ENARPT_LEVEL 0xf12a0070 ++#define FSTV0910_P1_SCLT_DELAY 0xf12a0008 ++#define FSTV0910_P1_STOP_ENABLE 0xf12a0004 ++#define FSTV0910_P1_STOP_SDAT2SDA 0xf12a0002 ++ ++/*P2_I2CRPT*/ ++#define RSTV0910_P2_I2CRPT 0xf12b ++#define FSTV0910_P2_I2CT_ON 0xf12b0080 ++#define FSTV0910_P2_ENARPT_LEVEL 0xf12b0070 ++#define FSTV0910_P2_SCLT_DELAY 0xf12b0008 ++#define FSTV0910_P2_STOP_ENABLE 0xf12b0004 ++#define FSTV0910_P2_STOP_SDAT2SDA 0xf12b0002 ++ ++/*GPIO0CFG*/ ++#define RSTV0910_GPIO0CFG 0xf140 ++#define FSTV0910_GPIO0_OPD 0xf1400080 ++#define FSTV0910_GPIO0_CONFIG 0xf140007e ++#define FSTV0910_GPIO0_XOR 0xf1400001 ++ ++/*GPIO1CFG*/ ++#define RSTV0910_GPIO1CFG 0xf141 ++#define FSTV0910_GPIO1_OPD 0xf1410080 ++#define FSTV0910_GPIO1_CONFIG 0xf141007e ++#define FSTV0910_GPIO1_XOR 0xf1410001 ++ ++/*GPIO2CFG*/ ++#define RSTV0910_GPIO2CFG 0xf142 ++#define FSTV0910_GPIO2_OPD 0xf1420080 ++#define FSTV0910_GPIO2_CONFIG 0xf142007e ++#define FSTV0910_GPIO2_XOR 0xf1420001 ++ ++/*GPIO3CFG*/ ++#define RSTV0910_GPIO3CFG 0xf143 ++#define FSTV0910_GPIO3_OPD 0xf1430080 ++#define FSTV0910_GPIO3_CONFIG 0xf143007e ++#define FSTV0910_GPIO3_XOR 0xf1430001 ++ ++/*GPIO4CFG*/ ++#define RSTV0910_GPIO4CFG 0xf144 ++#define FSTV0910_GPIO4_OPD 0xf1440080 ++#define FSTV0910_GPIO4_CONFIG 0xf144007e ++#define FSTV0910_GPIO4_XOR 0xf1440001 ++ ++/*GPIO5CFG*/ ++#define RSTV0910_GPIO5CFG 0xf145 ++#define FSTV0910_GPIO5_OPD 0xf1450080 ++#define FSTV0910_GPIO5_CONFIG 0xf145007e ++#define FSTV0910_GPIO5_XOR 0xf1450001 ++ ++/*GPIO6CFG*/ ++#define RSTV0910_GPIO6CFG 0xf146 ++#define FSTV0910_GPIO6_OPD 0xf1460080 ++#define FSTV0910_GPIO6_CONFIG 0xf146007e ++#define FSTV0910_GPIO6_XOR 0xf1460001 ++ ++/*GPIO7CFG*/ ++#define RSTV0910_GPIO7CFG 0xf147 ++#define FSTV0910_GPIO7_OPD 0xf1470080 ++#define FSTV0910_GPIO7_CONFIG 0xf147007e ++#define FSTV0910_GPIO7_XOR 0xf1470001 ++ ++/*GPIO8CFG*/ ++#define RSTV0910_GPIO8CFG 0xf148 ++#define FSTV0910_GPIO8_OPD 0xf1480080 ++#define FSTV0910_GPIO8_CONFIG 0xf148007e ++#define FSTV0910_GPIO8_XOR 0xf1480001 ++ ++/*GPIO9CFG*/ ++#define RSTV0910_GPIO9CFG 0xf149 ++#define FSTV0910_GPIO9_OPD 0xf1490080 ++#define FSTV0910_GPIO9_CONFIG 0xf149007e ++#define FSTV0910_GPIO9_XOR 0xf1490001 ++ ++/*GPIO10CFG*/ ++#define RSTV0910_GPIO10CFG 0xf14a ++#define FSTV0910_GPIO10_OPD 0xf14a0080 ++#define FSTV0910_GPIO10_CONFIG 0xf14a007e ++#define FSTV0910_GPIO10_XOR 0xf14a0001 ++ ++/*GPIO11CFG*/ ++#define RSTV0910_GPIO11CFG 0xf14b ++#define FSTV0910_GPIO11_OPD 0xf14b0080 ++#define FSTV0910_GPIO11_CONFIG 0xf14b007e ++#define FSTV0910_GPIO11_XOR 0xf14b0001 ++ ++/*GPIO12CFG*/ ++#define RSTV0910_GPIO12CFG 0xf14c ++#define FSTV0910_GPIO12_OPD 0xf14c0080 ++#define FSTV0910_GPIO12_CONFIG 0xf14c007e ++#define FSTV0910_GPIO12_XOR 0xf14c0001 ++ ++/*GPIO13CFG*/ ++#define RSTV0910_GPIO13CFG 0xf14d ++#define FSTV0910_GPIO13_OPD 0xf14d0080 ++#define FSTV0910_GPIO13_CONFIG 0xf14d007e ++#define FSTV0910_GPIO13_XOR 0xf14d0001 ++ ++/*GPIO14CFG*/ ++#define RSTV0910_GPIO14CFG 0xf14e ++#define FSTV0910_GPIO14_OPD 0xf14e0080 ++#define FSTV0910_GPIO14_CONFIG 0xf14e007e ++#define FSTV0910_GPIO14_XOR 0xf14e0001 ++ ++/*GPIO15CFG*/ ++#define RSTV0910_GPIO15CFG 0xf14f ++#define FSTV0910_GPIO15_OPD 0xf14f0080 ++#define FSTV0910_GPIO15_CONFIG 0xf14f007e ++#define FSTV0910_GPIO15_XOR 0xf14f0001 ++ ++/*GPIO16CFG*/ ++#define RSTV0910_GPIO16CFG 0xf150 ++#define FSTV0910_GPIO16_OPD 0xf1500080 ++#define FSTV0910_GPIO16_CONFIG 0xf150007e ++#define FSTV0910_GPIO16_XOR 0xf1500001 ++ ++/*GPIO17CFG*/ ++#define RSTV0910_GPIO17CFG 0xf151 ++#define FSTV0910_GPIO17_OPD 0xf1510080 ++#define FSTV0910_GPIO17_CONFIG 0xf151007e ++#define FSTV0910_GPIO17_XOR 0xf1510001 ++ ++/*GPIO18CFG*/ ++#define RSTV0910_GPIO18CFG 0xf152 ++#define FSTV0910_GPIO18_OPD 0xf1520080 ++#define FSTV0910_GPIO18_CONFIG 0xf152007e ++#define FSTV0910_GPIO18_XOR 0xf1520001 ++ ++/*GPIO19CFG*/ ++#define RSTV0910_GPIO19CFG 0xf153 ++#define FSTV0910_GPIO19_OPD 0xf1530080 ++#define FSTV0910_GPIO19_CONFIG 0xf153007e ++#define FSTV0910_GPIO19_XOR 0xf1530001 ++ ++/*GPIO20CFG*/ ++#define RSTV0910_GPIO20CFG 0xf154 ++#define FSTV0910_GPIO20_OPD 0xf1540080 ++#define FSTV0910_GPIO20_CONFIG 0xf154007e ++#define FSTV0910_GPIO20_XOR 0xf1540001 ++ ++/*GPIO21CFG*/ ++#define RSTV0910_GPIO21CFG 0xf155 ++#define FSTV0910_GPIO21_OPD 0xf1550080 ++#define FSTV0910_GPIO21_CONFIG 0xf155007e ++#define FSTV0910_GPIO21_XOR 0xf1550001 ++ ++/*GPIO22CFG*/ ++#define RSTV0910_GPIO22CFG 0xf156 ++#define FSTV0910_GPIO22_OPD 0xf1560080 ++#define FSTV0910_GPIO22_CONFIG 0xf156007e ++#define FSTV0910_GPIO22_XOR 0xf1560001 ++ ++/*STRSTATUS1*/ ++#define RSTV0910_STRSTATUS1 0xf16a ++#define FSTV0910_STRSTATUS_SEL2 0xf16a00f0 ++#define FSTV0910_STRSTATUS_SEL1 0xf16a000f ++ ++/*STRSTATUS2*/ ++#define RSTV0910_STRSTATUS2 0xf16b ++#define FSTV0910_STRSTATUS_SEL4 0xf16b00f0 ++#define FSTV0910_STRSTATUS_SEL3 0xf16b000f ++ ++/*STRSTATUS3*/ ++#define RSTV0910_STRSTATUS3 0xf16c ++#define FSTV0910_STRSTATUS_SEL6 0xf16c00f0 ++#define FSTV0910_STRSTATUS_SEL5 0xf16c000f ++ ++/*FSKTFC2*/ ++#define RSTV0910_FSKTFC2 0xf170 ++#define FSTV0910_FSKT_KMOD 0xf17000fc ++#define FSTV0910_FSKT_CAR2 0xf1700003 ++ ++/*FSKTFC1*/ ++#define RSTV0910_FSKTFC1 0xf171 ++#define FSTV0910_FSKT_CAR1 0xf17100ff ++ ++/*FSKTFC0*/ ++#define RSTV0910_FSKTFC0 0xf172 ++#define FSTV0910_FSKT_CAR0 0xf17200ff ++ ++/*FSKTDELTAF1*/ ++#define RSTV0910_FSKTDELTAF1 0xf173 ++#define FSTV0910_FSKT_DELTAF1 0xf173000f ++ ++/*FSKTDELTAF0*/ ++#define RSTV0910_FSKTDELTAF0 0xf174 ++#define FSTV0910_FSKT_DELTAF0 0xf17400ff ++ ++/*FSKTCTRL*/ ++#define RSTV0910_FSKTCTRL 0xf175 ++#define FSTV0910_FSKT_PINSEL 0xf1750080 ++#define FSTV0910_FSKT_EN_SGN 0xf1750040 ++#define FSTV0910_FSKT_MOD_SGN 0xf1750020 ++#define FSTV0910_FSKT_MOD_EN 0xf175001c ++#define FSTV0910_FSKT_DACMODE 0xf1750003 ++ ++/*FSKRFC2*/ ++#define RSTV0910_FSKRFC2 0xf176 ++#define FSTV0910_FSKR_DETSGN 0xf1760040 ++#define FSTV0910_FSKR_OUTSGN 0xf1760020 ++#define FSTV0910_FSKR_KAGC 0xf176001c ++#define FSTV0910_FSKR_CAR2 0xf1760003 ++ ++/*FSKRFC1*/ ++#define RSTV0910_FSKRFC1 0xf177 ++#define FSTV0910_FSKR_CAR1 0xf17700ff ++ ++/*FSKRFC0*/ ++#define RSTV0910_FSKRFC0 0xf178 ++#define FSTV0910_FSKR_CAR0 0xf17800ff ++ ++/*FSKRK1*/ ++#define RSTV0910_FSKRK1 0xf179 ++#define FSTV0910_FSKR_K1_EXP 0xf17900e0 ++#define FSTV0910_FSKR_K1_MANT 0xf179001f ++ ++/*FSKRK2*/ ++#define RSTV0910_FSKRK2 0xf17a ++#define FSTV0910_FSKR_K2_EXP 0xf17a00e0 ++#define FSTV0910_FSKR_K2_MANT 0xf17a001f ++ ++/*FSKRAGCR*/ ++#define RSTV0910_FSKRAGCR 0xf17b ++#define FSTV0910_FSKR_OUTCTL 0xf17b00c0 ++#define FSTV0910_FSKR_AGC_REF 0xf17b003f ++ ++/*FSKRAGC*/ ++#define RSTV0910_FSKRAGC 0xf17c ++#define FSTV0910_FSKR_AGC_ACCU 0xf17c00ff ++ ++/*FSKRALPHA*/ ++#define RSTV0910_FSKRALPHA 0xf17d ++#define FSTV0910_FSKR_ALPHA_EXP 0xf17d001c ++#define FSTV0910_FSKR_ALPHA_M 0xf17d0003 ++ ++/*FSKRPLTH1*/ ++#define RSTV0910_FSKRPLTH1 0xf17e ++#define FSTV0910_FSKR_BETA 0xf17e00f0 ++#define FSTV0910_FSKR_PLL_TRESH1 0xf17e000f ++ ++/*FSKRPLTH0*/ ++#define RSTV0910_FSKRPLTH0 0xf17f ++#define FSTV0910_FSKR_PLL_TRESH0 0xf17f00ff ++ ++/*FSKRDF1*/ ++#define RSTV0910_FSKRDF1 0xf180 ++#define FSTV0910_FSKR_OUT 0xf1800080 ++#define FSTV0910_FSKR_STATE 0xf1800060 ++#define FSTV0910_FSKR_DELTAF1 0xf180001f ++ ++/*FSKRDF0*/ ++#define RSTV0910_FSKRDF0 0xf181 ++#define FSTV0910_FSKR_DELTAF0 0xf18100ff ++ ++/*FSKRSTEPP*/ ++#define RSTV0910_FSKRSTEPP 0xf182 ++#define FSTV0910_FSKR_STEP_PLUS 0xf18200ff ++ ++/*FSKRSTEPM*/ ++#define RSTV0910_FSKRSTEPM 0xf183 ++#define FSTV0910_FSKR_STEP_MINUS 0xf18300ff ++ ++/*FSKRDET1*/ ++#define RSTV0910_FSKRDET1 0xf184 ++#define FSTV0910_FSKR_DETECT 0xf1840080 ++#define FSTV0910_FSKR_CARDET_ACCU1 0xf184000f ++ ++/*FSKRDET0*/ ++#define RSTV0910_FSKRDET0 0xf185 ++#define FSTV0910_FSKR_CARDET_ACCU0 0xf18500ff ++ ++/*FSKRDTH1*/ ++#define RSTV0910_FSKRDTH1 0xf186 ++#define FSTV0910_FSKR_CARLOSS_THRESH1 0xf18600f0 ++#define FSTV0910_FSKR_CARDET_THRESH1 0xf186000f ++ ++/*FSKRDTH0*/ ++#define RSTV0910_FSKRDTH0 0xf187 ++#define FSTV0910_FSKR_CARDET_THRESH0 0xf18700ff ++ ++/*FSKRLOSS*/ ++#define RSTV0910_FSKRLOSS 0xf188 ++#define FSTV0910_FSKR_CARLOSS_THRESH0 0xf18800ff ++ ++/*NCOARSE*/ ++#define RSTV0910_NCOARSE 0xf1b3 ++#define FSTV0910_CP 0xf1b300f8 ++#define FSTV0910_IDF 0xf1b30007 ++ ++/*NCOARSE1*/ ++#define RSTV0910_NCOARSE1 0xf1b4 ++#define FSTV0910_N_DIV 0xf1b400ff ++ ++/*NCOARSE2*/ ++#define RSTV0910_NCOARSE2 0xf1b5 ++#define FSTV0910_ODF 0xf1b5003f ++ ++/*SYNTCTRL*/ ++#define RSTV0910_SYNTCTRL 0xf1b6 ++#define FSTV0910_STANDBY 0xf1b60080 ++#define FSTV0910_BYPASSPLLCORE 0xf1b60040 ++#define FSTV0910_STOP_PLL 0xf1b60008 ++#define FSTV0910_OSCI_E 0xf1b60002 ++ ++/*FILTCTRL*/ ++#define RSTV0910_FILTCTRL 0xf1b7 ++#define FSTV0910_INV_CLKFSK 0xf1b70002 ++#define FSTV0910_BYPASS_APPLI 0xf1b70001 ++ ++/*PLLSTAT*/ ++#define RSTV0910_PLLSTAT 0xf1b8 ++#define FSTV0910_PLL_BIST_END 0xf1b80004 ++#define FSTV0910_PLLLOCK 0xf1b80001 ++ ++/*STOPCLK1*/ ++#define RSTV0910_STOPCLK1 0xf1c2 ++#define FSTV0910_INV_CLKADCI2 0xf1c20004 ++#define FSTV0910_INV_CLKADCI1 0xf1c20001 ++ ++/*STOPCLK2*/ ++#define RSTV0910_STOPCLK2 0xf1c3 ++#define FSTV0910_STOP_DVBS2FEC2 0xf1c30020 ++#define FSTV0910_STOP_DVBS2FEC 0xf1c30010 ++#define FSTV0910_STOP_DVBS1FEC2 0xf1c30008 ++#define FSTV0910_STOP_DVBS1FEC 0xf1c30004 ++#define FSTV0910_STOP_DEMOD2 0xf1c30002 ++#define FSTV0910_STOP_DEMOD 0xf1c30001 ++ ++/*PREGCTL*/ ++#define RSTV0910_PREGCTL 0xf1c8 ++#define FSTV0910_REG3V3TO2V5_POFF 0xf1c80080 ++ ++/*TSTTNR0*/ ++#define RSTV0910_TSTTNR0 0xf1df ++#define FSTV0910_FSK_PON 0xf1df0004 ++#define FSTV0910_FSK_OPENLOOP 0xf1df0002 ++ ++/*TSTTNR1*/ ++#define RSTV0910_TSTTNR1 0xf1e0 ++#define FSTV0910_BYPASS_ADC1 0xf1e00080 ++#define FSTV0910_INVADC1_CKOUT 0xf1e00040 ++#define FSTV0910_SELIQSRC1 0xf1e00030 ++#define FSTV0910_DEMOD2_SELADC 0xf1e00008 ++#define FSTV0910_DEMOD1_SELADC 0xf1e00004 ++#define FSTV0910_ADC1_PON 0xf1e00002 ++ ++/*TSTTNR2*/ ++#define RSTV0910_TSTTNR2 0xf1e1 ++#define FSTV0910_I2C_DISEQC_BYPASS 0xf1e10080 ++#define FSTV0910_I2C_DISEQC_ENCH 0xf1e10040 ++#define FSTV0910_I2C_DISEQC_PON 0xf1e10020 ++#define FSTV0910_DISEQC_CLKDIV 0xf1e1000f ++ ++/*TSTTNR3*/ ++#define RSTV0910_TSTTNR3 0xf1e2 ++#define FSTV0910_BYPASS_ADC2 0xf1e20080 ++#define FSTV0910_INVADC2_CKOUT 0xf1e20040 ++#define FSTV0910_SELIQSRC2 0xf1e20030 ++#define FSTV0910_ADC2_PON 0xf1e20002 ++ ++/*P2_IQCONST*/ ++#define RSTV0910_P2_IQCONST 0xf200 ++#define FSTV0910_P2_CONSTEL_SELECT 0xf2000060 ++#define FSTV0910_P2_IQSYMB_SEL 0xf200001f ++ ++/*P2_NOSCFG*/ ++#define RSTV0910_P2_NOSCFG 0xf201 ++#define FSTV0910_P2_DIS_ACMRATIO 0xf2010080 ++#define FSTV0910_P2_NOSIN_EGALSEL 0xf2010040 ++#define FSTV0910_P2_DUMMYPL_NOSDATA 0xf2010020 ++#define FSTV0910_P2_NOSPLH_BETA 0xf2010018 ++#define FSTV0910_P2_NOSDATA_BETA 0xf2010007 ++ ++/*P2_ISYMB*/ ++#define RSTV0910_P2_ISYMB 0xf202 ++#define FSTV0910_P2_I_SYMBOL 0xf20201ff ++ ++/*P2_QSYMB*/ ++#define RSTV0910_P2_QSYMB 0xf203 ++#define FSTV0910_P2_Q_SYMBOL 0xf20301ff ++ ++/*P2_AGC1CFG*/ ++#define RSTV0910_P2_AGC1CFG 0xf204 ++#define FSTV0910_P2_DC_FROZEN 0xf2040080 ++#define FSTV0910_P2_DC_CORRECT 0xf2040040 ++#define FSTV0910_P2_AMM_FROZEN 0xf2040020 ++#define FSTV0910_P2_AMM_CORRECT 0xf2040010 ++#define FSTV0910_P2_QUAD_FROZEN 0xf2040008 ++#define FSTV0910_P2_QUAD_CORRECT 0xf2040004 ++#define FSTV0910_P2_DCCOMP_SLOW 0xf2040002 ++#define FSTV0910_P2_IQMISM_SLOW 0xf2040001 ++ ++/*P2_AGC1CN*/ ++#define RSTV0910_P2_AGC1CN 0xf206 ++#define FSTV0910_P2_AGC1_LOCKED 0xf2060080 ++#define FSTV0910_P2_AGC1_OVERFLOW 0xf2060040 ++#define FSTV0910_P2_AGC1_NOSLOWLK 0xf2060020 ++#define FSTV0910_P2_AGC1_MINPOWER 0xf2060010 ++#define FSTV0910_P2_AGCOUT_FAST 0xf2060008 ++#define FSTV0910_P2_AGCIQ_BETA 0xf2060007 ++ ++/*P2_AGC1REF*/ ++#define RSTV0910_P2_AGC1REF 0xf207 ++#define FSTV0910_P2_AGCIQ_REF 0xf20700ff ++ ++/*P2_IDCCOMP*/ ++#define RSTV0910_P2_IDCCOMP 0xf208 ++#define FSTV0910_P2_IAVERAGE_ADJ 0xf20801ff ++ ++/*P2_QDCCOMP*/ ++#define RSTV0910_P2_QDCCOMP 0xf209 ++#define FSTV0910_P2_QAVERAGE_ADJ 0xf20901ff ++ ++/*P2_POWERI*/ ++#define RSTV0910_P2_POWERI 0xf20a ++#define FSTV0910_P2_POWER_I 0xf20a00ff ++ ++/*P2_POWERQ*/ ++#define RSTV0910_P2_POWERQ 0xf20b ++#define FSTV0910_P2_POWER_Q 0xf20b00ff ++ ++/*P2_AGC1AMM*/ ++#define RSTV0910_P2_AGC1AMM 0xf20c ++#define FSTV0910_P2_AMM_VALUE 0xf20c00ff ++ ++/*P2_AGC1QUAD*/ ++#define RSTV0910_P2_AGC1QUAD 0xf20d ++#define FSTV0910_P2_QUAD_VALUE 0xf20d01ff ++ ++/*P2_AGCIQIN1*/ ++#define RSTV0910_P2_AGCIQIN1 0xf20e ++#define FSTV0910_P2_AGCIQ_VALUE1 0xf20e00ff ++ ++/*P2_AGCIQIN0*/ ++#define RSTV0910_P2_AGCIQIN0 0xf20f ++#define FSTV0910_P2_AGCIQ_VALUE0 0xf20f00ff ++ ++/*P2_DEMOD*/ ++#define RSTV0910_P2_DEMOD 0xf210 ++#define FSTV0910_P2_MANUALS2_ROLLOFF 0xf2100080 ++#define FSTV0910_P2_SPECINV_CONTROL 0xf2100030 ++#define FSTV0910_P2_MANUALSX_ROLLOFF 0xf2100004 ++#define FSTV0910_P2_ROLLOFF_CONTROL 0xf2100003 ++ ++/*P2_DMDMODCOD*/ ++#define RSTV0910_P2_DMDMODCOD 0xf211 ++#define FSTV0910_P2_MANUAL_MODCOD 0xf2110080 ++#define FSTV0910_P2_DEMOD_MODCOD 0xf211007c ++#define FSTV0910_P2_DEMOD_TYPE 0xf2110003 ++ ++/*P2_DSTATUS*/ ++#define RSTV0910_P2_DSTATUS 0xf212 ++#define FSTV0910_P2_CAR_LOCK 0xf2120080 ++#define FSTV0910_P2_TMGLOCK_QUALITY 0xf2120060 ++#define FSTV0910_P2_SDVBS1_ENABLE 0xf2120010 ++#define FSTV0910_P2_LOCK_DEFINITIF 0xf2120008 ++#define FSTV0910_P2_TIMING_IS_LOCKED 0xf2120004 ++#define FSTV0910_P2_DEMOD_SYSCFG 0xf2120002 ++#define FSTV0910_P2_OVADC_DETECT 0xf2120001 ++ ++/*P2_DSTATUS2*/ ++#define RSTV0910_P2_DSTATUS2 0xf213 ++#define FSTV0910_P2_DEMOD_DELOCK 0xf2130080 ++#define FSTV0910_P2_DEMOD_TIMEOUT 0xf2130040 ++#define FSTV0910_P2_MODCODRQ_SYNCTAG 0xf2130020 ++#define FSTV0910_P2_POLYPH_SATEVENT 0xf2130010 ++#define FSTV0910_P2_AGC1_NOSIGNALACK 0xf2130008 ++#define FSTV0910_P2_AGC2_OVERFLOW 0xf2130004 ++#define FSTV0910_P2_CFR_OVERFLOW 0xf2130002 ++#define FSTV0910_P2_GAMMA_OVERUNDER 0xf2130001 ++ ++/*P2_DMDCFGMD*/ ++#define RSTV0910_P2_DMDCFGMD 0xf214 ++#define FSTV0910_P2_DVBS2_ENABLE 0xf2140080 ++#define FSTV0910_P2_DVBS1_ENABLE 0xf2140040 ++#define FSTV0910_P2_SCAN_ENABLE 0xf2140010 ++#define FSTV0910_P2_CFR_AUTOSCAN 0xf2140008 ++#define FSTV0910_P2_NOFORCE_RELOCK 0xf2140004 ++#define FSTV0910_P2_TUN_RNG 0xf2140003 ++ ++/*P2_DMDCFG2*/ ++#define RSTV0910_P2_DMDCFG2 0xf215 ++#define FSTV0910_P2_AGC1_WAITLOCK 0xf2150080 ++#define FSTV0910_P2_S1S2_SEQUENTIAL 0xf2150040 ++#define FSTV0910_P2_BLINDPEA_MODE 0xf2150020 ++#define FSTV0910_P2_INFINITE_RELOCK 0xf2150010 ++#define FSTV0910_P2_BWOFFSET_COLDWARM 0xf2150008 ++#define FSTV0910_P2_TMGLOCK_NSCANSTOP 0xf2150004 ++#define FSTV0910_P2_COARSE_LK3MODE 0xf2150002 ++#define FSTV0910_P2_COARSE_LK2MODE 0xf2150001 ++ ++/*P2_DMDISTATE*/ ++#define RSTV0910_P2_DMDISTATE 0xf216 ++#define FSTV0910_P2_I2C_NORESETDMODE 0xf2160080 ++#define FSTV0910_P2_FORCE_ETAPED 0xf2160040 ++#define FSTV0910_P2_SDMDRST_DIRCLK 0xf2160020 ++#define FSTV0910_P2_I2C_DEMOD_MODE 0xf216001f ++ ++/*P2_DMDT0M*/ ++#define RSTV0910_P2_DMDT0M 0xf217 ++#define FSTV0910_P2_DMDT0_MIN 0xf21700ff ++ ++/*P2_DMDSTATE*/ ++#define RSTV0910_P2_DMDSTATE 0xf21b ++#define FSTV0910_P2_DEMOD_LOCKED 0xf21b0080 ++#define FSTV0910_P2_HEADER_MODE 0xf21b0060 ++#define FSTV0910_P2_DEMOD_MODE 0xf21b001f ++ ++/*P2_DMDFLYW*/ ++#define RSTV0910_P2_DMDFLYW 0xf21c ++#define FSTV0910_P2_I2C_IRQVAL 0xf21c00f0 ++#define FSTV0910_P2_FLYWHEEL_CPT 0xf21c000f ++ ++/*P2_DSTATUS3*/ ++#define RSTV0910_P2_DSTATUS3 0xf21d ++#define FSTV0910_P2_CFR_ZIGZAG 0xf21d0080 ++#define FSTV0910_P2_DEMOD_CFGMODE 0xf21d0060 ++#define FSTV0910_P2_GAMMA_LOWBAUDRATE 0xf21d0010 ++#define FSTV0910_P2_RELOCK_MODE 0xf21d0008 ++#define FSTV0910_P2_DEMOD_FAIL 0xf21d0004 ++#define FSTV0910_P2_ETAPE1A_DVBXMEM 0xf21d0003 ++ ++/*P2_DMDCFG3*/ ++#define RSTV0910_P2_DMDCFG3 0xf21e ++#define FSTV0910_P2_DVBS1_TMGWAIT 0xf21e0080 ++#define FSTV0910_P2_NO_BWCENTERING 0xf21e0040 ++#define FSTV0910_P2_INV_SEQSRCH 0xf21e0020 ++#define FSTV0910_P2_DIS_SFRUPLOW_TRK 0xf21e0010 ++#define FSTV0910_P2_NOSTOP_FIFOFULL 0xf21e0008 ++#define FSTV0910_P2_LOCKTIME_MODE 0xf21e0007 ++ ++/*P2_DMDCFG4*/ ++#define RSTV0910_P2_DMDCFG4 0xf21f ++#define FSTV0910_P2_DIS_VITLOCK 0xf21f0080 ++#define FSTV0910_P2_S1S2TOUT_FAST 0xf21f0040 ++#define FSTV0910_P2_DEMOD_FASTLOCK 0xf21f0020 ++#define FSTV0910_P2_S1HIER_ENABLE 0xf21f0010 ++#define FSTV0910_P2_TUNER_NRELAUNCH 0xf21f0008 ++#define FSTV0910_P2_DIS_CLKENABLE 0xf21f0004 ++#define FSTV0910_P2_DIS_HDRDIVLOCK 0xf21f0002 ++#define FSTV0910_P2_NO_TNRWBINIT 0xf21f0001 ++ ++/*P2_CORRELMANT*/ ++#define RSTV0910_P2_CORRELMANT 0xf220 ++#define FSTV0910_P2_CORREL_MANT 0xf22000ff ++ ++/*P2_CORRELABS*/ ++#define RSTV0910_P2_CORRELABS 0xf221 ++#define FSTV0910_P2_CORREL_ABS 0xf22100ff ++ ++/*P2_CORRELEXP*/ ++#define RSTV0910_P2_CORRELEXP 0xf222 ++#define FSTV0910_P2_CORREL_ABSEXP 0xf22200f0 ++#define FSTV0910_P2_CORREL_EXP 0xf222000f ++ ++/*P2_PLHMODCOD*/ ++#define RSTV0910_P2_PLHMODCOD 0xf224 ++#define FSTV0910_P2_SPECINV_DEMOD 0xf2240080 ++#define FSTV0910_P2_PLH_MODCOD 0xf224007c ++#define FSTV0910_P2_PLH_TYPE 0xf2240003 ++ ++/*P2_DMDREG*/ ++#define RSTV0910_P2_DMDREG 0xf225 ++#define FSTV0910_P2_EXTPSK_MODE 0xf2250080 ++#define FSTV0910_P2_HIER_SHORTFRAME 0xf2250002 ++#define FSTV0910_P2_DECIM_PLFRAMES 0xf2250001 ++ ++/*P2_AGC2O*/ ++#define RSTV0910_P2_AGC2O 0xf22c ++#define FSTV0910_P2_CSTENV_MODE 0xf22c00c0 ++#define FSTV0910_P2_AGC2_LKSQRT 0xf22c0020 ++#define FSTV0910_P2_AGC2_LKMODE 0xf22c0010 ++#define FSTV0910_P2_AGC2_LKEQUA 0xf22c0008 ++#define FSTV0910_P2_AGC2_COEF 0xf22c0007 ++ ++/*P2_AGC2REF*/ ++#define RSTV0910_P2_AGC2REF 0xf22d ++#define FSTV0910_P2_AGC2_REF 0xf22d00ff ++ ++/*P2_AGC1ADJ*/ ++#define RSTV0910_P2_AGC1ADJ 0xf22e ++#define FSTV0910_P2_AGC1ADJ_MANUAL 0xf22e0080 ++#define FSTV0910_P2_AGC1_ADJUSTED 0xf22e007f ++ ++/*P2_AGC2I1*/ ++#define RSTV0910_P2_AGC2I1 0xf236 ++#define FSTV0910_P2_AGC2_INTEGRATOR1 0xf23600ff ++ ++/*P2_AGC2I0*/ ++#define RSTV0910_P2_AGC2I0 0xf237 ++#define FSTV0910_P2_AGC2_INTEGRATOR0 0xf23700ff ++ ++/*P2_CARCFG*/ ++#define RSTV0910_P2_CARCFG 0xf238 ++#define FSTV0910_P2_CFRUPLOW_AUTO 0xf2380080 ++#define FSTV0910_P2_CFRUPLOW_TEST 0xf2380040 ++#define FSTV0910_P2_WIDE_FREQDET 0xf2380020 ++#define FSTV0910_P2_CARHDR_NODIV8 0xf2380010 ++#define FSTV0910_P2_I2C_ROTA 0xf2380008 ++#define FSTV0910_P2_ROTAON 0xf2380004 ++#define FSTV0910_P2_PH_DET_ALGO 0xf2380003 ++ ++/*P2_ACLC*/ ++#define RSTV0910_P2_ACLC 0xf239 ++#define FSTV0910_P2_CARS1_ANOSAUTO 0xf2390040 ++#define FSTV0910_P2_CAR_ALPHA_MANT 0xf2390030 ++#define FSTV0910_P2_CAR_ALPHA_EXP 0xf239000f ++ ++/*P2_BCLC*/ ++#define RSTV0910_P2_BCLC 0xf23a ++#define FSTV0910_P2_CARS1_BNOSAUTO 0xf23a0040 ++#define FSTV0910_P2_CAR_BETA_MANT 0xf23a0030 ++#define FSTV0910_P2_CAR_BETA_EXP 0xf23a000f ++ ++/*P2_CARFREQ*/ ++#define RSTV0910_P2_CARFREQ 0xf23d ++#define FSTV0910_P2_KC_COARSE_EXP 0xf23d00f0 ++#define FSTV0910_P2_BETA_FREQ 0xf23d000f ++ ++/*P2_CARHDR*/ ++#define RSTV0910_P2_CARHDR 0xf23e ++#define FSTV0910_P2_K_FREQ_HDR 0xf23e00ff ++ ++/*P2_LDT*/ ++#define RSTV0910_P2_LDT 0xf23f ++#define FSTV0910_P2_CARLOCK_THRES 0xf23f01ff ++ ++/*P2_LDT2*/ ++#define RSTV0910_P2_LDT2 0xf240 ++#define FSTV0910_P2_CARLOCK_THRES2 0xf24001ff ++ ++/*P2_CFRICFG*/ ++#define RSTV0910_P2_CFRICFG 0xf241 ++#define FSTV0910_P2_CFRINIT_UNVALRNG 0xf2410080 ++#define FSTV0910_P2_CFRINIT_LUNVALCPT 0xf2410040 ++#define FSTV0910_P2_CFRINIT_ABORTDBL 0xf2410020 ++#define FSTV0910_P2_CFRINIT_ABORTPRED 0xf2410010 ++#define FSTV0910_P2_CFRINIT_UNVALSKIP 0xf2410008 ++#define FSTV0910_P2_CFRINIT_CSTINC 0xf2410004 ++#define FSTV0910_P2_CFRIROLL_GARDER 0xf2410002 ++#define FSTV0910_P2_NEG_CFRSTEP 0xf2410001 ++ ++/*P2_CFRUP1*/ ++#define RSTV0910_P2_CFRUP1 0xf242 ++#define FSTV0910_P2_CFR_UP1 0xf24201ff ++ ++/*P2_CFRUP0*/ ++#define RSTV0910_P2_CFRUP0 0xf243 ++#define FSTV0910_P2_CFR_UP0 0xf24300ff ++ ++/*P2_CFRIBASE1*/ ++#define RSTV0910_P2_CFRIBASE1 0xf244 ++#define FSTV0910_P2_CFRINIT_BASE1 0xf24400ff ++ ++/*P2_CFRIBASE0*/ ++#define RSTV0910_P2_CFRIBASE0 0xf245 ++#define FSTV0910_P2_CFRINIT_BASE0 0xf24500ff ++ ++/*P2_CFRLOW1*/ ++#define RSTV0910_P2_CFRLOW1 0xf246 ++#define FSTV0910_P2_CFR_LOW1 0xf24601ff ++ ++/*P2_CFRLOW0*/ ++#define RSTV0910_P2_CFRLOW0 0xf247 ++#define FSTV0910_P2_CFR_LOW0 0xf24700ff ++ ++/*P2_CFRINIT1*/ ++#define RSTV0910_P2_CFRINIT1 0xf248 ++#define FSTV0910_P2_CFR_INIT1 0xf24801ff ++ ++/*P2_CFRINIT0*/ ++#define RSTV0910_P2_CFRINIT0 0xf249 ++#define FSTV0910_P2_CFR_INIT0 0xf24900ff ++ ++/*P2_CFRINC1*/ ++#define RSTV0910_P2_CFRINC1 0xf24a ++#define FSTV0910_P2_MANUAL_CFRINC 0xf24a0080 ++#define FSTV0910_P2_CFR_INC1 0xf24a003f ++ ++/*P2_CFRINC0*/ ++#define RSTV0910_P2_CFRINC0 0xf24b ++#define FSTV0910_P2_CFR_INC0 0xf24b00ff ++ ++/*P2_CFR2*/ ++#define RSTV0910_P2_CFR2 0xf24c ++#define FSTV0910_P2_CAR_FREQ2 0xf24c01ff ++ ++/*P2_CFR1*/ ++#define RSTV0910_P2_CFR1 0xf24d ++#define FSTV0910_P2_CAR_FREQ1 0xf24d00ff ++ ++/*P2_CFR0*/ ++#define RSTV0910_P2_CFR0 0xf24e ++#define FSTV0910_P2_CAR_FREQ0 0xf24e00ff ++ ++/*P2_LDI*/ ++#define RSTV0910_P2_LDI 0xf24f ++#define FSTV0910_P2_LOCK_DET_INTEGR 0xf24f01ff ++ ++/*P2_TMGCFG*/ ++#define RSTV0910_P2_TMGCFG 0xf250 ++#define FSTV0910_P2_TMGLOCK_BETA 0xf25000c0 ++#define FSTV0910_P2_DO_TIMING_CORR 0xf2500010 ++#define FSTV0910_P2_MANUAL_SCAN 0xf250000c ++#define FSTV0910_P2_TMG_MINFREQ 0xf2500003 ++ ++/*P2_RTC*/ ++#define RSTV0910_P2_RTC 0xf251 ++#define FSTV0910_P2_TMGALPHA_EXP 0xf25100f0 ++#define FSTV0910_P2_TMGBETA_EXP 0xf251000f ++ ++/*P2_RTCS2*/ ++#define RSTV0910_P2_RTCS2 0xf252 ++#define FSTV0910_P2_TMGALPHAS2_EXP 0xf25200f0 ++#define FSTV0910_P2_TMGBETAS2_EXP 0xf252000f ++ ++/*P2_TMGTHRISE*/ ++#define RSTV0910_P2_TMGTHRISE 0xf253 ++#define FSTV0910_P2_TMGLOCK_THRISE 0xf25300ff ++ ++/*P2_TMGTHFALL*/ ++#define RSTV0910_P2_TMGTHFALL 0xf254 ++#define FSTV0910_P2_TMGLOCK_THFALL 0xf25400ff ++ ++/*P2_SFRUPRATIO*/ ++#define RSTV0910_P2_SFRUPRATIO 0xf255 ++#define FSTV0910_P2_SFR_UPRATIO 0xf25500ff ++ ++/*P2_SFRLOWRATIO*/ ++#define RSTV0910_P2_SFRLOWRATIO 0xf256 ++#define FSTV0910_P2_SFR_LOWRATIO 0xf25600ff ++ ++/*P2_KTTMG*/ ++#define RSTV0910_P2_KTTMG 0xf257 ++#define FSTV0910_P2_KT_TMG_EXP 0xf25700f0 ++ ++/*P2_KREFTMG*/ ++#define RSTV0910_P2_KREFTMG 0xf258 ++#define FSTV0910_P2_KREF_TMG 0xf25800ff ++ ++/*P2_SFRSTEP*/ ++#define RSTV0910_P2_SFRSTEP 0xf259 ++#define FSTV0910_P2_SFR_SCANSTEP 0xf25900f0 ++#define FSTV0910_P2_SFR_CENTERSTEP 0xf259000f ++ ++/*P2_TMGCFG2*/ ++#define RSTV0910_P2_TMGCFG2 0xf25a ++#define FSTV0910_P2_KREFTMG2_DECMODE 0xf25a00c0 ++#define FSTV0910_P2_DIS_AUTOSAMP 0xf25a0008 ++#define FSTV0910_P2_SCANINIT_QUART 0xf25a0004 ++#define FSTV0910_P2_NOTMG_DVBS1DERAT 0xf25a0002 ++#define FSTV0910_P2_SFRRATIO_FINE 0xf25a0001 ++ ++/*P2_KREFTMG2*/ ++#define RSTV0910_P2_KREFTMG2 0xf25b ++#define FSTV0910_P2_KREF_TMG2 0xf25b00ff ++ ++/*P2_TMGCFG3*/ ++#define RSTV0910_P2_TMGCFG3 0xf25d ++#define FSTV0910_P2_CFRINC_MODE 0xf25d0070 ++#define FSTV0910_P2_CONT_TMGCENTER 0xf25d0008 ++#define FSTV0910_P2_AUTO_GUP 0xf25d0004 ++#define FSTV0910_P2_AUTO_GLOW 0xf25d0002 ++#define FSTV0910_P2_SFRVAL_MINMODE 0xf25d0001 ++ ++/*P2_SFRINIT1*/ ++#define RSTV0910_P2_SFRINIT1 0xf25e ++#define FSTV0910_P2_SFR_INIT1 0xf25e00ff ++ ++/*P2_SFRINIT0*/ ++#define RSTV0910_P2_SFRINIT0 0xf25f ++#define FSTV0910_P2_SFR_INIT0 0xf25f00ff ++ ++/*P2_SFRUP1*/ ++#define RSTV0910_P2_SFRUP1 0xf260 ++#define FSTV0910_P2_SYMB_FREQ_UP1 0xf26000ff ++ ++/*P2_SFRUP0*/ ++#define RSTV0910_P2_SFRUP0 0xf261 ++#define FSTV0910_P2_SYMB_FREQ_UP0 0xf26100ff ++ ++/*P2_SFRLOW1*/ ++#define RSTV0910_P2_SFRLOW1 0xf262 ++#define FSTV0910_P2_SYMB_FREQ_LOW1 0xf26200ff ++ ++/*P2_SFRLOW0*/ ++#define RSTV0910_P2_SFRLOW0 0xf263 ++#define FSTV0910_P2_SYMB_FREQ_LOW0 0xf26300ff ++ ++/*P2_SFR3*/ ++#define RSTV0910_P2_SFR3 0xf264 ++#define FSTV0910_P2_SYMB_FREQ3 0xf26400ff ++ ++/*P2_SFR2*/ ++#define RSTV0910_P2_SFR2 0xf265 ++#define FSTV0910_P2_SYMB_FREQ2 0xf26500ff ++ ++/*P2_SFR1*/ ++#define RSTV0910_P2_SFR1 0xf266 ++#define FSTV0910_P2_SYMB_FREQ1 0xf26600ff ++ ++/*P2_SFR0*/ ++#define RSTV0910_P2_SFR0 0xf267 ++#define FSTV0910_P2_SYMB_FREQ0 0xf26700ff ++ ++/*P2_TMGREG2*/ ++#define RSTV0910_P2_TMGREG2 0xf268 ++#define FSTV0910_P2_TMGREG2 0xf26800ff ++ ++/*P2_TMGREG1*/ ++#define RSTV0910_P2_TMGREG1 0xf269 ++#define FSTV0910_P2_TMGREG1 0xf26900ff ++ ++/*P2_TMGREG0*/ ++#define RSTV0910_P2_TMGREG0 0xf26a ++#define FSTV0910_P2_TMGREG0 0xf26a00ff ++ ++/*P2_TMGLOCK1*/ ++#define RSTV0910_P2_TMGLOCK1 0xf26b ++#define FSTV0910_P2_TMGLOCK_LEVEL1 0xf26b01ff ++ ++/*P2_TMGLOCK0*/ ++#define RSTV0910_P2_TMGLOCK0 0xf26c ++#define FSTV0910_P2_TMGLOCK_LEVEL0 0xf26c00ff ++ ++/*P2_TMGOBS*/ ++#define RSTV0910_P2_TMGOBS 0xf26d ++#define FSTV0910_P2_ROLLOFF_STATUS 0xf26d00c0 ++#define FSTV0910_P2_SCAN_SIGN 0xf26d0030 ++#define FSTV0910_P2_TMG_SCANNING 0xf26d0008 ++#define FSTV0910_P2_CHCENTERING_MODE 0xf26d0004 ++#define FSTV0910_P2_TMG_SCANFAIL 0xf26d0002 ++ ++/*P2_EQUALCFG*/ ++#define RSTV0910_P2_EQUALCFG 0xf26f ++#define FSTV0910_P2_NOTMG_NEGALWAIT 0xf26f0080 ++#define FSTV0910_P2_EQUAL_ON 0xf26f0040 ++#define FSTV0910_P2_SEL_EQUALCOR 0xf26f0038 ++#define FSTV0910_P2_MU_EQUALDFE 0xf26f0007 ++ ++/*P2_EQUAI1*/ ++#define RSTV0910_P2_EQUAI1 0xf270 ++#define FSTV0910_P2_EQUA_ACCI1 0xf27001ff ++ ++/*P2_EQUAQ1*/ ++#define RSTV0910_P2_EQUAQ1 0xf271 ++#define FSTV0910_P2_EQUA_ACCQ1 0xf27101ff ++ ++/*P2_EQUAI2*/ ++#define RSTV0910_P2_EQUAI2 0xf272 ++#define FSTV0910_P2_EQUA_ACCI2 0xf27201ff ++ ++/*P2_EQUAQ2*/ ++#define RSTV0910_P2_EQUAQ2 0xf273 ++#define FSTV0910_P2_EQUA_ACCQ2 0xf27301ff ++ ++/*P2_EQUAI3*/ ++#define RSTV0910_P2_EQUAI3 0xf274 ++#define FSTV0910_P2_EQUA_ACCI3 0xf27401ff ++ ++/*P2_EQUAQ3*/ ++#define RSTV0910_P2_EQUAQ3 0xf275 ++#define FSTV0910_P2_EQUA_ACCQ3 0xf27501ff ++ ++/*P2_EQUAI4*/ ++#define RSTV0910_P2_EQUAI4 0xf276 ++#define FSTV0910_P2_EQUA_ACCI4 0xf27601ff ++ ++/*P2_EQUAQ4*/ ++#define RSTV0910_P2_EQUAQ4 0xf277 ++#define FSTV0910_P2_EQUA_ACCQ4 0xf27701ff ++ ++/*P2_EQUAI5*/ ++#define RSTV0910_P2_EQUAI5 0xf278 ++#define FSTV0910_P2_EQUA_ACCI5 0xf27801ff ++ ++/*P2_EQUAQ5*/ ++#define RSTV0910_P2_EQUAQ5 0xf279 ++#define FSTV0910_P2_EQUA_ACCQ5 0xf27901ff ++ ++/*P2_EQUAI6*/ ++#define RSTV0910_P2_EQUAI6 0xf27a ++#define FSTV0910_P2_EQUA_ACCI6 0xf27a01ff ++ ++/*P2_EQUAQ6*/ ++#define RSTV0910_P2_EQUAQ6 0xf27b ++#define FSTV0910_P2_EQUA_ACCQ6 0xf27b01ff ++ ++/*P2_EQUAI7*/ ++#define RSTV0910_P2_EQUAI7 0xf27c ++#define FSTV0910_P2_EQUA_ACCI7 0xf27c01ff ++ ++/*P2_EQUAQ7*/ ++#define RSTV0910_P2_EQUAQ7 0xf27d ++#define FSTV0910_P2_EQUA_ACCQ7 0xf27d01ff ++ ++/*P2_EQUAI8*/ ++#define RSTV0910_P2_EQUAI8 0xf27e ++#define FSTV0910_P2_EQUA_ACCI8 0xf27e01ff ++ ++/*P2_EQUAQ8*/ ++#define RSTV0910_P2_EQUAQ8 0xf27f ++#define FSTV0910_P2_EQUA_ACCQ8 0xf27f01ff ++ ++/*P2_NNOSDATAT1*/ ++#define RSTV0910_P2_NNOSDATAT1 0xf280 ++#define FSTV0910_P2_NOSDATAT_NORMED1 0xf28000ff ++ ++/*P2_NNOSDATAT0*/ ++#define RSTV0910_P2_NNOSDATAT0 0xf281 ++#define FSTV0910_P2_NOSDATAT_NORMED0 0xf28100ff ++ ++/*P2_NNOSDATA1*/ ++#define RSTV0910_P2_NNOSDATA1 0xf282 ++#define FSTV0910_P2_NOSDATA_NORMED1 0xf28200ff ++ ++/*P2_NNOSDATA0*/ ++#define RSTV0910_P2_NNOSDATA0 0xf283 ++#define FSTV0910_P2_NOSDATA_NORMED0 0xf28300ff ++ ++/*P2_NNOSPLHT1*/ ++#define RSTV0910_P2_NNOSPLHT1 0xf284 ++#define FSTV0910_P2_NOSPLHT_NORMED1 0xf28400ff ++ ++/*P2_NNOSPLHT0*/ ++#define RSTV0910_P2_NNOSPLHT0 0xf285 ++#define FSTV0910_P2_NOSPLHT_NORMED0 0xf28500ff ++ ++/*P2_NNOSPLH1*/ ++#define RSTV0910_P2_NNOSPLH1 0xf286 ++#define FSTV0910_P2_NOSPLH_NORMED1 0xf28600ff ++ ++/*P2_NNOSPLH0*/ ++#define RSTV0910_P2_NNOSPLH0 0xf287 ++#define FSTV0910_P2_NOSPLH_NORMED0 0xf28700ff ++ ++/*P2_NOSDATAT1*/ ++#define RSTV0910_P2_NOSDATAT1 0xf288 ++#define FSTV0910_P2_NOSDATAT_UNNORMED1 0xf28800ff ++ ++/*P2_NOSDATAT0*/ ++#define RSTV0910_P2_NOSDATAT0 0xf289 ++#define FSTV0910_P2_NOSDATAT_UNNORMED0 0xf28900ff ++ ++/*P2_NNOSFRAME1*/ ++#define RSTV0910_P2_NNOSFRAME1 0xf28a ++#define FSTV0910_P2_NOSFRAME_NORMED1 0xf28a00ff ++ ++/*P2_NNOSFRAME0*/ ++#define RSTV0910_P2_NNOSFRAME0 0xf28b ++#define FSTV0910_P2_NOSFRAME_NORMED0 0xf28b00ff ++ ++/*P2_NNOSRAD1*/ ++#define RSTV0910_P2_NNOSRAD1 0xf28c ++#define FSTV0910_P2_NOSRADIAL_NORMED1 0xf28c00ff ++ ++/*P2_NNOSRAD0*/ ++#define RSTV0910_P2_NNOSRAD0 0xf28d ++#define FSTV0910_P2_NOSRADIAL_NORMED0 0xf28d00ff ++ ++/*P2_NOSCFGF1*/ ++#define RSTV0910_P2_NOSCFGF1 0xf28e ++#define FSTV0910_P2_LOWNOISE_MESURE 0xf28e0080 ++#define FSTV0910_P2_NOS_DELFRAME 0xf28e0040 ++#define FSTV0910_P2_NOSDATA_MODE 0xf28e0030 ++#define FSTV0910_P2_FRAMESEL_TYPESEL 0xf28e000c ++#define FSTV0910_P2_FRAMESEL_TYPE 0xf28e0003 ++ ++/*P2_CAR2CFG*/ ++#define RSTV0910_P2_CAR2CFG 0xf290 ++#define FSTV0910_P2_DESCRAMB_OFF 0xf2900080 ++#define FSTV0910_P2_EN_PHNOSRAM 0xf2900020 ++#define FSTV0910_P2_STOP_CFR2UPDATE 0xf2900010 ++#define FSTV0910_P2_STOP_NCO2UPDATE 0xf2900008 ++#define FSTV0910_P2_ROTA2ON 0xf2900004 ++#define FSTV0910_P2_PH_DET_ALGO2 0xf2900003 ++ ++/*P2_CFR2CFR1*/ ++#define RSTV0910_P2_CFR2CFR1 0xf291 ++#define FSTV0910_P2_CFR2_S2CONTROL 0xf29100c0 ++#define FSTV0910_P2_EN_S2CAR2CENTER 0xf2910020 ++#define FSTV0910_P2_BCHERRCFR2_MODE 0xf2910018 ++#define FSTV0910_P2_CFR2TOCFR1_BETA 0xf2910007 ++ ++/*P2_CAR3CFG*/ ++#define RSTV0910_P2_CAR3CFG 0xf292 ++#define FSTV0910_P2_CARRIER23_MODE 0xf29200c0 ++#define FSTV0910_P2_CAR3INTERM_DVBS1 0xf2920020 ++#define FSTV0910_P2_ABAMPLIF_MODE 0xf2920018 ++#define FSTV0910_P2_CARRIER3_ALPHA3DL 0xf2920007 ++ ++/*P2_CFR22*/ ++#define RSTV0910_P2_CFR22 0xf293 ++#define FSTV0910_P2_CAR2_FREQ2 0xf29301ff ++ ++/*P2_CFR21*/ ++#define RSTV0910_P2_CFR21 0xf294 ++#define FSTV0910_P2_CAR2_FREQ1 0xf29400ff ++ ++/*P2_CFR20*/ ++#define RSTV0910_P2_CFR20 0xf295 ++#define FSTV0910_P2_CAR2_FREQ0 0xf29500ff ++ ++/*P2_ACLC2S2Q*/ ++#define RSTV0910_P2_ACLC2S2Q 0xf297 ++#define FSTV0910_P2_ENAB_SPSKSYMB 0xf2970080 ++#define FSTV0910_P2_CAR2S2_QANOSAUTO 0xf2970040 ++#define FSTV0910_P2_CAR2S2_Q_ALPH_M 0xf2970030 ++#define FSTV0910_P2_CAR2S2_Q_ALPH_E 0xf297000f ++ ++/*P2_ACLC2S28*/ ++#define RSTV0910_P2_ACLC2S28 0xf298 ++#define FSTV0910_P2_OLDI3Q_MODE 0xf2980080 ++#define FSTV0910_P2_CAR2S2_8ANOSAUTO 0xf2980040 ++#define FSTV0910_P2_CAR2S2_8_ALPH_M 0xf2980030 ++#define FSTV0910_P2_CAR2S2_8_ALPH_E 0xf298000f ++ ++/*P2_ACLC2S216A*/ ++#define RSTV0910_P2_ACLC2S216A 0xf299 ++#define FSTV0910_P2_CAR2S2_16ANOSAUTO 0xf2990040 ++#define FSTV0910_P2_CAR2S2_16A_ALPH_M 0xf2990030 ++#define FSTV0910_P2_CAR2S2_16A_ALPH_E 0xf299000f ++ ++/*P2_ACLC2S232A*/ ++#define RSTV0910_P2_ACLC2S232A 0xf29a ++#define FSTV0910_P2_CAR2S2_32ANOSUATO 0xf29a0040 ++#define FSTV0910_P2_CAR2S2_32A_ALPH_M 0xf29a0030 ++#define FSTV0910_P2_CAR2S2_32A_ALPH_E 0xf29a000f ++ ++/*P2_BCLC2S2Q*/ ++#define RSTV0910_P2_BCLC2S2Q 0xf29c ++#define FSTV0910_P2_DVBS2S2Q_NIP 0xf29c0080 ++#define FSTV0910_P2_CAR2S2_QBNOSAUTO 0xf29c0040 ++#define FSTV0910_P2_CAR2S2_Q_BETA_M 0xf29c0030 ++#define FSTV0910_P2_CAR2S2_Q_BETA_E 0xf29c000f ++ ++/*P2_BCLC2S28*/ ++#define RSTV0910_P2_BCLC2S28 0xf29d ++#define FSTV0910_P2_DVBS2S28_NIP 0xf29d0080 ++#define FSTV0910_P2_CAR2S2_8BNOSAUTO 0xf29d0040 ++#define FSTV0910_P2_CAR2S2_8_BETA_M 0xf29d0030 ++#define FSTV0910_P2_CAR2S2_8_BETA_E 0xf29d000f ++ ++/*P2_PLROOT2*/ ++#define RSTV0910_P2_PLROOT2 0xf2ac ++#define FSTV0910_P2_PLHAUTO_DISPLH 0xf2ac0040 ++#define FSTV0910_P2_PLHAUTO_FASTMODE 0xf2ac0020 ++#define FSTV0910_P2_PLHAUTO_ENABLE 0xf2ac0010 ++#define FSTV0910_P2_PLSCRAMB_MODE 0xf2ac000c ++#define FSTV0910_P2_PLSCRAMB_ROOT2 0xf2ac0003 ++ ++/*P2_PLROOT1*/ ++#define RSTV0910_P2_PLROOT1 0xf2ad ++#define FSTV0910_P2_PLSCRAMB_ROOT1 0xf2ad00ff ++ ++/*P2_PLROOT0*/ ++#define RSTV0910_P2_PLROOT0 0xf2ae ++#define FSTV0910_P2_PLSCRAMB_ROOT0 0xf2ae00ff ++ ++/*P2_MODCODLST7*/ ++#define RSTV0910_P2_MODCODLST7 0xf2b7 ++#define FSTV0910_P2_MODCOD_NNOSFILTER 0xf2b70080 ++#define FSTV0910_P2_MODCODLST_NOSTYPE 0xf2b70040 ++#define FSTV0910_P2_DIS_8PSK_9_10 0xf2b70030 ++#define FSTV0910_P2_DIS_8P_8_9 0xf2b7000f ++ ++/*P2_MODCODLST8*/ ++#define RSTV0910_P2_MODCODLST8 0xf2b8 ++#define FSTV0910_P2_DIS_8P_5_6 0xf2b800f0 ++#define FSTV0910_P2_DIS_8P_3_4 0xf2b8000f ++ ++/*P2_MODCODLST9*/ ++#define RSTV0910_P2_MODCODLST9 0xf2b9 ++#define FSTV0910_P2_DIS_8P_2_3 0xf2b900f0 ++#define FSTV0910_P2_DIS_8P_3_5 0xf2b9000f ++ ++/*P2_MODCODLSTA*/ ++#define RSTV0910_P2_MODCODLSTA 0xf2ba ++#define FSTV0910_P2_NOSFILTER_LIMITE 0xf2ba0080 ++#define FSTV0910_P2_NOSFILTER_MODE 0xf2ba0040 ++#define FSTV0910_P2_DIS_QPSK_9_10 0xf2ba0030 ++#define FSTV0910_P2_DIS_QP_8_9 0xf2ba000f ++ ++/*P2_MODCODLSTB*/ ++#define RSTV0910_P2_MODCODLSTB 0xf2bb ++#define FSTV0910_P2_DIS_QP_5_6 0xf2bb00f0 ++#define FSTV0910_P2_DIS_QP_4_5 0xf2bb000f ++ ++/*P2_MODCODLSTC*/ ++#define RSTV0910_P2_MODCODLSTC 0xf2bc ++#define FSTV0910_P2_DIS_QP_3_4 0xf2bc00f0 ++#define FSTV0910_P2_DIS_QP_2_3 0xf2bc000f ++ ++/*P2_MODCODLSTD*/ ++#define RSTV0910_P2_MODCODLSTD 0xf2bd ++#define FSTV0910_P2_DIS_QPSK_3_5 0xf2bd00f0 ++#define FSTV0910_P2_DIS_QPSK_1_2 0xf2bd000f ++ ++/*P2_GAUSSR0*/ ++#define RSTV0910_P2_GAUSSR0 0xf2c0 ++#define FSTV0910_P2_EN_CCIMODE 0xf2c00080 ++#define FSTV0910_P2_R0_GAUSSIEN 0xf2c0007f ++ ++/*P2_CCIR0*/ ++#define RSTV0910_P2_CCIR0 0xf2c1 ++#define FSTV0910_P2_CCIDETECT_PLHONLY 0xf2c10080 ++#define FSTV0910_P2_R0_CCI 0xf2c1007f ++ ++/*P2_CCIQUANT*/ ++#define RSTV0910_P2_CCIQUANT 0xf2c2 ++#define FSTV0910_P2_CCI_BETA 0xf2c200e0 ++#define FSTV0910_P2_CCI_QUANT 0xf2c2001f ++ ++/*P2_CCITHRES*/ ++#define RSTV0910_P2_CCITHRES 0xf2c3 ++#define FSTV0910_P2_CCI_THRESHOLD 0xf2c300ff ++ ++/*P2_CCIACC*/ ++#define RSTV0910_P2_CCIACC 0xf2c4 ++#define FSTV0910_P2_CCI_VALUE 0xf2c400ff ++ ++/*P2_DSTATUS4*/ ++#define RSTV0910_P2_DSTATUS4 0xf2c5 ++#define FSTV0910_P2_RAINFADE_DETECT 0xf2c50080 ++#define FSTV0910_P2_NOTHRES2_FAIL 0xf2c50040 ++#define FSTV0910_P2_NOTHRES1_FAIL 0xf2c50020 ++#define FSTV0910_P2_PILOT_FAILDETECT 0xf2c50010 ++#define FSTV0910_P2_HIER_DETECT 0xf2c50008 ++#define FSTV0910_P2_DMDPROG_ERROR 0xf2c50004 ++#define FSTV0910_P2_CSTENV_DETECT 0xf2c50002 ++#define FSTV0910_P2_DETECTION_TRIAX 0xf2c50001 ++ ++/*P2_DMDRESCFG*/ ++#define RSTV0910_P2_DMDRESCFG 0xf2c6 ++#define FSTV0910_P2_DMDRES_RESET 0xf2c60080 ++#define FSTV0910_P2_DMDRES_NOISESQR 0xf2c60010 ++#define FSTV0910_P2_DMDRES_STRALL 0xf2c60008 ++#define FSTV0910_P2_DMDRES_NEWONLY 0xf2c60004 ++#define FSTV0910_P2_DMDRES_NOSTORE 0xf2c60002 ++#define FSTV0910_P2_DMDRES_AGC2MEM 0xf2c60001 ++ ++/*P2_DMDRESADR*/ ++#define RSTV0910_P2_DMDRESADR 0xf2c7 ++#define FSTV0910_P2_SUSP_PREDCANAL 0xf2c70080 ++#define FSTV0910_P2_DMDRES_VALIDCFR 0xf2c70040 ++#define FSTV0910_P2_DMDRES_MEMFULL 0xf2c70030 ++#define FSTV0910_P2_DMDRES_RESNBR 0xf2c7000f ++ ++/*P2_DMDRESDATA7*/ ++#define RSTV0910_P2_DMDRESDATA7 0xf2c8 ++#define FSTV0910_P2_DMDRES_DATA7 0xf2c800ff ++ ++/*P2_DMDRESDATA6*/ ++#define RSTV0910_P2_DMDRESDATA6 0xf2c9 ++#define FSTV0910_P2_DMDRES_DATA6 0xf2c900ff ++ ++/*P2_DMDRESDATA5*/ ++#define RSTV0910_P2_DMDRESDATA5 0xf2ca ++#define FSTV0910_P2_DMDRES_DATA5 0xf2ca00ff ++ ++/*P2_DMDRESDATA4*/ ++#define RSTV0910_P2_DMDRESDATA4 0xf2cb ++#define FSTV0910_P2_DMDRES_DATA4 0xf2cb00ff ++ ++/*P2_DMDRESDATA3*/ ++#define RSTV0910_P2_DMDRESDATA3 0xf2cc ++#define FSTV0910_P2_DMDRES_DATA3 0xf2cc00ff ++ ++/*P2_DMDRESDATA2*/ ++#define RSTV0910_P2_DMDRESDATA2 0xf2cd ++#define FSTV0910_P2_DMDRES_DATA2 0xf2cd00ff ++ ++/*P2_DMDRESDATA1*/ ++#define RSTV0910_P2_DMDRESDATA1 0xf2ce ++#define FSTV0910_P2_DMDRES_DATA1 0xf2ce00ff ++ ++/*P2_DMDRESDATA0*/ ++#define RSTV0910_P2_DMDRESDATA0 0xf2cf ++#define FSTV0910_P2_DMDRES_DATA0 0xf2cf00ff ++ ++/*P2_FFEI1*/ ++#define RSTV0910_P2_FFEI1 0xf2d0 ++#define FSTV0910_P2_FFE_ACCI1 0xf2d001ff ++ ++/*P2_FFEQ1*/ ++#define RSTV0910_P2_FFEQ1 0xf2d1 ++#define FSTV0910_P2_FFE_ACCQ1 0xf2d101ff ++ ++/*P2_FFEI2*/ ++#define RSTV0910_P2_FFEI2 0xf2d2 ++#define FSTV0910_P2_FFE_ACCI2 0xf2d201ff ++ ++/*P2_FFEQ2*/ ++#define RSTV0910_P2_FFEQ2 0xf2d3 ++#define FSTV0910_P2_FFE_ACCQ2 0xf2d301ff ++ ++/*P2_FFEI3*/ ++#define RSTV0910_P2_FFEI3 0xf2d4 ++#define FSTV0910_P2_FFE_ACCI3 0xf2d401ff ++ ++/*P2_FFEQ3*/ ++#define RSTV0910_P2_FFEQ3 0xf2d5 ++#define FSTV0910_P2_FFE_ACCQ3 0xf2d501ff ++ ++/*P2_FFEI4*/ ++#define RSTV0910_P2_FFEI4 0xf2d6 ++#define FSTV0910_P2_FFE_ACCI4 0xf2d601ff ++ ++/*P2_FFEQ4*/ ++#define RSTV0910_P2_FFEQ4 0xf2d7 ++#define FSTV0910_P2_FFE_ACCQ4 0xf2d701ff ++ ++/*P2_FFECFG*/ ++#define RSTV0910_P2_FFECFG 0xf2d8 ++#define FSTV0910_P2_EQUALFFE_ON 0xf2d80040 ++#define FSTV0910_P2_EQUAL_USEDSYMB 0xf2d80030 ++#define FSTV0910_P2_MU_EQUALFFE 0xf2d80007 ++ ++/*P2_TNRCFG2*/ ++#define RSTV0910_P2_TNRCFG2 0xf2e1 ++#define FSTV0910_P2_TUN_IQSWAP 0xf2e10080 ++#define FSTV0910_P2_STB6110_STEP2MHZ 0xf2e10040 ++#define FSTV0910_P2_STB6120_DBLI2C 0xf2e10020 ++#define FSTV0910_P2_TUNER_WIDEBAND 0xf2e10010 ++#define FSTV0910_P2_TUNER_OBSPAGE 0xf2e10008 ++#define FSTV0910_P2_DIS_BWCALC 0xf2e10004 ++#define FSTV0910_P2_SHORT_WAITSTATES 0xf2e10002 ++#define FSTV0910_P2_DIS_2BWAGC1 0xf2e10001 ++ ++/*P2_SMAPCOEF7*/ ++#define RSTV0910_P2_SMAPCOEF7 0xf300 ++#define FSTV0910_P2_DIS_QSCALE 0xf3000080 ++#define FSTV0910_P2_SMAPCOEF_Q_LLR12 0xf300017f ++ ++/*P2_SMAPCOEF6*/ ++#define RSTV0910_P2_SMAPCOEF6 0xf301 ++#define FSTV0910_P2_DIS_AGC2SCALE 0xf3010080 ++#define FSTV0910_P2_DIS_16IQMULT 0xf3010040 ++#define FSTV0910_P2_OLD_16APSK47 0xf3010020 ++#define FSTV0910_P2_OLD_16APSK12 0xf3010010 ++#define FSTV0910_P2_DIS_NEWSCALE 0xf3010008 ++#define FSTV0910_P2_ADJ_8PSKLLR1 0xf3010004 ++#define FSTV0910_P2_OLD_8PSKLLR1 0xf3010002 ++#define FSTV0910_P2_DIS_AB8PSK 0xf3010001 ++ ++/*P2_SMAPCOEF5*/ ++#define RSTV0910_P2_SMAPCOEF5 0xf302 ++#define FSTV0910_P2_DIS_8SCALE 0xf3020080 ++#define FSTV0910_P2_SMAPCOEF_8P_LLR23 0xf302017f ++ ++/*P2_NOSTHRES1*/ ++#define RSTV0910_P2_NOSTHRES1 0xf309 ++#define FSTV0910_P2_NOS_THRESHOLD1 0xf30900ff ++ ++/*P2_NOSTHRES2*/ ++#define RSTV0910_P2_NOSTHRES2 0xf30a ++#define FSTV0910_P2_NOS_THRESHOLD2 0xf30a00ff ++ ++/*P2_NOSDIFF1*/ ++#define RSTV0910_P2_NOSDIFF1 0xf30b ++#define FSTV0910_P2_NOSTHRES1_DIFF 0xf30b00ff ++ ++/*P2_RAINFADE*/ ++#define RSTV0910_P2_RAINFADE 0xf30c ++#define FSTV0910_P2_NOSTHRES_DATAT 0xf30c0080 ++#define FSTV0910_P2_RAINFADE_CNLIMIT 0xf30c0070 ++#define FSTV0910_P2_RAINFADE_TIMEOUT 0xf30c0007 ++ ++/*P2_NOSRAMCFG*/ ++#define RSTV0910_P2_NOSRAMCFG 0xf30d ++#define FSTV0910_P2_NOSRAM_DVBS2DATA 0xf30d0080 ++#define FSTV0910_P2_NOSRAM_QUADRAT 0xf30d0040 ++#define FSTV0910_P2_NOSRAM_ACTIVATION 0xf30d0030 ++#define FSTV0910_P2_NOSRAM_CNRONLY 0xf30d0008 ++#define FSTV0910_P2_NOSRAM_LGNCNR1 0xf30d0007 ++ ++/*P2_NOSRAMPOS*/ ++#define RSTV0910_P2_NOSRAMPOS 0xf30e ++#define FSTV0910_P2_NOSRAM_LGNCNR0 0xf30e00f0 ++#define FSTV0910_P2_NOSRAM_VALIDE 0xf30e0004 ++#define FSTV0910_P2_NOSRAM_CNRVAL1 0xf30e0003 ++ ++/*P2_NOSRAMVAL*/ ++#define RSTV0910_P2_NOSRAMVAL 0xf30f ++#define FSTV0910_P2_NOSRAM_CNRVAL0 0xf30f00ff ++ ++/*P2_DMDPLHSTAT*/ ++#define RSTV0910_P2_DMDPLHSTAT 0xf320 ++#define FSTV0910_P2_PLH_STATISTIC 0xf32000ff ++ ++/*P2_LOCKTIME3*/ ++#define RSTV0910_P2_LOCKTIME3 0xf322 ++#define FSTV0910_P2_DEMOD_LOCKTIME3 0xf32200ff ++ ++/*P2_LOCKTIME2*/ ++#define RSTV0910_P2_LOCKTIME2 0xf323 ++#define FSTV0910_P2_DEMOD_LOCKTIME2 0xf32300ff ++ ++/*P2_LOCKTIME1*/ ++#define RSTV0910_P2_LOCKTIME1 0xf324 ++#define FSTV0910_P2_DEMOD_LOCKTIME1 0xf32400ff ++ ++/*P2_LOCKTIME0*/ ++#define RSTV0910_P2_LOCKTIME0 0xf325 ++#define FSTV0910_P2_DEMOD_LOCKTIME0 0xf32500ff ++ ++/*P2_VITSCALE*/ ++#define RSTV0910_P2_VITSCALE 0xf332 ++#define FSTV0910_P2_NVTH_NOSRANGE 0xf3320080 ++#define FSTV0910_P2_VERROR_MAXMODE 0xf3320040 ++#define FSTV0910_P2_KDIV_MODE 0xf3320030 ++#define FSTV0910_P2_NSLOWSN_LOCKED 0xf3320008 ++#define FSTV0910_P2_DELOCK_PRFLOSS 0xf3320004 ++#define FSTV0910_P2_DIS_RSFLOCK 0xf3320002 ++ ++/*P2_FECM*/ ++#define RSTV0910_P2_FECM 0xf333 ++#define FSTV0910_P2_DSS_DVB 0xf3330080 ++#define FSTV0910_P2_DEMOD_BYPASS 0xf3330040 ++#define FSTV0910_P2_CMP_SLOWMODE 0xf3330020 ++#define FSTV0910_P2_DSS_SRCH 0xf3330010 ++#define FSTV0910_P2_DIFF_MODEVIT 0xf3330004 ++#define FSTV0910_P2_SYNCVIT 0xf3330002 ++#define FSTV0910_P2_IQINV 0xf3330001 ++ ++/*P2_VTH12*/ ++#define RSTV0910_P2_VTH12 0xf334 ++#define FSTV0910_P2_VTH12 0xf33400ff ++ ++/*P2_VTH23*/ ++#define RSTV0910_P2_VTH23 0xf335 ++#define FSTV0910_P2_VTH23 0xf33500ff ++ ++/*P2_VTH34*/ ++#define RSTV0910_P2_VTH34 0xf336 ++#define FSTV0910_P2_VTH34 0xf33600ff ++ ++/*P2_VTH56*/ ++#define RSTV0910_P2_VTH56 0xf337 ++#define FSTV0910_P2_VTH56 0xf33700ff ++ ++/*P2_VTH67*/ ++#define RSTV0910_P2_VTH67 0xf338 ++#define FSTV0910_P2_VTH67 0xf33800ff ++ ++/*P2_VTH78*/ ++#define RSTV0910_P2_VTH78 0xf339 ++#define FSTV0910_P2_VTH78 0xf33900ff ++ ++/*P2_VITCURPUN*/ ++#define RSTV0910_P2_VITCURPUN 0xf33a ++#define FSTV0910_P2_CYCLESLIP_VIT 0xf33a0080 ++#define FSTV0910_P2_VIT_ROTA180 0xf33a0040 ++#define FSTV0910_P2_VIT_ROTA90 0xf33a0020 ++#define FSTV0910_P2_VIT_CURPUN 0xf33a001f ++ ++/*P2_VERROR*/ ++#define RSTV0910_P2_VERROR 0xf33b ++#define FSTV0910_P2_REGERR_VIT 0xf33b00ff ++ ++/*P2_PRVIT*/ ++#define RSTV0910_P2_PRVIT 0xf33c ++#define FSTV0910_P2_DIS_VTHLOCK 0xf33c0040 ++#define FSTV0910_P2_E7_8VIT 0xf33c0020 ++#define FSTV0910_P2_E6_7VIT 0xf33c0010 ++#define FSTV0910_P2_E5_6VIT 0xf33c0008 ++#define FSTV0910_P2_E3_4VIT 0xf33c0004 ++#define FSTV0910_P2_E2_3VIT 0xf33c0002 ++#define FSTV0910_P2_E1_2VIT 0xf33c0001 ++ ++/*P2_VAVSRVIT*/ ++#define RSTV0910_P2_VAVSRVIT 0xf33d ++#define FSTV0910_P2_AMVIT 0xf33d0080 ++#define FSTV0910_P2_FROZENVIT 0xf33d0040 ++#define FSTV0910_P2_SNVIT 0xf33d0030 ++#define FSTV0910_P2_TOVVIT 0xf33d000c ++#define FSTV0910_P2_HYPVIT 0xf33d0003 ++ ++/*P2_VSTATUSVIT*/ ++#define RSTV0910_P2_VSTATUSVIT 0xf33e ++#define FSTV0910_P2_VITERBI_ON 0xf33e0080 ++#define FSTV0910_P2_END_LOOPVIT 0xf33e0040 ++#define FSTV0910_P2_VITERBI_DEPRF 0xf33e0020 ++#define FSTV0910_P2_PRFVIT 0xf33e0010 ++#define FSTV0910_P2_LOCKEDVIT 0xf33e0008 ++#define FSTV0910_P2_VITERBI_DELOCK 0xf33e0004 ++#define FSTV0910_P2_VIT_DEMODSEL 0xf33e0002 ++#define FSTV0910_P2_VITERBI_COMPOUT 0xf33e0001 ++ ++/*P2_VTHINUSE*/ ++#define RSTV0910_P2_VTHINUSE 0xf33f ++#define FSTV0910_P2_VIT_INUSE 0xf33f00ff ++ ++/*P2_KDIV12*/ ++#define RSTV0910_P2_KDIV12 0xf340 ++#define FSTV0910_P2_KDIV12_MANUAL 0xf3400080 ++#define FSTV0910_P2_K_DIVIDER_12 0xf340007f ++ ++/*P2_KDIV23*/ ++#define RSTV0910_P2_KDIV23 0xf341 ++#define FSTV0910_P2_KDIV23_MANUAL 0xf3410080 ++#define FSTV0910_P2_K_DIVIDER_23 0xf341007f ++ ++/*P2_KDIV34*/ ++#define RSTV0910_P2_KDIV34 0xf342 ++#define FSTV0910_P2_KDIV34_MANUAL 0xf3420080 ++#define FSTV0910_P2_K_DIVIDER_34 0xf342007f ++ ++/*P2_KDIV56*/ ++#define RSTV0910_P2_KDIV56 0xf343 ++#define FSTV0910_P2_KDIV56_MANUAL 0xf3430080 ++#define FSTV0910_P2_K_DIVIDER_56 0xf343007f ++ ++/*P2_KDIV67*/ ++#define RSTV0910_P2_KDIV67 0xf344 ++#define FSTV0910_P2_KDIV67_MANUAL 0xf3440080 ++#define FSTV0910_P2_K_DIVIDER_67 0xf344007f ++ ++/*P2_KDIV78*/ ++#define RSTV0910_P2_KDIV78 0xf345 ++#define FSTV0910_P2_KDIV78_MANUAL 0xf3450080 ++#define FSTV0910_P2_K_DIVIDER_78 0xf345007f ++ ++/*P2_PDELCTRL0*/ ++#define RSTV0910_P2_PDELCTRL0 0xf34f ++#define FSTV0910_P2_ISIOBS_MODE 0xf34f0030 ++#define FSTV0910_P2_PDELDIS_BITWISE 0xf34f0004 ++ ++/*P2_PDELCTRL1*/ ++#define RSTV0910_P2_PDELCTRL1 0xf350 ++#define FSTV0910_P2_INV_MISMASK 0xf3500080 ++#define FSTV0910_P2_FORCE_ACCEPTED 0xf3500040 ++#define FSTV0910_P2_FILTER_EN 0xf3500020 ++#define FSTV0910_P2_FORCE_PKTDELINUSE 0xf3500010 ++#define FSTV0910_P2_HYSTEN 0xf3500008 ++#define FSTV0910_P2_HYSTSWRST 0xf3500004 ++#define FSTV0910_P2_EN_MIS00 0xf3500002 ++#define FSTV0910_P2_ALGOSWRST 0xf3500001 ++ ++/*P2_PDELCTRL2*/ ++#define RSTV0910_P2_PDELCTRL2 0xf351 ++#define FSTV0910_P2_FORCE_CONTINUOUS 0xf3510080 ++#define FSTV0910_P2_RESET_UPKO_COUNT 0xf3510040 ++#define FSTV0910_P2_USER_PKTDELIN_NB 0xf3510020 ++#define FSTV0910_P2_DATA_UNBBSCRAMBLED 0xf3510008 ++#define FSTV0910_P2_FORCE_LONGPKT 0xf3510004 ++#define FSTV0910_P2_FRAME_MODE 0xf3510002 ++ ++/*P2_HYSTTHRESH*/ ++#define RSTV0910_P2_HYSTTHRESH 0xf354 ++#define FSTV0910_P2_DELIN_LOCKTHRES 0xf35400f0 ++#define FSTV0910_P2_DELIN_UNLOCKTHRES 0xf354000f ++ ++/*P2_ISIENTRY*/ ++#define RSTV0910_P2_ISIENTRY 0xf35e ++#define FSTV0910_P2_ISI_ENTRY 0xf35e00ff ++ ++/*P2_ISIBITENA*/ ++#define RSTV0910_P2_ISIBITENA 0xf35f ++#define FSTV0910_P2_ISI_BIT_EN 0xf35f00ff ++ ++/*P2_MATSTR1*/ ++#define RSTV0910_P2_MATSTR1 0xf360 ++#define FSTV0910_P2_MATYPE_CURRENT1 0xf36000ff ++ ++/*P2_MATSTR0*/ ++#define RSTV0910_P2_MATSTR0 0xf361 ++#define FSTV0910_P2_MATYPE_CURRENT0 0xf36100ff ++ ++/*P2_UPLSTR1*/ ++#define RSTV0910_P2_UPLSTR1 0xf362 ++#define FSTV0910_P2_UPL_CURRENT1 0xf36200ff ++ ++/*P2_UPLSTR0*/ ++#define RSTV0910_P2_UPLSTR0 0xf363 ++#define FSTV0910_P2_UPL_CURRENT0 0xf36300ff ++ ++/*P2_DFLSTR1*/ ++#define RSTV0910_P2_DFLSTR1 0xf364 ++#define FSTV0910_P2_DFL_CURRENT1 0xf36400ff ++ ++/*P2_DFLSTR0*/ ++#define RSTV0910_P2_DFLSTR0 0xf365 ++#define FSTV0910_P2_DFL_CURRENT0 0xf36500ff ++ ++/*P2_SYNCSTR*/ ++#define RSTV0910_P2_SYNCSTR 0xf366 ++#define FSTV0910_P2_SYNC_CURRENT 0xf36600ff ++ ++/*P2_SYNCDSTR1*/ ++#define RSTV0910_P2_SYNCDSTR1 0xf367 ++#define FSTV0910_P2_SYNCD_CURRENT1 0xf36700ff ++ ++/*P2_SYNCDSTR0*/ ++#define RSTV0910_P2_SYNCDSTR0 0xf368 ++#define FSTV0910_P2_SYNCD_CURRENT0 0xf36800ff ++ ++/*P2_PDELSTATUS1*/ ++#define RSTV0910_P2_PDELSTATUS1 0xf369 ++#define FSTV0910_P2_PKTDELIN_DELOCK 0xf3690080 ++#define FSTV0910_P2_SYNCDUPDFL_BADDFL 0xf3690040 ++#define FSTV0910_P2_CONTINUOUS_STREAM 0xf3690020 ++#define FSTV0910_P2_UNACCEPTED_STREAM 0xf3690010 ++#define FSTV0910_P2_BCH_ERROR_FLAG 0xf3690008 ++#define FSTV0910_P2_BBHCRCKO 0xf3690004 ++#define FSTV0910_P2_PKTDELIN_LOCK 0xf3690002 ++#define FSTV0910_P2_FIRST_LOCK 0xf3690001 ++ ++/*P2_PDELSTATUS2*/ ++#define RSTV0910_P2_PDELSTATUS2 0xf36a ++#define FSTV0910_P2_PKTDEL_DEMODSEL 0xf36a0080 ++#define FSTV0910_P2_FRAME_MODCOD 0xf36a007c ++#define FSTV0910_P2_FRAME_TYPE 0xf36a0003 ++ ++/*P2_BBFCRCKO1*/ ++#define RSTV0910_P2_BBFCRCKO1 0xf36b ++#define FSTV0910_P2_BBHCRC_KOCNT1 0xf36b00ff ++ ++/*P2_BBFCRCKO0*/ ++#define RSTV0910_P2_BBFCRCKO0 0xf36c ++#define FSTV0910_P2_BBHCRC_KOCNT0 0xf36c00ff ++ ++/*P2_UPCRCKO1*/ ++#define RSTV0910_P2_UPCRCKO1 0xf36d ++#define FSTV0910_P2_PKTCRC_KOCNT1 0xf36d00ff ++ ++/*P2_UPCRCKO0*/ ++#define RSTV0910_P2_UPCRCKO0 0xf36e ++#define FSTV0910_P2_PKTCRC_KOCNT0 0xf36e00ff ++ ++/*P2_PDELCTRL3*/ ++#define RSTV0910_P2_PDELCTRL3 0xf36f ++#define FSTV0910_P2_PKTDEL_CONTFAIL 0xf36f0080 ++#define FSTV0910_P2_PKTDEL_ENLONGPKT 0xf36f0040 ++#define FSTV0910_P2_NOFIFO_BCHERR 0xf36f0020 ++#define FSTV0910_P2_PKTDELIN_DELACMERR 0xf36f0010 ++#define FSTV0910_P2_SATURATE_BBPKTKO 0xf36f0004 ++#define FSTV0910_P2_PKTDEL_BCHERRCONT 0xf36f0002 ++#define FSTV0910_P2_ETHERNET_DISFCS 0xf36f0001 ++ ++/*P2_TSSTATEM*/ ++#define RSTV0910_P2_TSSTATEM 0xf370 ++#define FSTV0910_P2_TSDIL_ON 0xf3700080 ++#define FSTV0910_P2_TSSKIPRS_ON 0xf3700040 ++#define FSTV0910_P2_TSRS_ON 0xf3700020 ++#define FSTV0910_P2_TSDESCRAMB_ON 0xf3700010 ++#define FSTV0910_P2_TSFRAME_MODE 0xf3700008 ++#define FSTV0910_P2_TS_DISABLE 0xf3700004 ++#define FSTV0910_P2_TSACM_MODE 0xf3700002 ++#define FSTV0910_P2_TSOUT_NOSYNC 0xf3700001 ++ ++/*P2_TSCFGH*/ ++#define RSTV0910_P2_TSCFGH 0xf372 ++#define FSTV0910_P2_TSFIFO_DVBCI 0xf3720080 ++#define FSTV0910_P2_TSFIFO_SERIAL 0xf3720040 ++#define FSTV0910_P2_TSFIFO_TEIUPDATE 0xf3720020 ++#define FSTV0910_P2_TSFIFO_DUTY50 0xf3720010 ++#define FSTV0910_P2_TSFIFO_HSGNLOUT 0xf3720008 ++#define FSTV0910_P2_TSFIFO_ERRMODE 0xf3720006 ++#define FSTV0910_P2_RST_HWARE 0xf3720001 ++ ++/*P2_TSCFGM*/ ++#define RSTV0910_P2_TSCFGM 0xf373 ++#define FSTV0910_P2_TSFIFO_MANSPEED 0xf37300c0 ++#define FSTV0910_P2_TSFIFO_PERMDATA 0xf3730020 ++#define FSTV0910_P2_TSFIFO_NONEWSGNL 0xf3730010 ++#define FSTV0910_P2_NPD_SPECDVBS2 0xf3730004 ++#define FSTV0910_P2_TSFIFO_DPUNACTIVE 0xf3730002 ++#define FSTV0910_P2_TSFIFO_INVDATA 0xf3730001 ++ ++/*P2_TSCFGL*/ ++#define RSTV0910_P2_TSCFGL 0xf374 ++#define FSTV0910_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 ++#define FSTV0910_P2_BCHERROR_MODE 0xf3740030 ++#define FSTV0910_P2_TSFIFO_NSGNL2DATA 0xf3740008 ++#define FSTV0910_P2_TSFIFO_EMBINDVB 0xf3740004 ++#define FSTV0910_P2_TSFIFO_BITSPEED 0xf3740003 ++ ++/*P2_TSINSDELH*/ ++#define RSTV0910_P2_TSINSDELH 0xf376 ++#define FSTV0910_P2_TSDEL_SYNCBYTE 0xf3760080 ++#define FSTV0910_P2_TSDEL_XXHEADER 0xf3760040 ++#define FSTV0910_P2_TSDEL_BBHEADER 0xf3760020 ++#define FSTV0910_P2_TSDEL_DATAFIELD 0xf3760010 ++#define FSTV0910_P2_TSINSDEL_ISCR 0xf3760008 ++#define FSTV0910_P2_TSINSDEL_NPD 0xf3760004 ++#define FSTV0910_P2_TSINSDEL_RSPARITY 0xf3760002 ++#define FSTV0910_P2_TSINSDEL_CRC8 0xf3760001 ++ ++/*P2_TSDIVN*/ ++#define RSTV0910_P2_TSDIVN 0xf379 ++#define FSTV0910_P2_TSFIFO_SPEEDMODE 0xf37900c0 ++#define FSTV0910_P2_BYTE_OVERSAMPLING 0xf3790038 ++#define FSTV0910_P2_TSFIFO_RISEOK 0xf3790007 ++ ++/*P2_TSCFG4*/ ++#define RSTV0910_P2_TSCFG4 0xf37a ++#define FSTV0910_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0 ++#define FSTV0910_P2_TSFIFO_HIERSEL 0xf37a0020 ++#define FSTV0910_P2_TSFIFO_SPECTOKEN 0xf37a0010 ++#define FSTV0910_P2_TSFIFO_MAXMODE 0xf37a0008 ++#define FSTV0910_P2_TSFIFO_FRFORCEPKT 0xf37a0004 ++#define FSTV0910_P2_EXT_FECSPYIN 0xf37a0002 ++#define FSTV0910_P2_TSFIFO_DELSPEEDUP 0xf37a0001 ++ ++/*P2_TSSPEED*/ ++#define RSTV0910_P2_TSSPEED 0xf380 ++#define FSTV0910_P2_TSFIFO_OUTSPEED 0xf38000ff ++ ++/*P2_TSSTATUS*/ ++#define RSTV0910_P2_TSSTATUS 0xf381 ++#define FSTV0910_P2_TSFIFO_LINEOK 0xf3810080 ++#define FSTV0910_P2_TSFIFO_ERROR 0xf3810040 ++#define FSTV0910_P2_TSFIFO_DATA7 0xf3810020 ++#define FSTV0910_P2_TSFIFO_NOSYNC 0xf3810010 ++#define FSTV0910_P2_ISCR_INITIALIZED 0xf3810008 ++#define FSTV0910_P2_TSREGUL_ERROR 0xf3810004 ++#define FSTV0910_P2_SOFFIFO_UNREGUL 0xf3810002 ++#define FSTV0910_P2_DIL_READY 0xf3810001 ++ ++/*P2_TSSTATUS2*/ ++#define RSTV0910_P2_TSSTATUS2 0xf382 ++#define FSTV0910_P2_TSFIFO_DEMODSEL 0xf3820080 ++#define FSTV0910_P2_TSFIFOSPEED_STORE 0xf3820040 ++#define FSTV0910_P2_DILXX_RESET 0xf3820020 ++#define FSTV0910_P2_TSSPEED_IMPOSSIBLE 0xf3820010 ++#define FSTV0910_P2_TSFIFO_LINENOK 0xf3820008 ++#define FSTV0910_P2_TSFIFO_MUXSTREAM 0xf3820004 ++#define FSTV0910_P2_SCRAMBDETECT 0xf3820002 ++#define FSTV0910_P2_ULDTV67_FALSELOCK 0xf3820001 ++ ++/*P2_TSBITRATE1*/ ++#define RSTV0910_P2_TSBITRATE1 0xf383 ++#define FSTV0910_P2_TSFIFO_BITRATE1 0xf38300ff ++ ++/*P2_TSBITRATE0*/ ++#define RSTV0910_P2_TSBITRATE0 0xf384 ++#define FSTV0910_P2_TSFIFO_BITRATE0 0xf38400ff ++ ++/*P2_ERRCTRL1*/ ++#define RSTV0910_P2_ERRCTRL1 0xf398 ++#define FSTV0910_P2_ERR_SOURCE1 0xf39800f0 ++#define FSTV0910_P2_NUM_EVENT1 0xf3980007 ++ ++/*P2_ERRCNT12*/ ++#define RSTV0910_P2_ERRCNT12 0xf399 ++#define FSTV0910_P2_ERRCNT1_OLDVALUE 0xf3990080 ++#define FSTV0910_P2_ERR_CNT12 0xf399007f ++ ++/*P2_ERRCNT11*/ ++#define RSTV0910_P2_ERRCNT11 0xf39a ++#define FSTV0910_P2_ERR_CNT11 0xf39a00ff ++ ++/*P2_ERRCNT10*/ ++#define RSTV0910_P2_ERRCNT10 0xf39b ++#define FSTV0910_P2_ERR_CNT10 0xf39b00ff ++ ++/*P2_ERRCTRL2*/ ++#define RSTV0910_P2_ERRCTRL2 0xf39c ++#define FSTV0910_P2_ERR_SOURCE2 0xf39c00f0 ++#define FSTV0910_P2_NUM_EVENT2 0xf39c0007 ++ ++/*P2_ERRCNT22*/ ++#define RSTV0910_P2_ERRCNT22 0xf39d ++#define FSTV0910_P2_ERRCNT2_OLDVALUE 0xf39d0080 ++#define FSTV0910_P2_ERR_CNT22 0xf39d007f ++ ++/*P2_ERRCNT21*/ ++#define RSTV0910_P2_ERRCNT21 0xf39e ++#define FSTV0910_P2_ERR_CNT21 0xf39e00ff ++ ++/*P2_ERRCNT20*/ ++#define RSTV0910_P2_ERRCNT20 0xf39f ++#define FSTV0910_P2_ERR_CNT20 0xf39f00ff ++ ++/*P2_FECSPY*/ ++#define RSTV0910_P2_FECSPY 0xf3a0 ++#define FSTV0910_P2_SPY_ENABLE 0xf3a00080 ++#define FSTV0910_P2_NO_SYNCBYTE 0xf3a00040 ++#define FSTV0910_P2_SERIAL_MODE 0xf3a00020 ++#define FSTV0910_P2_UNUSUAL_PACKET 0xf3a00010 ++#define FSTV0910_P2_BERMETER_DATAMODE 0xf3a0000c ++#define FSTV0910_P2_BERMETER_LMODE 0xf3a00002 ++#define FSTV0910_P2_BERMETER_RESET 0xf3a00001 ++ ++/*P2_FSPYCFG*/ ++#define RSTV0910_P2_FSPYCFG 0xf3a1 ++#define FSTV0910_P2_FECSPY_INPUT 0xf3a100c0 ++#define FSTV0910_P2_RST_ON_ERROR 0xf3a10020 ++#define FSTV0910_P2_ONE_SHOT 0xf3a10010 ++#define FSTV0910_P2_I2C_MODE 0xf3a1000c ++#define FSTV0910_P2_SPY_HYSTERESIS 0xf3a10003 ++ ++/*P2_FSPYDATA*/ ++#define RSTV0910_P2_FSPYDATA 0xf3a2 ++#define FSTV0910_P2_SPY_STUFFING 0xf3a20080 ++#define FSTV0910_P2_NOERROR_PKTJITTER 0xf3a20040 ++#define FSTV0910_P2_SPY_CNULLPKT 0xf3a20020 ++#define FSTV0910_P2_SPY_OUTDATA_MODE 0xf3a2001f ++ ++/*P2_FSPYOUT*/ ++#define RSTV0910_P2_FSPYOUT 0xf3a3 ++#define FSTV0910_P2_FSPY_DIRECT 0xf3a30080 ++#define FSTV0910_P2_SPY_OUTDATA_BUS 0xf3a30038 ++#define FSTV0910_P2_STUFF_MODE 0xf3a30007 ++ ++/*P2_FSTATUS*/ ++#define RSTV0910_P2_FSTATUS 0xf3a4 ++#define FSTV0910_P2_SPY_ENDSIM 0xf3a40080 ++#define FSTV0910_P2_VALID_SIM 0xf3a40040 ++#define FSTV0910_P2_FOUND_SIGNAL 0xf3a40020 ++#define FSTV0910_P2_DSS_SYNCBYTE 0xf3a40010 ++#define FSTV0910_P2_RESULT_STATE 0xf3a4000f ++ ++/*P2_FBERCPT4*/ ++#define RSTV0910_P2_FBERCPT4 0xf3a8 ++#define FSTV0910_P2_FBERMETER_CPT4 0xf3a800ff ++ ++/*P2_FBERCPT3*/ ++#define RSTV0910_P2_FBERCPT3 0xf3a9 ++#define FSTV0910_P2_FBERMETER_CPT3 0xf3a900ff ++ ++/*P2_FBERCPT2*/ ++#define RSTV0910_P2_FBERCPT2 0xf3aa ++#define FSTV0910_P2_FBERMETER_CPT2 0xf3aa00ff ++ ++/*P2_FBERCPT1*/ ++#define RSTV0910_P2_FBERCPT1 0xf3ab ++#define FSTV0910_P2_FBERMETER_CPT1 0xf3ab00ff ++ ++/*P2_FBERCPT0*/ ++#define RSTV0910_P2_FBERCPT0 0xf3ac ++#define FSTV0910_P2_FBERMETER_CPT0 0xf3ac00ff ++ ++/*P2_FBERERR2*/ ++#define RSTV0910_P2_FBERERR2 0xf3ad ++#define FSTV0910_P2_FBERMETER_ERR2 0xf3ad00ff ++ ++/*P2_FBERERR1*/ ++#define RSTV0910_P2_FBERERR1 0xf3ae ++#define FSTV0910_P2_FBERMETER_ERR1 0xf3ae00ff ++ ++/*P2_FBERERR0*/ ++#define RSTV0910_P2_FBERERR0 0xf3af ++#define FSTV0910_P2_FBERMETER_ERR0 0xf3af00ff ++ ++/*P2_FSPYBER*/ ++#define RSTV0910_P2_FSPYBER 0xf3b2 ++#define FSTV0910_P2_FSPYOBS_XORREAD 0xf3b20040 ++#define FSTV0910_P2_FSPYBER_OBSMODE 0xf3b20020 ++#define FSTV0910_P2_FSPYBER_SYNCBYTE 0xf3b20010 ++#define FSTV0910_P2_FSPYBER_UNSYNC 0xf3b20008 ++#define FSTV0910_P2_FSPYBER_CTIME 0xf3b20007 ++ ++/*P2_SFERROR*/ ++#define RSTV0910_P2_SFERROR 0xf3c1 ++#define FSTV0910_P2_SFEC_REGERR_VIT 0xf3c100ff ++ ++/*P2_SFECSTATUS*/ ++#define RSTV0910_P2_SFECSTATUS 0xf3c3 ++#define FSTV0910_P2_SFEC_ON 0xf3c30080 ++#define FSTV0910_P2_SFEC_OFF 0xf3c30040 ++#define FSTV0910_P2_LOCKEDSFEC 0xf3c30008 ++#define FSTV0910_P2_SFEC_DELOCK 0xf3c30004 ++#define FSTV0910_P2_SFEC_DEMODSEL 0xf3c30002 ++#define FSTV0910_P2_SFEC_OVFON 0xf3c30001 ++ ++/*P2_SFKDIV12*/ ++#define RSTV0910_P2_SFKDIV12 0xf3c4 ++#define FSTV0910_P2_SFECKDIV12_MAN 0xf3c40080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_12 0xf3c4007f ++ ++/*P2_SFKDIV23*/ ++#define RSTV0910_P2_SFKDIV23 0xf3c5 ++#define FSTV0910_P2_SFECKDIV23_MAN 0xf3c50080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_23 0xf3c5007f ++ ++/*P2_SFKDIV34*/ ++#define RSTV0910_P2_SFKDIV34 0xf3c6 ++#define FSTV0910_P2_SFECKDIV34_MAN 0xf3c60080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_34 0xf3c6007f ++ ++/*P2_SFKDIV56*/ ++#define RSTV0910_P2_SFKDIV56 0xf3c7 ++#define FSTV0910_P2_SFECKDIV56_MAN 0xf3c70080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_56 0xf3c7007f ++ ++/*P2_SFKDIV67*/ ++#define RSTV0910_P2_SFKDIV67 0xf3c8 ++#define FSTV0910_P2_SFECKDIV67_MAN 0xf3c80080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_67 0xf3c8007f ++ ++/*P2_SFKDIV78*/ ++#define RSTV0910_P2_SFKDIV78 0xf3c9 ++#define FSTV0910_P2_SFECKDIV78_MAN 0xf3c90080 ++#define FSTV0910_P2_SFEC_K_DIVIDER_78 0xf3c9007f ++ ++/*P2_SFSTATUS*/ ++#define RSTV0910_P2_SFSTATUS 0xf3cc ++#define FSTV0910_P2_SFEC_LINEOK 0xf3cc0080 ++#define FSTV0910_P2_SFEC_ERROR 0xf3cc0040 ++#define FSTV0910_P2_SFEC_DATA7 0xf3cc0020 ++#define FSTV0910_P2_SFEC_PKTDNBRFAIL 0xf3cc0010 ++#define FSTV0910_P2_TSSFEC_DEMODSEL 0xf3cc0008 ++#define FSTV0910_P2_SFEC_NOSYNC 0xf3cc0004 ++#define FSTV0910_P2_SFEC_UNREGULA 0xf3cc0002 ++#define FSTV0910_P2_SFEC_READY 0xf3cc0001 ++ ++/*P2_SFDLYSET2*/ ++#define RSTV0910_P2_SFDLYSET2 0xf3d0 ++#define FSTV0910_P2_SFEC_OFFSET 0xf3d000c0 ++#define FSTV0910_P2_RST_SFEC 0xf3d00008 ++#define FSTV0910_P2_DILDLINE_ERROR 0xf3d00004 ++#define FSTV0910_P2_SFEC_DISABLE 0xf3d00002 ++#define FSTV0910_P2_SFEC_UNREGUL 0xf3d00001 ++ ++/*P2_SFERRCTRL*/ ++#define RSTV0910_P2_SFERRCTRL 0xf3d8 ++#define FSTV0910_P2_SFEC_ERR_SOURCE 0xf3d800f0 ++#define FSTV0910_P2_SFEC_NUM_EVENT 0xf3d80007 ++ ++/*P2_SFERRCNT2*/ ++#define RSTV0910_P2_SFERRCNT2 0xf3d9 ++#define FSTV0910_P2_SFERRC_OLDVALUE 0xf3d90080 ++#define FSTV0910_P2_SFEC_ERR_CNT2 0xf3d9007f ++ ++/*P2_SFERRCNT1*/ ++#define RSTV0910_P2_SFERRCNT1 0xf3da ++#define FSTV0910_P2_SFEC_ERR_CNT1 0xf3da00ff ++ ++/*P2_SFERRCNT0*/ ++#define RSTV0910_P2_SFERRCNT0 0xf3db ++#define FSTV0910_P2_SFEC_ERR_CNT0 0xf3db00ff ++ ++/*P1_IQCONST*/ ++#define RSTV0910_P1_IQCONST 0xf400 ++#define FSTV0910_P1_CONSTEL_SELECT 0xf4000060 ++#define FSTV0910_P1_IQSYMB_SEL 0xf400001f ++ ++/*P1_NOSCFG*/ ++#define RSTV0910_P1_NOSCFG 0xf401 ++#define FSTV0910_P1_DIS_ACMRATIO 0xf4010080 ++#define FSTV0910_P1_NOSIN_EGALSEL 0xf4010040 ++#define FSTV0910_P1_DUMMYPL_NOSDATA 0xf4010020 ++#define FSTV0910_P1_NOSPLH_BETA 0xf4010018 ++#define FSTV0910_P1_NOSDATA_BETA 0xf4010007 ++ ++/*P1_ISYMB*/ ++#define RSTV0910_P1_ISYMB 0xf402 ++#define FSTV0910_P1_I_SYMBOL 0xf40201ff ++ ++/*P1_QSYMB*/ ++#define RSTV0910_P1_QSYMB 0xf403 ++#define FSTV0910_P1_Q_SYMBOL 0xf40301ff ++ ++/*P1_AGC1CFG*/ ++#define RSTV0910_P1_AGC1CFG 0xf404 ++#define FSTV0910_P1_DC_FROZEN 0xf4040080 ++#define FSTV0910_P1_DC_CORRECT 0xf4040040 ++#define FSTV0910_P1_AMM_FROZEN 0xf4040020 ++#define FSTV0910_P1_AMM_CORRECT 0xf4040010 ++#define FSTV0910_P1_QUAD_FROZEN 0xf4040008 ++#define FSTV0910_P1_QUAD_CORRECT 0xf4040004 ++#define FSTV0910_P1_DCCOMP_SLOW 0xf4040002 ++#define FSTV0910_P1_IQMISM_SLOW 0xf4040001 ++ ++/*P1_AGC1CN*/ ++#define RSTV0910_P1_AGC1CN 0xf406 ++#define FSTV0910_P1_AGC1_LOCKED 0xf4060080 ++#define FSTV0910_P1_AGC1_OVERFLOW 0xf4060040 ++#define FSTV0910_P1_AGC1_NOSLOWLK 0xf4060020 ++#define FSTV0910_P1_AGC1_MINPOWER 0xf4060010 ++#define FSTV0910_P1_AGCOUT_FAST 0xf4060008 ++#define FSTV0910_P1_AGCIQ_BETA 0xf4060007 ++ ++/*P1_AGC1REF*/ ++#define RSTV0910_P1_AGC1REF 0xf407 ++#define FSTV0910_P1_AGCIQ_REF 0xf40700ff ++ ++/*P1_IDCCOMP*/ ++#define RSTV0910_P1_IDCCOMP 0xf408 ++#define FSTV0910_P1_IAVERAGE_ADJ 0xf40801ff ++ ++/*P1_QDCCOMP*/ ++#define RSTV0910_P1_QDCCOMP 0xf409 ++#define FSTV0910_P1_QAVERAGE_ADJ 0xf40901ff ++ ++/*P1_POWERI*/ ++#define RSTV0910_P1_POWERI 0xf40a ++#define FSTV0910_P1_POWER_I 0xf40a00ff ++ ++/*P1_POWERQ*/ ++#define RSTV0910_P1_POWERQ 0xf40b ++#define FSTV0910_P1_POWER_Q 0xf40b00ff ++ ++/*P1_AGC1AMM*/ ++#define RSTV0910_P1_AGC1AMM 0xf40c ++#define FSTV0910_P1_AMM_VALUE 0xf40c00ff ++ ++/*P1_AGC1QUAD*/ ++#define RSTV0910_P1_AGC1QUAD 0xf40d ++#define FSTV0910_P1_QUAD_VALUE 0xf40d01ff ++ ++/*P1_AGCIQIN1*/ ++#define RSTV0910_P1_AGCIQIN1 0xf40e ++#define FSTV0910_P1_AGCIQ_VALUE1 0xf40e00ff ++ ++/*P1_AGCIQIN0*/ ++#define RSTV0910_P1_AGCIQIN0 0xf40f ++#define FSTV0910_P1_AGCIQ_VALUE0 0xf40f00ff ++ ++/*P1_DEMOD*/ ++#define RSTV0910_P1_DEMOD 0xf410 ++#define FSTV0910_P1_MANUALS2_ROLLOFF 0xf4100080 ++#define FSTV0910_P1_SPECINV_CONTROL 0xf4100030 ++#define FSTV0910_P1_MANUALSX_ROLLOFF 0xf4100004 ++#define FSTV0910_P1_ROLLOFF_CONTROL 0xf4100003 ++ ++/*P1_DMDMODCOD*/ ++#define RSTV0910_P1_DMDMODCOD 0xf411 ++#define FSTV0910_P1_MANUAL_MODCOD 0xf4110080 ++#define FSTV0910_P1_DEMOD_MODCOD 0xf411007c ++#define FSTV0910_P1_DEMOD_TYPE 0xf4110003 ++ ++/*P1_DSTATUS*/ ++#define RSTV0910_P1_DSTATUS 0xf412 ++#define FSTV0910_P1_CAR_LOCK 0xf4120080 ++#define FSTV0910_P1_TMGLOCK_QUALITY 0xf4120060 ++#define FSTV0910_P1_SDVBS1_ENABLE 0xf4120010 ++#define FSTV0910_P1_LOCK_DEFINITIF 0xf4120008 ++#define FSTV0910_P1_TIMING_IS_LOCKED 0xf4120004 ++#define FSTV0910_P1_DEMOD_SYSCFG 0xf4120002 ++#define FSTV0910_P1_OVADC_DETECT 0xf4120001 ++ ++/*P1_DSTATUS2*/ ++#define RSTV0910_P1_DSTATUS2 0xf413 ++#define FSTV0910_P1_DEMOD_DELOCK 0xf4130080 ++#define FSTV0910_P1_DEMOD_TIMEOUT 0xf4130040 ++#define FSTV0910_P1_MODCODRQ_SYNCTAG 0xf4130020 ++#define FSTV0910_P1_POLYPH_SATEVENT 0xf4130010 ++#define FSTV0910_P1_AGC1_NOSIGNALACK 0xf4130008 ++#define FSTV0910_P1_AGC2_OVERFLOW 0xf4130004 ++#define FSTV0910_P1_CFR_OVERFLOW 0xf4130002 ++#define FSTV0910_P1_GAMMA_OVERUNDER 0xf4130001 ++ ++/*P1_DMDCFGMD*/ ++#define RSTV0910_P1_DMDCFGMD 0xf414 ++#define FSTV0910_P1_DVBS2_ENABLE 0xf4140080 ++#define FSTV0910_P1_DVBS1_ENABLE 0xf4140040 ++#define FSTV0910_P1_SCAN_ENABLE 0xf4140010 ++#define FSTV0910_P1_CFR_AUTOSCAN 0xf4140008 ++#define FSTV0910_P1_NOFORCE_RELOCK 0xf4140004 ++#define FSTV0910_P1_TUN_RNG 0xf4140003 ++ ++/*P1_DMDCFG2*/ ++#define RSTV0910_P1_DMDCFG2 0xf415 ++#define FSTV0910_P1_AGC1_WAITLOCK 0xf4150080 ++#define FSTV0910_P1_S1S2_SEQUENTIAL 0xf4150040 ++#define FSTV0910_P1_BLINDPEA_MODE 0xf4150020 ++#define FSTV0910_P1_INFINITE_RELOCK 0xf4150010 ++#define FSTV0910_P1_BWOFFSET_COLDWARM 0xf4150008 ++#define FSTV0910_P1_TMGLOCK_NSCANSTOP 0xf4150004 ++#define FSTV0910_P1_COARSE_LK3MODE 0xf4150002 ++#define FSTV0910_P1_COARSE_LK2MODE 0xf4150001 ++ ++/*P1_DMDISTATE*/ ++#define RSTV0910_P1_DMDISTATE 0xf416 ++#define FSTV0910_P1_I2C_NORESETDMODE 0xf4160080 ++#define FSTV0910_P1_FORCE_ETAPED 0xf4160040 ++#define FSTV0910_P1_SDMDRST_DIRCLK 0xf4160020 ++#define FSTV0910_P1_I2C_DEMOD_MODE 0xf416001f ++ ++/*P1_DMDT0M*/ ++#define RSTV0910_P1_DMDT0M 0xf417 ++#define FSTV0910_P1_DMDT0_MIN 0xf41700ff ++ ++/*P1_DMDSTATE*/ ++#define RSTV0910_P1_DMDSTATE 0xf41b ++#define FSTV0910_P1_DEMOD_LOCKED 0xf41b0080 ++#define FSTV0910_P1_HEADER_MODE 0xf41b0060 ++#define FSTV0910_P1_DEMOD_MODE 0xf41b001f ++ ++/*P1_DMDFLYW*/ ++#define RSTV0910_P1_DMDFLYW 0xf41c ++#define FSTV0910_P1_I2C_IRQVAL 0xf41c00f0 ++#define FSTV0910_P1_FLYWHEEL_CPT 0xf41c000f ++ ++/*P1_DSTATUS3*/ ++#define RSTV0910_P1_DSTATUS3 0xf41d ++#define FSTV0910_P1_CFR_ZIGZAG 0xf41d0080 ++#define FSTV0910_P1_DEMOD_CFGMODE 0xf41d0060 ++#define FSTV0910_P1_GAMMA_LOWBAUDRATE 0xf41d0010 ++#define FSTV0910_P1_RELOCK_MODE 0xf41d0008 ++#define FSTV0910_P1_DEMOD_FAIL 0xf41d0004 ++#define FSTV0910_P1_ETAPE1A_DVBXMEM 0xf41d0003 ++ ++/*P1_DMDCFG3*/ ++#define RSTV0910_P1_DMDCFG3 0xf41e ++#define FSTV0910_P1_DVBS1_TMGWAIT 0xf41e0080 ++#define FSTV0910_P1_NO_BWCENTERING 0xf41e0040 ++#define FSTV0910_P1_INV_SEQSRCH 0xf41e0020 ++#define FSTV0910_P1_DIS_SFRUPLOW_TRK 0xf41e0010 ++#define FSTV0910_P1_NOSTOP_FIFOFULL 0xf41e0008 ++#define FSTV0910_P1_LOCKTIME_MODE 0xf41e0007 ++ ++/*P1_DMDCFG4*/ ++#define RSTV0910_P1_DMDCFG4 0xf41f ++#define FSTV0910_P1_DIS_VITLOCK 0xf41f0080 ++#define FSTV0910_P1_S1S2TOUT_FAST 0xf41f0040 ++#define FSTV0910_P1_DEMOD_FASTLOCK 0xf41f0020 ++#define FSTV0910_P1_S1HIER_ENABLE 0xf41f0010 ++#define FSTV0910_P1_TUNER_NRELAUNCH 0xf41f0008 ++#define FSTV0910_P1_DIS_CLKENABLE 0xf41f0004 ++#define FSTV0910_P1_DIS_HDRDIVLOCK 0xf41f0002 ++#define FSTV0910_P1_NO_TNRWBINIT 0xf41f0001 ++ ++/*P1_CORRELMANT*/ ++#define RSTV0910_P1_CORRELMANT 0xf420 ++#define FSTV0910_P1_CORREL_MANT 0xf42000ff ++ ++/*P1_CORRELABS*/ ++#define RSTV0910_P1_CORRELABS 0xf421 ++#define FSTV0910_P1_CORREL_ABS 0xf42100ff ++ ++/*P1_CORRELEXP*/ ++#define RSTV0910_P1_CORRELEXP 0xf422 ++#define FSTV0910_P1_CORREL_ABSEXP 0xf42200f0 ++#define FSTV0910_P1_CORREL_EXP 0xf422000f ++ ++/*P1_PLHMODCOD*/ ++#define RSTV0910_P1_PLHMODCOD 0xf424 ++#define FSTV0910_P1_SPECINV_DEMOD 0xf4240080 ++#define FSTV0910_P1_PLH_MODCOD 0xf424007c ++#define FSTV0910_P1_PLH_TYPE 0xf4240003 ++ ++/*P1_DMDREG*/ ++#define RSTV0910_P1_DMDREG 0xf425 ++#define FSTV0910_P1_EXTPSK_MODE 0xf4250080 ++#define FSTV0910_P1_HIER_SHORTFRAME 0xf4250002 ++#define FSTV0910_P1_DECIM_PLFRAMES 0xf4250001 ++ ++/*P1_AGC2O*/ ++#define RSTV0910_P1_AGC2O 0xf42c ++#define FSTV0910_P1_CSTENV_MODE 0xf42c00c0 ++#define FSTV0910_P1_AGC2_LKSQRT 0xf42c0020 ++#define FSTV0910_P1_AGC2_LKMODE 0xf42c0010 ++#define FSTV0910_P1_AGC2_LKEQUA 0xf42c0008 ++#define FSTV0910_P1_AGC2_COEF 0xf42c0007 ++ ++/*P1_AGC2REF*/ ++#define RSTV0910_P1_AGC2REF 0xf42d ++#define FSTV0910_P1_AGC2_REF 0xf42d00ff ++ ++/*P1_AGC1ADJ*/ ++#define RSTV0910_P1_AGC1ADJ 0xf42e ++#define FSTV0910_P1_AGC1ADJ_MANUAL 0xf42e0080 ++#define FSTV0910_P1_AGC1_ADJUSTED 0xf42e007f ++ ++/*P1_AGC2I1*/ ++#define RSTV0910_P1_AGC2I1 0xf436 ++#define FSTV0910_P1_AGC2_INTEGRATOR1 0xf43600ff ++ ++/*P1_AGC2I0*/ ++#define RSTV0910_P1_AGC2I0 0xf437 ++#define FSTV0910_P1_AGC2_INTEGRATOR0 0xf43700ff ++ ++/*P1_CARCFG*/ ++#define RSTV0910_P1_CARCFG 0xf438 ++#define FSTV0910_P1_CFRUPLOW_AUTO 0xf4380080 ++#define FSTV0910_P1_CFRUPLOW_TEST 0xf4380040 ++#define FSTV0910_P1_WIDE_FREQDET 0xf4380020 ++#define FSTV0910_P1_CARHDR_NODIV8 0xf4380010 ++#define FSTV0910_P1_I2C_ROTA 0xf4380008 ++#define FSTV0910_P1_ROTAON 0xf4380004 ++#define FSTV0910_P1_PH_DET_ALGO 0xf4380003 ++ ++/*P1_ACLC*/ ++#define RSTV0910_P1_ACLC 0xf439 ++#define FSTV0910_P1_CARS1_ANOSAUTO 0xf4390040 ++#define FSTV0910_P1_CAR_ALPHA_MANT 0xf4390030 ++#define FSTV0910_P1_CAR_ALPHA_EXP 0xf439000f ++ ++/*P1_BCLC*/ ++#define RSTV0910_P1_BCLC 0xf43a ++#define FSTV0910_P1_CARS1_BNOSAUTO 0xf43a0040 ++#define FSTV0910_P1_CAR_BETA_MANT 0xf43a0030 ++#define FSTV0910_P1_CAR_BETA_EXP 0xf43a000f ++ ++/*P1_CARFREQ*/ ++#define RSTV0910_P1_CARFREQ 0xf43d ++#define FSTV0910_P1_KC_COARSE_EXP 0xf43d00f0 ++#define FSTV0910_P1_BETA_FREQ 0xf43d000f ++ ++/*P1_CARHDR*/ ++#define RSTV0910_P1_CARHDR 0xf43e ++#define FSTV0910_P1_K_FREQ_HDR 0xf43e00ff ++ ++/*P1_LDT*/ ++#define RSTV0910_P1_LDT 0xf43f ++#define FSTV0910_P1_CARLOCK_THRES 0xf43f01ff ++ ++/*P1_LDT2*/ ++#define RSTV0910_P1_LDT2 0xf440 ++#define FSTV0910_P1_CARLOCK_THRES2 0xf44001ff ++ ++/*P1_CFRICFG*/ ++#define RSTV0910_P1_CFRICFG 0xf441 ++#define FSTV0910_P1_CFRINIT_UNVALRNG 0xf4410080 ++#define FSTV0910_P1_CFRINIT_LUNVALCPT 0xf4410040 ++#define FSTV0910_P1_CFRINIT_ABORTDBL 0xf4410020 ++#define FSTV0910_P1_CFRINIT_ABORTPRED 0xf4410010 ++#define FSTV0910_P1_CFRINIT_UNVALSKIP 0xf4410008 ++#define FSTV0910_P1_CFRINIT_CSTINC 0xf4410004 ++#define FSTV0910_P1_CFRIROLL_GARDER 0xf4410002 ++#define FSTV0910_P1_NEG_CFRSTEP 0xf4410001 ++ ++/*P1_CFRUP1*/ ++#define RSTV0910_P1_CFRUP1 0xf442 ++#define FSTV0910_P1_CFR_UP1 0xf44201ff ++ ++/*P1_CFRUP0*/ ++#define RSTV0910_P1_CFRUP0 0xf443 ++#define FSTV0910_P1_CFR_UP0 0xf44300ff ++ ++/*P1_CFRIBASE1*/ ++#define RSTV0910_P1_CFRIBASE1 0xf444 ++#define FSTV0910_P1_CFRINIT_BASE1 0xf44400ff ++ ++/*P1_CFRIBASE0*/ ++#define RSTV0910_P1_CFRIBASE0 0xf445 ++#define FSTV0910_P1_CFRINIT_BASE0 0xf44500ff ++ ++/*P1_CFRLOW1*/ ++#define RSTV0910_P1_CFRLOW1 0xf446 ++#define FSTV0910_P1_CFR_LOW1 0xf44601ff ++ ++/*P1_CFRLOW0*/ ++#define RSTV0910_P1_CFRLOW0 0xf447 ++#define FSTV0910_P1_CFR_LOW0 0xf44700ff ++ ++/*P1_CFRINIT1*/ ++#define RSTV0910_P1_CFRINIT1 0xf448 ++#define FSTV0910_P1_CFR_INIT1 0xf44801ff ++ ++/*P1_CFRINIT0*/ ++#define RSTV0910_P1_CFRINIT0 0xf449 ++#define FSTV0910_P1_CFR_INIT0 0xf44900ff ++ ++/*P1_CFRINC1*/ ++#define RSTV0910_P1_CFRINC1 0xf44a ++#define FSTV0910_P1_MANUAL_CFRINC 0xf44a0080 ++#define FSTV0910_P1_CFR_INC1 0xf44a003f ++ ++/*P1_CFRINC0*/ ++#define RSTV0910_P1_CFRINC0 0xf44b ++#define FSTV0910_P1_CFR_INC0 0xf44b00ff ++ ++/*P1_CFR2*/ ++#define RSTV0910_P1_CFR2 0xf44c ++#define FSTV0910_P1_CAR_FREQ2 0xf44c01ff ++ ++/*P1_CFR1*/ ++#define RSTV0910_P1_CFR1 0xf44d ++#define FSTV0910_P1_CAR_FREQ1 0xf44d00ff ++ ++/*P1_CFR0*/ ++#define RSTV0910_P1_CFR0 0xf44e ++#define FSTV0910_P1_CAR_FREQ0 0xf44e00ff ++ ++/*P1_LDI*/ ++#define RSTV0910_P1_LDI 0xf44f ++#define FSTV0910_P1_LOCK_DET_INTEGR 0xf44f01ff ++ ++/*P1_TMGCFG*/ ++#define RSTV0910_P1_TMGCFG 0xf450 ++#define FSTV0910_P1_TMGLOCK_BETA 0xf45000c0 ++#define FSTV0910_P1_DO_TIMING_CORR 0xf4500010 ++#define FSTV0910_P1_MANUAL_SCAN 0xf450000c ++#define FSTV0910_P1_TMG_MINFREQ 0xf4500003 ++ ++/*P1_RTC*/ ++#define RSTV0910_P1_RTC 0xf451 ++#define FSTV0910_P1_TMGALPHA_EXP 0xf45100f0 ++#define FSTV0910_P1_TMGBETA_EXP 0xf451000f ++ ++/*P1_RTCS2*/ ++#define RSTV0910_P1_RTCS2 0xf452 ++#define FSTV0910_P1_TMGALPHAS2_EXP 0xf45200f0 ++#define FSTV0910_P1_TMGBETAS2_EXP 0xf452000f ++ ++/*P1_TMGTHRISE*/ ++#define RSTV0910_P1_TMGTHRISE 0xf453 ++#define FSTV0910_P1_TMGLOCK_THRISE 0xf45300ff ++ ++/*P1_TMGTHFALL*/ ++#define RSTV0910_P1_TMGTHFALL 0xf454 ++#define FSTV0910_P1_TMGLOCK_THFALL 0xf45400ff ++ ++/*P1_SFRUPRATIO*/ ++#define RSTV0910_P1_SFRUPRATIO 0xf455 ++#define FSTV0910_P1_SFR_UPRATIO 0xf45500ff ++ ++/*P1_SFRLOWRATIO*/ ++#define RSTV0910_P1_SFRLOWRATIO 0xf456 ++#define FSTV0910_P1_SFR_LOWRATIO 0xf45600ff ++ ++/*P1_KTTMG*/ ++#define RSTV0910_P1_KTTMG 0xf457 ++#define FSTV0910_P1_KT_TMG_EXP 0xf45700f0 ++ ++/*P1_KREFTMG*/ ++#define RSTV0910_P1_KREFTMG 0xf458 ++#define FSTV0910_P1_KREF_TMG 0xf45800ff ++ ++/*P1_SFRSTEP*/ ++#define RSTV0910_P1_SFRSTEP 0xf459 ++#define FSTV0910_P1_SFR_SCANSTEP 0xf45900f0 ++#define FSTV0910_P1_SFR_CENTERSTEP 0xf459000f ++ ++/*P1_TMGCFG2*/ ++#define RSTV0910_P1_TMGCFG2 0xf45a ++#define FSTV0910_P1_KREFTMG2_DECMODE 0xf45a00c0 ++#define FSTV0910_P1_DIS_AUTOSAMP 0xf45a0008 ++#define FSTV0910_P1_SCANINIT_QUART 0xf45a0004 ++#define FSTV0910_P1_NOTMG_DVBS1DERAT 0xf45a0002 ++#define FSTV0910_P1_SFRRATIO_FINE 0xf45a0001 ++ ++/*P1_KREFTMG2*/ ++#define RSTV0910_P1_KREFTMG2 0xf45b ++#define FSTV0910_P1_KREF_TMG2 0xf45b00ff ++ ++/*P1_TMGCFG3*/ ++#define RSTV0910_P1_TMGCFG3 0xf45d ++#define FSTV0910_P1_CFRINC_MODE 0xf45d0070 ++#define FSTV0910_P1_CONT_TMGCENTER 0xf45d0008 ++#define FSTV0910_P1_AUTO_GUP 0xf45d0004 ++#define FSTV0910_P1_AUTO_GLOW 0xf45d0002 ++#define FSTV0910_P1_SFRVAL_MINMODE 0xf45d0001 ++ ++/*P1_SFRINIT1*/ ++#define RSTV0910_P1_SFRINIT1 0xf45e ++#define FSTV0910_P1_SFR_INIT1 0xf45e00ff ++ ++/*P1_SFRINIT0*/ ++#define RSTV0910_P1_SFRINIT0 0xf45f ++#define FSTV0910_P1_SFR_INIT0 0xf45f00ff ++ ++/*P1_SFRUP1*/ ++#define RSTV0910_P1_SFRUP1 0xf460 ++#define FSTV0910_P1_SYMB_FREQ_UP1 0xf46000ff ++ ++/*P1_SFRUP0*/ ++#define RSTV0910_P1_SFRUP0 0xf461 ++#define FSTV0910_P1_SYMB_FREQ_UP0 0xf46100ff ++ ++/*P1_SFRLOW1*/ ++#define RSTV0910_P1_SFRLOW1 0xf462 ++#define FSTV0910_P1_SYMB_FREQ_LOW1 0xf46200ff ++ ++/*P1_SFRLOW0*/ ++#define RSTV0910_P1_SFRLOW0 0xf463 ++#define FSTV0910_P1_SYMB_FREQ_LOW0 0xf46300ff ++ ++/*P1_SFR3*/ ++#define RSTV0910_P1_SFR3 0xf464 ++#define FSTV0910_P1_SYMB_FREQ3 0xf46400ff ++ ++/*P1_SFR2*/ ++#define RSTV0910_P1_SFR2 0xf465 ++#define FSTV0910_P1_SYMB_FREQ2 0xf46500ff ++ ++/*P1_SFR1*/ ++#define RSTV0910_P1_SFR1 0xf466 ++#define FSTV0910_P1_SYMB_FREQ1 0xf46600ff ++ ++/*P1_SFR0*/ ++#define RSTV0910_P1_SFR0 0xf467 ++#define FSTV0910_P1_SYMB_FREQ0 0xf46700ff ++ ++/*P1_TMGREG2*/ ++#define RSTV0910_P1_TMGREG2 0xf468 ++#define FSTV0910_P1_TMGREG2 0xf46800ff ++ ++/*P1_TMGREG1*/ ++#define RSTV0910_P1_TMGREG1 0xf469 ++#define FSTV0910_P1_TMGREG1 0xf46900ff ++ ++/*P1_TMGREG0*/ ++#define RSTV0910_P1_TMGREG0 0xf46a ++#define FSTV0910_P1_TMGREG0 0xf46a00ff ++ ++/*P1_TMGLOCK1*/ ++#define RSTV0910_P1_TMGLOCK1 0xf46b ++#define FSTV0910_P1_TMGLOCK_LEVEL1 0xf46b01ff ++ ++/*P1_TMGLOCK0*/ ++#define RSTV0910_P1_TMGLOCK0 0xf46c ++#define FSTV0910_P1_TMGLOCK_LEVEL0 0xf46c00ff ++ ++/*P1_TMGOBS*/ ++#define RSTV0910_P1_TMGOBS 0xf46d ++#define FSTV0910_P1_ROLLOFF_STATUS 0xf46d00c0 ++#define FSTV0910_P1_SCAN_SIGN 0xf46d0030 ++#define FSTV0910_P1_TMG_SCANNING 0xf46d0008 ++#define FSTV0910_P1_CHCENTERING_MODE 0xf46d0004 ++#define FSTV0910_P1_TMG_SCANFAIL 0xf46d0002 ++ ++/*P1_EQUALCFG*/ ++#define RSTV0910_P1_EQUALCFG 0xf46f ++#define FSTV0910_P1_NOTMG_NEGALWAIT 0xf46f0080 ++#define FSTV0910_P1_EQUAL_ON 0xf46f0040 ++#define FSTV0910_P1_SEL_EQUALCOR 0xf46f0038 ++#define FSTV0910_P1_MU_EQUALDFE 0xf46f0007 ++ ++/*P1_EQUAI1*/ ++#define RSTV0910_P1_EQUAI1 0xf470 ++#define FSTV0910_P1_EQUA_ACCI1 0xf47001ff ++ ++/*P1_EQUAQ1*/ ++#define RSTV0910_P1_EQUAQ1 0xf471 ++#define FSTV0910_P1_EQUA_ACCQ1 0xf47101ff ++ ++/*P1_EQUAI2*/ ++#define RSTV0910_P1_EQUAI2 0xf472 ++#define FSTV0910_P1_EQUA_ACCI2 0xf47201ff ++ ++/*P1_EQUAQ2*/ ++#define RSTV0910_P1_EQUAQ2 0xf473 ++#define FSTV0910_P1_EQUA_ACCQ2 0xf47301ff ++ ++/*P1_EQUAI3*/ ++#define RSTV0910_P1_EQUAI3 0xf474 ++#define FSTV0910_P1_EQUA_ACCI3 0xf47401ff ++ ++/*P1_EQUAQ3*/ ++#define RSTV0910_P1_EQUAQ3 0xf475 ++#define FSTV0910_P1_EQUA_ACCQ3 0xf47501ff ++ ++/*P1_EQUAI4*/ ++#define RSTV0910_P1_EQUAI4 0xf476 ++#define FSTV0910_P1_EQUA_ACCI4 0xf47601ff ++ ++/*P1_EQUAQ4*/ ++#define RSTV0910_P1_EQUAQ4 0xf477 ++#define FSTV0910_P1_EQUA_ACCQ4 0xf47701ff ++ ++/*P1_EQUAI5*/ ++#define RSTV0910_P1_EQUAI5 0xf478 ++#define FSTV0910_P1_EQUA_ACCI5 0xf47801ff ++ ++/*P1_EQUAQ5*/ ++#define RSTV0910_P1_EQUAQ5 0xf479 ++#define FSTV0910_P1_EQUA_ACCQ5 0xf47901ff ++ ++/*P1_EQUAI6*/ ++#define RSTV0910_P1_EQUAI6 0xf47a ++#define FSTV0910_P1_EQUA_ACCI6 0xf47a01ff ++ ++/*P1_EQUAQ6*/ ++#define RSTV0910_P1_EQUAQ6 0xf47b ++#define FSTV0910_P1_EQUA_ACCQ6 0xf47b01ff ++ ++/*P1_EQUAI7*/ ++#define RSTV0910_P1_EQUAI7 0xf47c ++#define FSTV0910_P1_EQUA_ACCI7 0xf47c01ff ++ ++/*P1_EQUAQ7*/ ++#define RSTV0910_P1_EQUAQ7 0xf47d ++#define FSTV0910_P1_EQUA_ACCQ7 0xf47d01ff ++ ++/*P1_EQUAI8*/ ++#define RSTV0910_P1_EQUAI8 0xf47e ++#define FSTV0910_P1_EQUA_ACCI8 0xf47e01ff ++ ++/*P1_EQUAQ8*/ ++#define RSTV0910_P1_EQUAQ8 0xf47f ++#define FSTV0910_P1_EQUA_ACCQ8 0xf47f01ff ++ ++/*P1_NNOSDATAT1*/ ++#define RSTV0910_P1_NNOSDATAT1 0xf480 ++#define FSTV0910_P1_NOSDATAT_NORMED1 0xf48000ff ++ ++/*P1_NNOSDATAT0*/ ++#define RSTV0910_P1_NNOSDATAT0 0xf481 ++#define FSTV0910_P1_NOSDATAT_NORMED0 0xf48100ff ++ ++/*P1_NNOSDATA1*/ ++#define RSTV0910_P1_NNOSDATA1 0xf482 ++#define FSTV0910_P1_NOSDATA_NORMED1 0xf48200ff ++ ++/*P1_NNOSDATA0*/ ++#define RSTV0910_P1_NNOSDATA0 0xf483 ++#define FSTV0910_P1_NOSDATA_NORMED0 0xf48300ff ++ ++/*P1_NNOSPLHT1*/ ++#define RSTV0910_P1_NNOSPLHT1 0xf484 ++#define FSTV0910_P1_NOSPLHT_NORMED1 0xf48400ff ++ ++/*P1_NNOSPLHT0*/ ++#define RSTV0910_P1_NNOSPLHT0 0xf485 ++#define FSTV0910_P1_NOSPLHT_NORMED0 0xf48500ff ++ ++/*P1_NNOSPLH1*/ ++#define RSTV0910_P1_NNOSPLH1 0xf486 ++#define FSTV0910_P1_NOSPLH_NORMED1 0xf48600ff ++ ++/*P1_NNOSPLH0*/ ++#define RSTV0910_P1_NNOSPLH0 0xf487 ++#define FSTV0910_P1_NOSPLH_NORMED0 0xf48700ff ++ ++/*P1_NOSDATAT1*/ ++#define RSTV0910_P1_NOSDATAT1 0xf488 ++#define FSTV0910_P1_NOSDATAT_UNNORMED1 0xf48800ff ++ ++/*P1_NOSDATAT0*/ ++#define RSTV0910_P1_NOSDATAT0 0xf489 ++#define FSTV0910_P1_NOSDATAT_UNNORMED0 0xf48900ff ++ ++/*P1_NNOSFRAME1*/ ++#define RSTV0910_P1_NNOSFRAME1 0xf48a ++#define FSTV0910_P1_NOSFRAME_NORMED1 0xf48a00ff ++ ++/*P1_NNOSFRAME0*/ ++#define RSTV0910_P1_NNOSFRAME0 0xf48b ++#define FSTV0910_P1_NOSFRAME_NORMED0 0xf48b00ff ++ ++/*P1_NNOSRAD1*/ ++#define RSTV0910_P1_NNOSRAD1 0xf48c ++#define FSTV0910_P1_NOSRADIAL_NORMED1 0xf48c00ff ++ ++/*P1_NNOSRAD0*/ ++#define RSTV0910_P1_NNOSRAD0 0xf48d ++#define FSTV0910_P1_NOSRADIAL_NORMED0 0xf48d00ff ++ ++/*P1_NOSCFGF1*/ ++#define RSTV0910_P1_NOSCFGF1 0xf48e ++#define FSTV0910_P1_LOWNOISE_MESURE 0xf48e0080 ++#define FSTV0910_P1_NOS_DELFRAME 0xf48e0040 ++#define FSTV0910_P1_NOSDATA_MODE 0xf48e0030 ++#define FSTV0910_P1_FRAMESEL_TYPESEL 0xf48e000c ++#define FSTV0910_P1_FRAMESEL_TYPE 0xf48e0003 ++ ++/*P1_CAR2CFG*/ ++#define RSTV0910_P1_CAR2CFG 0xf490 ++#define FSTV0910_P1_DESCRAMB_OFF 0xf4900080 ++#define FSTV0910_P1_EN_PHNOSRAM 0xf4900020 ++#define FSTV0910_P1_STOP_CFR2UPDATE 0xf4900010 ++#define FSTV0910_P1_STOP_NCO2UPDATE 0xf4900008 ++#define FSTV0910_P1_ROTA2ON 0xf4900004 ++#define FSTV0910_P1_PH_DET_ALGO2 0xf4900003 ++ ++/*P1_CFR2CFR1*/ ++#define RSTV0910_P1_CFR2CFR1 0xf491 ++#define FSTV0910_P1_CFR2_S2CONTROL 0xf49100c0 ++#define FSTV0910_P1_EN_S2CAR2CENTER 0xf4910020 ++#define FSTV0910_P1_BCHERRCFR2_MODE 0xf4910018 ++#define FSTV0910_P1_CFR2TOCFR1_BETA 0xf4910007 ++ ++/*P1_CAR3CFG*/ ++#define RSTV0910_P1_CAR3CFG 0xf492 ++#define FSTV0910_P1_CARRIER23_MODE 0xf49200c0 ++#define FSTV0910_P1_CAR3INTERM_DVBS1 0xf4920020 ++#define FSTV0910_P1_ABAMPLIF_MODE 0xf4920018 ++#define FSTV0910_P1_CARRIER3_ALPHA3DL 0xf4920007 ++ ++/*P1_CFR22*/ ++#define RSTV0910_P1_CFR22 0xf493 ++#define FSTV0910_P1_CAR2_FREQ2 0xf49301ff ++ ++/*P1_CFR21*/ ++#define RSTV0910_P1_CFR21 0xf494 ++#define FSTV0910_P1_CAR2_FREQ1 0xf49400ff ++ ++/*P1_CFR20*/ ++#define RSTV0910_P1_CFR20 0xf495 ++#define FSTV0910_P1_CAR2_FREQ0 0xf49500ff ++ ++/*P1_ACLC2S2Q*/ ++#define RSTV0910_P1_ACLC2S2Q 0xf497 ++#define FSTV0910_P1_ENAB_SPSKSYMB 0xf4970080 ++#define FSTV0910_P1_CAR2S2_QANOSAUTO 0xf4970040 ++#define FSTV0910_P1_CAR2S2_Q_ALPH_M 0xf4970030 ++#define FSTV0910_P1_CAR2S2_Q_ALPH_E 0xf497000f ++ ++/*P1_ACLC2S28*/ ++#define RSTV0910_P1_ACLC2S28 0xf498 ++#define FSTV0910_P1_OLDI3Q_MODE 0xf4980080 ++#define FSTV0910_P1_CAR2S2_8ANOSAUTO 0xf4980040 ++#define FSTV0910_P1_CAR2S2_8_ALPH_M 0xf4980030 ++#define FSTV0910_P1_CAR2S2_8_ALPH_E 0xf498000f ++ ++/*P1_ACLC2S216A*/ ++#define RSTV0910_P1_ACLC2S216A 0xf499 ++#define FSTV0910_P1_CAR2S2_16ANOSAUTO 0xf4990040 ++#define FSTV0910_P1_CAR2S2_16A_ALPH_M 0xf4990030 ++#define FSTV0910_P1_CAR2S2_16A_ALPH_E 0xf499000f ++ ++/*P1_ACLC2S232A*/ ++#define RSTV0910_P1_ACLC2S232A 0xf49a ++#define FSTV0910_P1_CAR2S2_32ANOSUATO 0xf49a0040 ++#define FSTV0910_P1_CAR2S2_32A_ALPH_M 0xf49a0030 ++#define FSTV0910_P1_CAR2S2_32A_ALPH_E 0xf49a000f ++ ++/*P1_BCLC2S2Q*/ ++#define RSTV0910_P1_BCLC2S2Q 0xf49c ++#define FSTV0910_P1_DVBS2S2Q_NIP 0xf49c0080 ++#define FSTV0910_P1_CAR2S2_QBNOSAUTO 0xf49c0040 ++#define FSTV0910_P1_CAR2S2_Q_BETA_M 0xf49c0030 ++#define FSTV0910_P1_CAR2S2_Q_BETA_E 0xf49c000f ++ ++/*P1_BCLC2S28*/ ++#define RSTV0910_P1_BCLC2S28 0xf49d ++#define FSTV0910_P1_DVBS2S28_NIP 0xf49d0080 ++#define FSTV0910_P1_CAR2S2_8BNOSAUTO 0xf49d0040 ++#define FSTV0910_P1_CAR2S2_8_BETA_M 0xf49d0030 ++#define FSTV0910_P1_CAR2S2_8_BETA_E 0xf49d000f ++ ++/*P1_PLROOT2*/ ++#define RSTV0910_P1_PLROOT2 0xf4ac ++#define FSTV0910_P1_PLHAUTO_DISPLH 0xf4ac0040 ++#define FSTV0910_P1_PLHAUTO_FASTMODE 0xf4ac0020 ++#define FSTV0910_P1_PLHAUTO_ENABLE 0xf4ac0010 ++#define FSTV0910_P1_PLSCRAMB_MODE 0xf4ac000c ++#define FSTV0910_P1_PLSCRAMB_ROOT2 0xf4ac0003 ++ ++/*P1_PLROOT1*/ ++#define RSTV0910_P1_PLROOT1 0xf4ad ++#define FSTV0910_P1_PLSCRAMB_ROOT1 0xf4ad00ff ++ ++/*P1_PLROOT0*/ ++#define RSTV0910_P1_PLROOT0 0xf4ae ++#define FSTV0910_P1_PLSCRAMB_ROOT0 0xf4ae00ff ++ ++/*P1_MODCODLST7*/ ++#define RSTV0910_P1_MODCODLST7 0xf4b7 ++#define FSTV0910_P1_MODCOD_NNOSFILTER 0xf4b70080 ++#define FSTV0910_P1_MODCODLST_NOSTYPE 0xf4b70040 ++#define FSTV0910_P1_DIS_8PSK_9_10 0xf4b70030 ++#define FSTV0910_P1_DIS_8P_8_9 0xf4b7000f ++ ++/*P1_MODCODLST8*/ ++#define RSTV0910_P1_MODCODLST8 0xf4b8 ++#define FSTV0910_P1_DIS_8P_5_6 0xf4b800f0 ++#define FSTV0910_P1_DIS_8P_3_4 0xf4b8000f ++ ++/*P1_MODCODLST9*/ ++#define RSTV0910_P1_MODCODLST9 0xf4b9 ++#define FSTV0910_P1_DIS_8P_2_3 0xf4b900f0 ++#define FSTV0910_P1_DIS_8P_3_5 0xf4b9000f ++ ++/*P1_MODCODLSTA*/ ++#define RSTV0910_P1_MODCODLSTA 0xf4ba ++#define FSTV0910_P1_NOSFILTER_LIMITE 0xf4ba0080 ++#define FSTV0910_P1_NOSFILTER_MODE 0xf4ba0040 ++#define FSTV0910_P1_DIS_QPSK_9_10 0xf4ba0030 ++#define FSTV0910_P1_DIS_QP_8_9 0xf4ba000f ++ ++/*P1_MODCODLSTB*/ ++#define RSTV0910_P1_MODCODLSTB 0xf4bb ++#define FSTV0910_P1_DIS_QP_5_6 0xf4bb00f0 ++#define FSTV0910_P1_DIS_QP_4_5 0xf4bb000f ++ ++/*P1_MODCODLSTC*/ ++#define RSTV0910_P1_MODCODLSTC 0xf4bc ++#define FSTV0910_P1_DIS_QP_3_4 0xf4bc00f0 ++#define FSTV0910_P1_DIS_QP_2_3 0xf4bc000f ++ ++/*P1_MODCODLSTD*/ ++#define RSTV0910_P1_MODCODLSTD 0xf4bd ++#define FSTV0910_P1_DIS_QPSK_3_5 0xf4bd00f0 ++#define FSTV0910_P1_DIS_QPSK_1_2 0xf4bd000f ++ ++/*P1_GAUSSR0*/ ++#define RSTV0910_P1_GAUSSR0 0xf4c0 ++#define FSTV0910_P1_EN_CCIMODE 0xf4c00080 ++#define FSTV0910_P1_R0_GAUSSIEN 0xf4c0007f ++ ++/*P1_CCIR0*/ ++#define RSTV0910_P1_CCIR0 0xf4c1 ++#define FSTV0910_P1_CCIDETECT_PLHONLY 0xf4c10080 ++#define FSTV0910_P1_R0_CCI 0xf4c1007f ++ ++/*P1_CCIQUANT*/ ++#define RSTV0910_P1_CCIQUANT 0xf4c2 ++#define FSTV0910_P1_CCI_BETA 0xf4c200e0 ++#define FSTV0910_P1_CCI_QUANT 0xf4c2001f ++ ++/*P1_CCITHRES*/ ++#define RSTV0910_P1_CCITHRES 0xf4c3 ++#define FSTV0910_P1_CCI_THRESHOLD 0xf4c300ff ++ ++/*P1_CCIACC*/ ++#define RSTV0910_P1_CCIACC 0xf4c4 ++#define FSTV0910_P1_CCI_VALUE 0xf4c400ff ++ ++/*P1_DSTATUS4*/ ++#define RSTV0910_P1_DSTATUS4 0xf4c5 ++#define FSTV0910_P1_RAINFADE_DETECT 0xf4c50080 ++#define FSTV0910_P1_NOTHRES2_FAIL 0xf4c50040 ++#define FSTV0910_P1_NOTHRES1_FAIL 0xf4c50020 ++#define FSTV0910_P1_PILOT_FAILDETECT 0xf4c50010 ++#define FSTV0910_P1_HIER_DETECT 0xf4c50008 ++#define FSTV0910_P1_DMDPROG_ERROR 0xf4c50004 ++#define FSTV0910_P1_CSTENV_DETECT 0xf4c50002 ++#define FSTV0910_P1_DETECTION_TRIAX 0xf4c50001 ++ ++/*P1_DMDRESCFG*/ ++#define RSTV0910_P1_DMDRESCFG 0xf4c6 ++#define FSTV0910_P1_DMDRES_RESET 0xf4c60080 ++#define FSTV0910_P1_DMDRES_NOISESQR 0xf4c60010 ++#define FSTV0910_P1_DMDRES_STRALL 0xf4c60008 ++#define FSTV0910_P1_DMDRES_NEWONLY 0xf4c60004 ++#define FSTV0910_P1_DMDRES_NOSTORE 0xf4c60002 ++#define FSTV0910_P1_DMDRES_AGC2MEM 0xf4c60001 ++ ++/*P1_DMDRESADR*/ ++#define RSTV0910_P1_DMDRESADR 0xf4c7 ++#define FSTV0910_P1_SUSP_PREDCANAL 0xf4c70080 ++#define FSTV0910_P1_DMDRES_VALIDCFR 0xf4c70040 ++#define FSTV0910_P1_DMDRES_MEMFULL 0xf4c70030 ++#define FSTV0910_P1_DMDRES_RESNBR 0xf4c7000f ++ ++/*P1_DMDRESDATA7*/ ++#define RSTV0910_P1_DMDRESDATA7 0xf4c8 ++#define FSTV0910_P1_DMDRES_DATA7 0xf4c800ff ++ ++/*P1_DMDRESDATA6*/ ++#define RSTV0910_P1_DMDRESDATA6 0xf4c9 ++#define FSTV0910_P1_DMDRES_DATA6 0xf4c900ff ++ ++/*P1_DMDRESDATA5*/ ++#define RSTV0910_P1_DMDRESDATA5 0xf4ca ++#define FSTV0910_P1_DMDRES_DATA5 0xf4ca00ff ++ ++/*P1_DMDRESDATA4*/ ++#define RSTV0910_P1_DMDRESDATA4 0xf4cb ++#define FSTV0910_P1_DMDRES_DATA4 0xf4cb00ff ++ ++/*P1_DMDRESDATA3*/ ++#define RSTV0910_P1_DMDRESDATA3 0xf4cc ++#define FSTV0910_P1_DMDRES_DATA3 0xf4cc00ff ++ ++/*P1_DMDRESDATA2*/ ++#define RSTV0910_P1_DMDRESDATA2 0xf4cd ++#define FSTV0910_P1_DMDRES_DATA2 0xf4cd00ff ++ ++/*P1_DMDRESDATA1*/ ++#define RSTV0910_P1_DMDRESDATA1 0xf4ce ++#define FSTV0910_P1_DMDRES_DATA1 0xf4ce00ff ++ ++/*P1_DMDRESDATA0*/ ++#define RSTV0910_P1_DMDRESDATA0 0xf4cf ++#define FSTV0910_P1_DMDRES_DATA0 0xf4cf00ff ++ ++/*P1_FFEI1*/ ++#define RSTV0910_P1_FFEI1 0xf4d0 ++#define FSTV0910_P1_FFE_ACCI1 0xf4d001ff ++ ++/*P1_FFEQ1*/ ++#define RSTV0910_P1_FFEQ1 0xf4d1 ++#define FSTV0910_P1_FFE_ACCQ1 0xf4d101ff ++ ++/*P1_FFEI2*/ ++#define RSTV0910_P1_FFEI2 0xf4d2 ++#define FSTV0910_P1_FFE_ACCI2 0xf4d201ff ++ ++/*P1_FFEQ2*/ ++#define RSTV0910_P1_FFEQ2 0xf4d3 ++#define FSTV0910_P1_FFE_ACCQ2 0xf4d301ff ++ ++/*P1_FFEI3*/ ++#define RSTV0910_P1_FFEI3 0xf4d4 ++#define FSTV0910_P1_FFE_ACCI3 0xf4d401ff ++ ++/*P1_FFEQ3*/ ++#define RSTV0910_P1_FFEQ3 0xf4d5 ++#define FSTV0910_P1_FFE_ACCQ3 0xf4d501ff ++ ++/*P1_FFEI4*/ ++#define RSTV0910_P1_FFEI4 0xf4d6 ++#define FSTV0910_P1_FFE_ACCI4 0xf4d601ff ++ ++/*P1_FFEQ4*/ ++#define RSTV0910_P1_FFEQ4 0xf4d7 ++#define FSTV0910_P1_FFE_ACCQ4 0xf4d701ff ++ ++/*P1_FFECFG*/ ++#define RSTV0910_P1_FFECFG 0xf4d8 ++#define FSTV0910_P1_EQUALFFE_ON 0xf4d80040 ++#define FSTV0910_P1_EQUAL_USEDSYMB 0xf4d80030 ++#define FSTV0910_P1_MU_EQUALFFE 0xf4d80007 ++ ++/*P1_TNRCFG2*/ ++#define RSTV0910_P1_TNRCFG2 0xf4e1 ++#define FSTV0910_P1_TUN_IQSWAP 0xf4e10080 ++#define FSTV0910_P1_STB6110_STEP2MHZ 0xf4e10040 ++#define FSTV0910_P1_STB6120_DBLI2C 0xf4e10020 ++#define FSTV0910_P1_TUNER_WIDEBAND 0xf4e10010 ++#define FSTV0910_P1_TUNER_OBSPAGE 0xf4e10008 ++#define FSTV0910_P1_DIS_BWCALC 0xf4e10004 ++#define FSTV0910_P1_SHORT_WAITSTATES 0xf4e10002 ++#define FSTV0910_P1_DIS_2BWAGC1 0xf4e10001 ++ ++/*P1_SMAPCOEF7*/ ++#define RSTV0910_P1_SMAPCOEF7 0xf500 ++#define FSTV0910_P1_DIS_QSCALE 0xf5000080 ++#define FSTV0910_P1_SMAPCOEF_Q_LLR12 0xf500017f ++ ++/*P1_SMAPCOEF6*/ ++#define RSTV0910_P1_SMAPCOEF6 0xf501 ++#define FSTV0910_P1_DIS_AGC2SCALE 0xf5010080 ++#define FSTV0910_P1_DIS_16IQMULT 0xf5010040 ++#define FSTV0910_P1_OLD_16APSK47 0xf5010020 ++#define FSTV0910_P1_OLD_16APSK12 0xf5010010 ++#define FSTV0910_P1_DIS_NEWSCALE 0xf5010008 ++#define FSTV0910_P1_ADJ_8PSKLLR1 0xf5010004 ++#define FSTV0910_P1_OLD_8PSKLLR1 0xf5010002 ++#define FSTV0910_P1_DIS_AB8PSK 0xf5010001 ++ ++/*P1_SMAPCOEF5*/ ++#define RSTV0910_P1_SMAPCOEF5 0xf502 ++#define FSTV0910_P1_DIS_8SCALE 0xf5020080 ++#define FSTV0910_P1_SMAPCOEF_8P_LLR23 0xf502017f ++ ++/*P1_NOSTHRES1*/ ++#define RSTV0910_P1_NOSTHRES1 0xf509 ++#define FSTV0910_P1_NOS_THRESHOLD1 0xf50900ff ++ ++/*P1_NOSTHRES2*/ ++#define RSTV0910_P1_NOSTHRES2 0xf50a ++#define FSTV0910_P1_NOS_THRESHOLD2 0xf50a00ff ++ ++/*P1_NOSDIFF1*/ ++#define RSTV0910_P1_NOSDIFF1 0xf50b ++#define FSTV0910_P1_NOSTHRES1_DIFF 0xf50b00ff ++ ++/*P1_RAINFADE*/ ++#define RSTV0910_P1_RAINFADE 0xf50c ++#define FSTV0910_P1_NOSTHRES_DATAT 0xf50c0080 ++#define FSTV0910_P1_RAINFADE_CNLIMIT 0xf50c0070 ++#define FSTV0910_P1_RAINFADE_TIMEOUT 0xf50c0007 ++ ++/*P1_NOSRAMCFG*/ ++#define RSTV0910_P1_NOSRAMCFG 0xf50d ++#define FSTV0910_P1_NOSRAM_DVBS2DATA 0xf50d0080 ++#define FSTV0910_P1_NOSRAM_QUADRAT 0xf50d0040 ++#define FSTV0910_P1_NOSRAM_ACTIVATION 0xf50d0030 ++#define FSTV0910_P1_NOSRAM_CNRONLY 0xf50d0008 ++#define FSTV0910_P1_NOSRAM_LGNCNR1 0xf50d0007 ++ ++/*P1_NOSRAMPOS*/ ++#define RSTV0910_P1_NOSRAMPOS 0xf50e ++#define FSTV0910_P1_NOSRAM_LGNCNR0 0xf50e00f0 ++#define FSTV0910_P1_NOSRAM_VALIDE 0xf50e0004 ++#define FSTV0910_P1_NOSRAM_CNRVAL1 0xf50e0003 ++ ++/*P1_NOSRAMVAL*/ ++#define RSTV0910_P1_NOSRAMVAL 0xf50f ++#define FSTV0910_P1_NOSRAM_CNRVAL0 0xf50f00ff ++ ++/*P1_DMDPLHSTAT*/ ++#define RSTV0910_P1_DMDPLHSTAT 0xf520 ++#define FSTV0910_P1_PLH_STATISTIC 0xf52000ff ++ ++/*P1_LOCKTIME3*/ ++#define RSTV0910_P1_LOCKTIME3 0xf522 ++#define FSTV0910_P1_DEMOD_LOCKTIME3 0xf52200ff ++ ++/*P1_LOCKTIME2*/ ++#define RSTV0910_P1_LOCKTIME2 0xf523 ++#define FSTV0910_P1_DEMOD_LOCKTIME2 0xf52300ff ++ ++/*P1_LOCKTIME1*/ ++#define RSTV0910_P1_LOCKTIME1 0xf524 ++#define FSTV0910_P1_DEMOD_LOCKTIME1 0xf52400ff ++ ++/*P1_LOCKTIME0*/ ++#define RSTV0910_P1_LOCKTIME0 0xf525 ++#define FSTV0910_P1_DEMOD_LOCKTIME0 0xf52500ff ++ ++/*P1_VITSCALE*/ ++#define RSTV0910_P1_VITSCALE 0xf532 ++#define FSTV0910_P1_NVTH_NOSRANGE 0xf5320080 ++#define FSTV0910_P1_VERROR_MAXMODE 0xf5320040 ++#define FSTV0910_P1_KDIV_MODE 0xf5320030 ++#define FSTV0910_P1_NSLOWSN_LOCKED 0xf5320008 ++#define FSTV0910_P1_DELOCK_PRFLOSS 0xf5320004 ++#define FSTV0910_P1_DIS_RSFLOCK 0xf5320002 ++ ++/*P1_FECM*/ ++#define RSTV0910_P1_FECM 0xf533 ++#define FSTV0910_P1_DSS_DVB 0xf5330080 ++#define FSTV0910_P1_DEMOD_BYPASS 0xf5330040 ++#define FSTV0910_P1_CMP_SLOWMODE 0xf5330020 ++#define FSTV0910_P1_DSS_SRCH 0xf5330010 ++#define FSTV0910_P1_DIFF_MODEVIT 0xf5330004 ++#define FSTV0910_P1_SYNCVIT 0xf5330002 ++#define FSTV0910_P1_IQINV 0xf5330001 ++ ++/*P1_VTH12*/ ++#define RSTV0910_P1_VTH12 0xf534 ++#define FSTV0910_P1_VTH12 0xf53400ff ++ ++/*P1_VTH23*/ ++#define RSTV0910_P1_VTH23 0xf535 ++#define FSTV0910_P1_VTH23 0xf53500ff ++ ++/*P1_VTH34*/ ++#define RSTV0910_P1_VTH34 0xf536 ++#define FSTV0910_P1_VTH34 0xf53600ff ++ ++/*P1_VTH56*/ ++#define RSTV0910_P1_VTH56 0xf537 ++#define FSTV0910_P1_VTH56 0xf53700ff ++ ++/*P1_VTH67*/ ++#define RSTV0910_P1_VTH67 0xf538 ++#define FSTV0910_P1_VTH67 0xf53800ff ++ ++/*P1_VTH78*/ ++#define RSTV0910_P1_VTH78 0xf539 ++#define FSTV0910_P1_VTH78 0xf53900ff ++ ++/*P1_VITCURPUN*/ ++#define RSTV0910_P1_VITCURPUN 0xf53a ++#define FSTV0910_P1_CYCLESLIP_VIT 0xf53a0080 ++#define FSTV0910_P1_VIT_ROTA180 0xf53a0040 ++#define FSTV0910_P1_VIT_ROTA90 0xf53a0020 ++#define FSTV0910_P1_VIT_CURPUN 0xf53a001f ++ ++/*P1_VERROR*/ ++#define RSTV0910_P1_VERROR 0xf53b ++#define FSTV0910_P1_REGERR_VIT 0xf53b00ff ++ ++/*P1_PRVIT*/ ++#define RSTV0910_P1_PRVIT 0xf53c ++#define FSTV0910_P1_DIS_VTHLOCK 0xf53c0040 ++#define FSTV0910_P1_E7_8VIT 0xf53c0020 ++#define FSTV0910_P1_E6_7VIT 0xf53c0010 ++#define FSTV0910_P1_E5_6VIT 0xf53c0008 ++#define FSTV0910_P1_E3_4VIT 0xf53c0004 ++#define FSTV0910_P1_E2_3VIT 0xf53c0002 ++#define FSTV0910_P1_E1_2VIT 0xf53c0001 ++ ++/*P1_VAVSRVIT*/ ++#define RSTV0910_P1_VAVSRVIT 0xf53d ++#define FSTV0910_P1_AMVIT 0xf53d0080 ++#define FSTV0910_P1_FROZENVIT 0xf53d0040 ++#define FSTV0910_P1_SNVIT 0xf53d0030 ++#define FSTV0910_P1_TOVVIT 0xf53d000c ++#define FSTV0910_P1_HYPVIT 0xf53d0003 ++ ++/*P1_VSTATUSVIT*/ ++#define RSTV0910_P1_VSTATUSVIT 0xf53e ++#define FSTV0910_P1_VITERBI_ON 0xf53e0080 ++#define FSTV0910_P1_END_LOOPVIT 0xf53e0040 ++#define FSTV0910_P1_VITERBI_DEPRF 0xf53e0020 ++#define FSTV0910_P1_PRFVIT 0xf53e0010 ++#define FSTV0910_P1_LOCKEDVIT 0xf53e0008 ++#define FSTV0910_P1_VITERBI_DELOCK 0xf53e0004 ++#define FSTV0910_P1_VIT_DEMODSEL 0xf53e0002 ++#define FSTV0910_P1_VITERBI_COMPOUT 0xf53e0001 ++ ++/*P1_VTHINUSE*/ ++#define RSTV0910_P1_VTHINUSE 0xf53f ++#define FSTV0910_P1_VIT_INUSE 0xf53f00ff ++ ++/*P1_KDIV12*/ ++#define RSTV0910_P1_KDIV12 0xf540 ++#define FSTV0910_P1_KDIV12_MANUAL 0xf5400080 ++#define FSTV0910_P1_K_DIVIDER_12 0xf540007f ++ ++/*P1_KDIV23*/ ++#define RSTV0910_P1_KDIV23 0xf541 ++#define FSTV0910_P1_KDIV23_MANUAL 0xf5410080 ++#define FSTV0910_P1_K_DIVIDER_23 0xf541007f ++ ++/*P1_KDIV34*/ ++#define RSTV0910_P1_KDIV34 0xf542 ++#define FSTV0910_P1_KDIV34_MANUAL 0xf5420080 ++#define FSTV0910_P1_K_DIVIDER_34 0xf542007f ++ ++/*P1_KDIV56*/ ++#define RSTV0910_P1_KDIV56 0xf543 ++#define FSTV0910_P1_KDIV56_MANUAL 0xf5430080 ++#define FSTV0910_P1_K_DIVIDER_56 0xf543007f ++ ++/*P1_KDIV67*/ ++#define RSTV0910_P1_KDIV67 0xf544 ++#define FSTV0910_P1_KDIV67_MANUAL 0xf5440080 ++#define FSTV0910_P1_K_DIVIDER_67 0xf544007f ++ ++/*P1_KDIV78*/ ++#define RSTV0910_P1_KDIV78 0xf545 ++#define FSTV0910_P1_KDIV78_MANUAL 0xf5450080 ++#define FSTV0910_P1_K_DIVIDER_78 0xf545007f ++ ++/*P1_PDELCTRL0*/ ++#define RSTV0910_P1_PDELCTRL0 0xf54f ++#define FSTV0910_P1_ISIOBS_MODE 0xf54f0030 ++#define FSTV0910_P1_PDELDIS_BITWISE 0xf54f0004 ++ ++/*P1_PDELCTRL1*/ ++#define RSTV0910_P1_PDELCTRL1 0xf550 ++#define FSTV0910_P1_INV_MISMASK 0xf5500080 ++#define FSTV0910_P1_FORCE_ACCEPTED 0xf5500040 ++#define FSTV0910_P1_FILTER_EN 0xf5500020 ++#define FSTV0910_P1_FORCE_PKTDELINUSE 0xf5500010 ++#define FSTV0910_P1_HYSTEN 0xf5500008 ++#define FSTV0910_P1_HYSTSWRST 0xf5500004 ++#define FSTV0910_P1_EN_MIS00 0xf5500002 ++#define FSTV0910_P1_ALGOSWRST 0xf5500001 ++ ++/*P1_PDELCTRL2*/ ++#define RSTV0910_P1_PDELCTRL2 0xf551 ++#define FSTV0910_P1_FORCE_CONTINUOUS 0xf5510080 ++#define FSTV0910_P1_RESET_UPKO_COUNT 0xf5510040 ++#define FSTV0910_P1_USER_PKTDELIN_NB 0xf5510020 ++#define FSTV0910_P1_DATA_UNBBSCRAMBLED 0xf5510008 ++#define FSTV0910_P1_FORCE_LONGPKT 0xf5510004 ++#define FSTV0910_P1_FRAME_MODE 0xf5510002 ++ ++/*P1_HYSTTHRESH*/ ++#define RSTV0910_P1_HYSTTHRESH 0xf554 ++#define FSTV0910_P1_DELIN_LOCKTHRES 0xf55400f0 ++#define FSTV0910_P1_DELIN_UNLOCKTHRES 0xf554000f ++ ++/*P1_ISIENTRY*/ ++#define RSTV0910_P1_ISIENTRY 0xf55e ++#define FSTV0910_P1_ISI_ENTRY 0xf55e00ff ++ ++/*P1_ISIBITENA*/ ++#define RSTV0910_P1_ISIBITENA 0xf55f ++#define FSTV0910_P1_ISI_BIT_EN 0xf55f00ff ++ ++/*P1_MATSTR1*/ ++#define RSTV0910_P1_MATSTR1 0xf560 ++#define FSTV0910_P1_MATYPE_CURRENT1 0xf56000ff ++ ++/*P1_MATSTR0*/ ++#define RSTV0910_P1_MATSTR0 0xf561 ++#define FSTV0910_P1_MATYPE_CURRENT0 0xf56100ff ++ ++/*P1_UPLSTR1*/ ++#define RSTV0910_P1_UPLSTR1 0xf562 ++#define FSTV0910_P1_UPL_CURRENT1 0xf56200ff ++ ++/*P1_UPLSTR0*/ ++#define RSTV0910_P1_UPLSTR0 0xf563 ++#define FSTV0910_P1_UPL_CURRENT0 0xf56300ff ++ ++/*P1_DFLSTR1*/ ++#define RSTV0910_P1_DFLSTR1 0xf564 ++#define FSTV0910_P1_DFL_CURRENT1 0xf56400ff ++ ++/*P1_DFLSTR0*/ ++#define RSTV0910_P1_DFLSTR0 0xf565 ++#define FSTV0910_P1_DFL_CURRENT0 0xf56500ff ++ ++/*P1_SYNCSTR*/ ++#define RSTV0910_P1_SYNCSTR 0xf566 ++#define FSTV0910_P1_SYNC_CURRENT 0xf56600ff ++ ++/*P1_SYNCDSTR1*/ ++#define RSTV0910_P1_SYNCDSTR1 0xf567 ++#define FSTV0910_P1_SYNCD_CURRENT1 0xf56700ff ++ ++/*P1_SYNCDSTR0*/ ++#define RSTV0910_P1_SYNCDSTR0 0xf568 ++#define FSTV0910_P1_SYNCD_CURRENT0 0xf56800ff ++ ++/*P1_PDELSTATUS1*/ ++#define RSTV0910_P1_PDELSTATUS1 0xf569 ++#define FSTV0910_P1_PKTDELIN_DELOCK 0xf5690080 ++#define FSTV0910_P1_SYNCDUPDFL_BADDFL 0xf5690040 ++#define FSTV0910_P1_CONTINUOUS_STREAM 0xf5690020 ++#define FSTV0910_P1_UNACCEPTED_STREAM 0xf5690010 ++#define FSTV0910_P1_BCH_ERROR_FLAG 0xf5690008 ++#define FSTV0910_P1_BBHCRCKO 0xf5690004 ++#define FSTV0910_P1_PKTDELIN_LOCK 0xf5690002 ++#define FSTV0910_P1_FIRST_LOCK 0xf5690001 ++ ++/*P1_PDELSTATUS2*/ ++#define RSTV0910_P1_PDELSTATUS2 0xf56a ++#define FSTV0910_P1_PKTDEL_DEMODSEL 0xf56a0080 ++#define FSTV0910_P1_FRAME_MODCOD 0xf56a007c ++#define FSTV0910_P1_FRAME_TYPE 0xf56a0003 ++ ++/*P1_BBFCRCKO1*/ ++#define RSTV0910_P1_BBFCRCKO1 0xf56b ++#define FSTV0910_P1_BBHCRC_KOCNT1 0xf56b00ff ++ ++/*P1_BBFCRCKO0*/ ++#define RSTV0910_P1_BBFCRCKO0 0xf56c ++#define FSTV0910_P1_BBHCRC_KOCNT0 0xf56c00ff ++ ++/*P1_UPCRCKO1*/ ++#define RSTV0910_P1_UPCRCKO1 0xf56d ++#define FSTV0910_P1_PKTCRC_KOCNT1 0xf56d00ff ++ ++/*P1_UPCRCKO0*/ ++#define RSTV0910_P1_UPCRCKO0 0xf56e ++#define FSTV0910_P1_PKTCRC_KOCNT0 0xf56e00ff ++ ++/*P1_PDELCTRL3*/ ++#define RSTV0910_P1_PDELCTRL3 0xf56f ++#define FSTV0910_P1_PKTDEL_CONTFAIL 0xf56f0080 ++#define FSTV0910_P1_PKTDEL_ENLONGPKT 0xf56f0040 ++#define FSTV0910_P1_NOFIFO_BCHERR 0xf56f0020 ++#define FSTV0910_P1_PKTDELIN_DELACMERR 0xf56f0010 ++#define FSTV0910_P1_SATURATE_BBPKTKO 0xf56f0004 ++#define FSTV0910_P1_PKTDEL_BCHERRCONT 0xf56f0002 ++#define FSTV0910_P1_ETHERNET_DISFCS 0xf56f0001 ++ ++/*P1_TSSTATEM*/ ++#define RSTV0910_P1_TSSTATEM 0xf570 ++#define FSTV0910_P1_TSDIL_ON 0xf5700080 ++#define FSTV0910_P1_TSSKIPRS_ON 0xf5700040 ++#define FSTV0910_P1_TSRS_ON 0xf5700020 ++#define FSTV0910_P1_TSDESCRAMB_ON 0xf5700010 ++#define FSTV0910_P1_TSFRAME_MODE 0xf5700008 ++#define FSTV0910_P1_TS_DISABLE 0xf5700004 ++#define FSTV0910_P1_TSACM_MODE 0xf5700002 ++#define FSTV0910_P1_TSOUT_NOSYNC 0xf5700001 ++ ++/*P1_TSCFGH*/ ++#define RSTV0910_P1_TSCFGH 0xf572 ++#define FSTV0910_P1_TSFIFO_DVBCI 0xf5720080 ++#define FSTV0910_P1_TSFIFO_SERIAL 0xf5720040 ++#define FSTV0910_P1_TSFIFO_TEIUPDATE 0xf5720020 ++#define FSTV0910_P1_TSFIFO_DUTY50 0xf5720010 ++#define FSTV0910_P1_TSFIFO_HSGNLOUT 0xf5720008 ++#define FSTV0910_P1_TSFIFO_ERRMODE 0xf5720006 ++#define FSTV0910_P1_RST_HWARE 0xf5720001 ++ ++/*P1_TSCFGM*/ ++#define RSTV0910_P1_TSCFGM 0xf573 ++#define FSTV0910_P1_TSFIFO_MANSPEED 0xf57300c0 ++#define FSTV0910_P1_TSFIFO_PERMDATA 0xf5730020 ++#define FSTV0910_P1_TSFIFO_NONEWSGNL 0xf5730010 ++#define FSTV0910_P1_NPD_SPECDVBS2 0xf5730004 ++#define FSTV0910_P1_TSFIFO_DPUNACTIVE 0xf5730002 ++#define FSTV0910_P1_TSFIFO_INVDATA 0xf5730001 ++ ++/*P1_TSCFGL*/ ++#define RSTV0910_P1_TSCFGL 0xf574 ++#define FSTV0910_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 ++#define FSTV0910_P1_BCHERROR_MODE 0xf5740030 ++#define FSTV0910_P1_TSFIFO_NSGNL2DATA 0xf5740008 ++#define FSTV0910_P1_TSFIFO_EMBINDVB 0xf5740004 ++#define FSTV0910_P1_TSFIFO_BITSPEED 0xf5740003 ++ ++/*P1_TSINSDELH*/ ++#define RSTV0910_P1_TSINSDELH 0xf576 ++#define FSTV0910_P1_TSDEL_SYNCBYTE 0xf5760080 ++#define FSTV0910_P1_TSDEL_XXHEADER 0xf5760040 ++#define FSTV0910_P1_TSDEL_BBHEADER 0xf5760020 ++#define FSTV0910_P1_TSDEL_DATAFIELD 0xf5760010 ++#define FSTV0910_P1_TSINSDEL_ISCR 0xf5760008 ++#define FSTV0910_P1_TSINSDEL_NPD 0xf5760004 ++#define FSTV0910_P1_TSINSDEL_RSPARITY 0xf5760002 ++#define FSTV0910_P1_TSINSDEL_CRC8 0xf5760001 ++ ++/*P1_TSDIVN*/ ++#define RSTV0910_P1_TSDIVN 0xf579 ++#define FSTV0910_P1_TSFIFO_SPEEDMODE 0xf57900c0 ++#define FSTV0910_P1_BYTE_OVERSAMPLING 0xf5790038 ++#define FSTV0910_P1_TSFIFO_RISEOK 0xf5790007 ++ ++/*P1_TSCFG4*/ ++#define RSTV0910_P1_TSCFG4 0xf57a ++#define FSTV0910_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0 ++#define FSTV0910_P1_TSFIFO_HIERSEL 0xf57a0020 ++#define FSTV0910_P1_TSFIFO_SPECTOKEN 0xf57a0010 ++#define FSTV0910_P1_TSFIFO_MAXMODE 0xf57a0008 ++#define FSTV0910_P1_TSFIFO_FRFORCEPKT 0xf57a0004 ++#define FSTV0910_P1_EXT_FECSPYIN 0xf57a0002 ++#define FSTV0910_P1_TSFIFO_DELSPEEDUP 0xf57a0001 ++ ++/*P1_TSSPEED*/ ++#define RSTV0910_P1_TSSPEED 0xf580 ++#define FSTV0910_P1_TSFIFO_OUTSPEED 0xf58000ff ++ ++/*P1_TSSTATUS*/ ++#define RSTV0910_P1_TSSTATUS 0xf581 ++#define FSTV0910_P1_TSFIFO_LINEOK 0xf5810080 ++#define FSTV0910_P1_TSFIFO_ERROR 0xf5810040 ++#define FSTV0910_P1_TSFIFO_DATA7 0xf5810020 ++#define FSTV0910_P1_TSFIFO_NOSYNC 0xf5810010 ++#define FSTV0910_P1_ISCR_INITIALIZED 0xf5810008 ++#define FSTV0910_P1_TSREGUL_ERROR 0xf5810004 ++#define FSTV0910_P1_SOFFIFO_UNREGUL 0xf5810002 ++#define FSTV0910_P1_DIL_READY 0xf5810001 ++ ++/*P1_TSSTATUS2*/ ++#define RSTV0910_P1_TSSTATUS2 0xf582 ++#define FSTV0910_P1_TSFIFO_DEMODSEL 0xf5820080 ++#define FSTV0910_P1_TSFIFOSPEED_STORE 0xf5820040 ++#define FSTV0910_P1_DILXX_RESET 0xf5820020 ++#define FSTV0910_P1_TSSPEED_IMPOSSIBLE 0xf5820010 ++#define FSTV0910_P1_TSFIFO_LINENOK 0xf5820008 ++#define FSTV0910_P1_TSFIFO_MUXSTREAM 0xf5820004 ++#define FSTV0910_P1_SCRAMBDETECT 0xf5820002 ++#define FSTV0910_P1_ULDTV67_FALSELOCK 0xf5820001 ++ ++/*P1_TSBITRATE1*/ ++#define RSTV0910_P1_TSBITRATE1 0xf583 ++#define FSTV0910_P1_TSFIFO_BITRATE1 0xf58300ff ++ ++/*P1_TSBITRATE0*/ ++#define RSTV0910_P1_TSBITRATE0 0xf584 ++#define FSTV0910_P1_TSFIFO_BITRATE0 0xf58400ff ++ ++/*P1_ERRCTRL1*/ ++#define RSTV0910_P1_ERRCTRL1 0xf598 ++#define FSTV0910_P1_ERR_SOURCE1 0xf59800f0 ++#define FSTV0910_P1_NUM_EVENT1 0xf5980007 ++ ++/*P1_ERRCNT12*/ ++#define RSTV0910_P1_ERRCNT12 0xf599 ++#define FSTV0910_P1_ERRCNT1_OLDVALUE 0xf5990080 ++#define FSTV0910_P1_ERR_CNT12 0xf599007f ++ ++/*P1_ERRCNT11*/ ++#define RSTV0910_P1_ERRCNT11 0xf59a ++#define FSTV0910_P1_ERR_CNT11 0xf59a00ff ++ ++/*P1_ERRCNT10*/ ++#define RSTV0910_P1_ERRCNT10 0xf59b ++#define FSTV0910_P1_ERR_CNT10 0xf59b00ff ++ ++/*P1_ERRCTRL2*/ ++#define RSTV0910_P1_ERRCTRL2 0xf59c ++#define FSTV0910_P1_ERR_SOURCE2 0xf59c00f0 ++#define FSTV0910_P1_NUM_EVENT2 0xf59c0007 ++ ++/*P1_ERRCNT22*/ ++#define RSTV0910_P1_ERRCNT22 0xf59d ++#define FSTV0910_P1_ERRCNT2_OLDVALUE 0xf59d0080 ++#define FSTV0910_P1_ERR_CNT22 0xf59d007f ++ ++/*P1_ERRCNT21*/ ++#define RSTV0910_P1_ERRCNT21 0xf59e ++#define FSTV0910_P1_ERR_CNT21 0xf59e00ff ++ ++/*P1_ERRCNT20*/ ++#define RSTV0910_P1_ERRCNT20 0xf59f ++#define FSTV0910_P1_ERR_CNT20 0xf59f00ff ++ ++/*P1_FECSPY*/ ++#define RSTV0910_P1_FECSPY 0xf5a0 ++#define FSTV0910_P1_SPY_ENABLE 0xf5a00080 ++#define FSTV0910_P1_NO_SYNCBYTE 0xf5a00040 ++#define FSTV0910_P1_SERIAL_MODE 0xf5a00020 ++#define FSTV0910_P1_UNUSUAL_PACKET 0xf5a00010 ++#define FSTV0910_P1_BERMETER_DATAMODE 0xf5a0000c ++#define FSTV0910_P1_BERMETER_LMODE 0xf5a00002 ++#define FSTV0910_P1_BERMETER_RESET 0xf5a00001 ++ ++/*P1_FSPYCFG*/ ++#define RSTV0910_P1_FSPYCFG 0xf5a1 ++#define FSTV0910_P1_FECSPY_INPUT 0xf5a100c0 ++#define FSTV0910_P1_RST_ON_ERROR 0xf5a10020 ++#define FSTV0910_P1_ONE_SHOT 0xf5a10010 ++#define FSTV0910_P1_I2C_MODE 0xf5a1000c ++#define FSTV0910_P1_SPY_HYSTERESIS 0xf5a10003 ++ ++/*P1_FSPYDATA*/ ++#define RSTV0910_P1_FSPYDATA 0xf5a2 ++#define FSTV0910_P1_SPY_STUFFING 0xf5a20080 ++#define FSTV0910_P1_NOERROR_PKTJITTER 0xf5a20040 ++#define FSTV0910_P1_SPY_CNULLPKT 0xf5a20020 ++#define FSTV0910_P1_SPY_OUTDATA_MODE 0xf5a2001f ++ ++/*P1_FSPYOUT*/ ++#define RSTV0910_P1_FSPYOUT 0xf5a3 ++#define FSTV0910_P1_FSPY_DIRECT 0xf5a30080 ++#define FSTV0910_P1_SPY_OUTDATA_BUS 0xf5a30038 ++#define FSTV0910_P1_STUFF_MODE 0xf5a30007 ++ ++/*P1_FSTATUS*/ ++#define RSTV0910_P1_FSTATUS 0xf5a4 ++#define FSTV0910_P1_SPY_ENDSIM 0xf5a40080 ++#define FSTV0910_P1_VALID_SIM 0xf5a40040 ++#define FSTV0910_P1_FOUND_SIGNAL 0xf5a40020 ++#define FSTV0910_P1_DSS_SYNCBYTE 0xf5a40010 ++#define FSTV0910_P1_RESULT_STATE 0xf5a4000f ++ ++/*P1_FBERCPT4*/ ++#define RSTV0910_P1_FBERCPT4 0xf5a8 ++#define FSTV0910_P1_FBERMETER_CPT4 0xf5a800ff ++ ++/*P1_FBERCPT3*/ ++#define RSTV0910_P1_FBERCPT3 0xf5a9 ++#define FSTV0910_P1_FBERMETER_CPT3 0xf5a900ff ++ ++/*P1_FBERCPT2*/ ++#define RSTV0910_P1_FBERCPT2 0xf5aa ++#define FSTV0910_P1_FBERMETER_CPT2 0xf5aa00ff ++ ++/*P1_FBERCPT1*/ ++#define RSTV0910_P1_FBERCPT1 0xf5ab ++#define FSTV0910_P1_FBERMETER_CPT1 0xf5ab00ff ++ ++/*P1_FBERCPT0*/ ++#define RSTV0910_P1_FBERCPT0 0xf5ac ++#define FSTV0910_P1_FBERMETER_CPT0 0xf5ac00ff ++ ++/*P1_FBERERR2*/ ++#define RSTV0910_P1_FBERERR2 0xf5ad ++#define FSTV0910_P1_FBERMETER_ERR2 0xf5ad00ff ++ ++/*P1_FBERERR1*/ ++#define RSTV0910_P1_FBERERR1 0xf5ae ++#define FSTV0910_P1_FBERMETER_ERR1 0xf5ae00ff ++ ++/*P1_FBERERR0*/ ++#define RSTV0910_P1_FBERERR0 0xf5af ++#define FSTV0910_P1_FBERMETER_ERR0 0xf5af00ff ++ ++/*P1_FSPYBER*/ ++#define RSTV0910_P1_FSPYBER 0xf5b2 ++#define FSTV0910_P1_FSPYOBS_XORREAD 0xf5b20040 ++#define FSTV0910_P1_FSPYBER_OBSMODE 0xf5b20020 ++#define FSTV0910_P1_FSPYBER_SYNCBYTE 0xf5b20010 ++#define FSTV0910_P1_FSPYBER_UNSYNC 0xf5b20008 ++#define FSTV0910_P1_FSPYBER_CTIME 0xf5b20007 ++ ++/*P1_SFERROR*/ ++#define RSTV0910_P1_SFERROR 0xf5c1 ++#define FSTV0910_P1_SFEC_REGERR_VIT 0xf5c100ff ++ ++/*P1_SFECSTATUS*/ ++#define RSTV0910_P1_SFECSTATUS 0xf5c3 ++#define FSTV0910_P1_SFEC_ON 0xf5c30080 ++#define FSTV0910_P1_SFEC_OFF 0xf5c30040 ++#define FSTV0910_P1_LOCKEDSFEC 0xf5c30008 ++#define FSTV0910_P1_SFEC_DELOCK 0xf5c30004 ++#define FSTV0910_P1_SFEC_DEMODSEL 0xf5c30002 ++#define FSTV0910_P1_SFEC_OVFON 0xf5c30001 ++ ++/*P1_SFKDIV12*/ ++#define RSTV0910_P1_SFKDIV12 0xf5c4 ++#define FSTV0910_P1_SFECKDIV12_MAN 0xf5c40080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_12 0xf5c4007f ++ ++/*P1_SFKDIV23*/ ++#define RSTV0910_P1_SFKDIV23 0xf5c5 ++#define FSTV0910_P1_SFECKDIV23_MAN 0xf5c50080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_23 0xf5c5007f ++ ++/*P1_SFKDIV34*/ ++#define RSTV0910_P1_SFKDIV34 0xf5c6 ++#define FSTV0910_P1_SFECKDIV34_MAN 0xf5c60080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_34 0xf5c6007f ++ ++/*P1_SFKDIV56*/ ++#define RSTV0910_P1_SFKDIV56 0xf5c7 ++#define FSTV0910_P1_SFECKDIV56_MAN 0xf5c70080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_56 0xf5c7007f ++ ++/*P1_SFKDIV67*/ ++#define RSTV0910_P1_SFKDIV67 0xf5c8 ++#define FSTV0910_P1_SFECKDIV67_MAN 0xf5c80080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_67 0xf5c8007f ++ ++/*P1_SFKDIV78*/ ++#define RSTV0910_P1_SFKDIV78 0xf5c9 ++#define FSTV0910_P1_SFECKDIV78_MAN 0xf5c90080 ++#define FSTV0910_P1_SFEC_K_DIVIDER_78 0xf5c9007f ++ ++/*P1_SFSTATUS*/ ++#define RSTV0910_P1_SFSTATUS 0xf5cc ++#define FSTV0910_P1_SFEC_LINEOK 0xf5cc0080 ++#define FSTV0910_P1_SFEC_ERROR 0xf5cc0040 ++#define FSTV0910_P1_SFEC_DATA7 0xf5cc0020 ++#define FSTV0910_P1_SFEC_PKTDNBRFAIL 0xf5cc0010 ++#define FSTV0910_P1_TSSFEC_DEMODSEL 0xf5cc0008 ++#define FSTV0910_P1_SFEC_NOSYNC 0xf5cc0004 ++#define FSTV0910_P1_SFEC_UNREGULA 0xf5cc0002 ++#define FSTV0910_P1_SFEC_READY 0xf5cc0001 ++ ++/*P1_SFDLYSET2*/ ++#define RSTV0910_P1_SFDLYSET2 0xf5d0 ++#define FSTV0910_P1_SFEC_OFFSET 0xf5d000c0 ++#define FSTV0910_P1_RST_SFEC 0xf5d00008 ++#define FSTV0910_P1_DILDLINE_ERROR 0xf5d00004 ++#define FSTV0910_P1_SFEC_DISABLE 0xf5d00002 ++#define FSTV0910_P1_SFEC_UNREGUL 0xf5d00001 ++ ++/*P1_SFERRCTRL*/ ++#define RSTV0910_P1_SFERRCTRL 0xf5d8 ++#define FSTV0910_P1_SFEC_ERR_SOURCE 0xf5d800f0 ++#define FSTV0910_P1_SFEC_NUM_EVENT 0xf5d80007 ++ ++/*P1_SFERRCNT2*/ ++#define RSTV0910_P1_SFERRCNT2 0xf5d9 ++#define FSTV0910_P1_SFERRC_OLDVALUE 0xf5d90080 ++#define FSTV0910_P1_SFEC_ERR_CNT2 0xf5d9007f ++ ++/*P1_SFERRCNT1*/ ++#define RSTV0910_P1_SFERRCNT1 0xf5da ++#define FSTV0910_P1_SFEC_ERR_CNT1 0xf5da00ff ++ ++/*P1_SFERRCNT0*/ ++#define RSTV0910_P1_SFERRCNT0 0xf5db ++#define FSTV0910_P1_SFEC_ERR_CNT0 0xf5db00ff ++ ++/*TSGENERAL*/ ++#define RSTV0910_TSGENERAL 0xf630 ++#define FSTV0910_EN_LGNERROR 0xf6300080 ++#define FSTV0910_TSFIFO_DISTS2PAR 0xf6300040 ++#define FSTV0910_MUXSTREAM_COMPMOSE 0xf6300030 ++#define FSTV0910_MUXSTREAM_OUTMODE 0xf6300008 ++#define FSTV0910_TSFIFO_PERMPARAL 0xf6300006 ++#define FSTV0910_RST_REEDSOLO 0xf6300001 ++ ++/*P1_DISIRQCFG*/ ++#define RSTV0910_P1_DISIRQCFG 0xf700 ++#define FSTV0910_P1_ENRXEND 0xf7000040 ++#define FSTV0910_P1_ENRXFIFO8B 0xf7000020 ++#define FSTV0910_P1_ENTRFINISH 0xf7000010 ++#define FSTV0910_P1_ENTIMEOUT 0xf7000008 ++#define FSTV0910_P1_ENTXEND 0xf7000004 ++#define FSTV0910_P1_ENTXFIFO64B 0xf7000002 ++#define FSTV0910_P1_ENGAPBURST 0xf7000001 ++ ++/*P1_DISIRQSTAT*/ ++#define RSTV0910_P1_DISIRQSTAT 0xf701 ++#define FSTV0910_P1_IRQRXEND 0xf7010040 ++#define FSTV0910_P1_IRQRXFIFO8B 0xf7010020 ++#define FSTV0910_P1_IRQTRFINISH 0xf7010010 ++#define FSTV0910_P1_IRQTIMEOUT 0xf7010008 ++#define FSTV0910_P1_IRQTXEND 0xf7010004 ++#define FSTV0910_P1_IRQTXFIFO64B 0xf7010002 ++#define FSTV0910_P1_IRQGAPBURST 0xf7010001 ++ ++/*P1_DISTXCFG*/ ++#define RSTV0910_P1_DISTXCFG 0xf702 ++#define FSTV0910_P1_DISTX_RESET 0xf7020080 ++#define FSTV0910_P1_TIM_OFF 0xf7020040 ++#define FSTV0910_P1_TIM_CMD 0xf7020030 ++#define FSTV0910_P1_ENVELOP 0xf7020008 ++#define FSTV0910_P1_DIS_PRECHARGE 0xf7020004 ++#define FSTV0910_P1_DISEQC_MODE 0xf7020003 ++ ++/*P1_DISTXSTATUS*/ ++#define RSTV0910_P1_DISTXSTATUS 0xf703 ++#define FSTV0910_P1_TX_FIFO_FULL 0xf7030040 ++#define FSTV0910_P1_TX_IDLE 0xf7030020 ++#define FSTV0910_P1_GAP_BURST 0xf7030010 ++#define FSTV0910_P1_TX_FIFO64B 0xf7030008 ++#define FSTV0910_P1_TX_END 0xf7030004 ++#define FSTV0910_P1_TR_TIMEOUT 0xf7030002 ++#define FSTV0910_P1_TR_FINISH 0xf7030001 ++ ++/*P1_DISTXBYTES*/ ++#define RSTV0910_P1_DISTXBYTES 0xf704 ++#define FSTV0910_P1_TXFIFO_BYTES 0xf70400ff ++ ++/*P1_DISTXFIFO*/ ++#define RSTV0910_P1_DISTXFIFO 0xf705 ++#define FSTV0910_P1_DISEQC_TX_FIFO 0xf70500ff ++ ++/*P1_DISTXF22*/ ++#define RSTV0910_P1_DISTXF22 0xf706 ++#define FSTV0910_P1_F22TX 0xf70600ff ++ ++/*P1_DISTIMEOCFG*/ ++#define RSTV0910_P1_DISTIMEOCFG 0xf708 ++#define FSTV0910_P1_RXCHOICE 0xf7080006 ++#define FSTV0910_P1_TIMEOUT_OFF 0xf7080001 ++ ++/*P1_DISTIMEOUT*/ ++#define RSTV0910_P1_DISTIMEOUT 0xf709 ++#define FSTV0910_P1_TIMEOUT_COUNT 0xf70900ff ++ ++/*P1_DISRXCFG*/ ++#define RSTV0910_P1_DISRXCFG 0xf70a ++#define FSTV0910_P1_DISRX_RESET 0xf70a0080 ++#define FSTV0910_P1_EXTENVELOP 0xf70a0040 ++#define FSTV0910_P1_PINSELECT 0xf70a0038 ++#define FSTV0910_P1_IGNORE_SHORT22K 0xf70a0004 ++#define FSTV0910_P1_SIGNED_RXIN 0xf70a0002 ++#define FSTV0910_P1_DISRX_ON 0xf70a0001 ++ ++/*P1_DISRXSTAT1*/ ++#define RSTV0910_P1_DISRXSTAT1 0xf70b ++#define FSTV0910_P1_RXEND 0xf70b0080 ++#define FSTV0910_P1_RXACTIVE 0xf70b0040 ++#define FSTV0910_P1_RXDETECT 0xf70b0020 ++#define FSTV0910_P1_CONTTONE 0xf70b0010 ++#define FSTV0910_P1_8BFIFOREADY 0xf70b0008 ++#define FSTV0910_P1_FIFOEMPTY 0xf70b0004 ++ ++/*P1_DISRXSTAT0*/ ++#define RSTV0910_P1_DISRXSTAT0 0xf70c ++#define FSTV0910_P1_RXFAIL 0xf70c0080 ++#define FSTV0910_P1_FIFOPFAIL 0xf70c0040 ++#define FSTV0910_P1_RXNONBYTE 0xf70c0020 ++#define FSTV0910_P1_FIFOOVF 0xf70c0010 ++#define FSTV0910_P1_SHORT22K 0xf70c0008 ++#define FSTV0910_P1_RXMSGLOST 0xf70c0004 ++ ++/*P1_DISRXBYTES*/ ++#define RSTV0910_P1_DISRXBYTES 0xf70d ++#define FSTV0910_P1_RXFIFO_BYTES 0xf70d001f ++ ++/*P1_DISRXPARITY1*/ ++#define RSTV0910_P1_DISRXPARITY1 0xf70e ++#define FSTV0910_P1_DISRX_PARITY1 0xf70e00ff ++ ++/*P1_DISRXPARITY0*/ ++#define RSTV0910_P1_DISRXPARITY0 0xf70f ++#define FSTV0910_P1_DISRX_PARITY0 0xf70f00ff ++ ++/*P1_DISRXFIFO*/ ++#define RSTV0910_P1_DISRXFIFO 0xf710 ++#define FSTV0910_P1_DISEQC_RX_FIFO 0xf71000ff ++ ++/*P1_DISRXDC1*/ ++#define RSTV0910_P1_DISRXDC1 0xf711 ++#define FSTV0910_P1_DC_VALUE1 0xf7110103 ++ ++/*P1_DISRXDC0*/ ++#define RSTV0910_P1_DISRXDC0 0xf712 ++#define FSTV0910_P1_DC_VALUE0 0xf71200ff ++ ++/*P1_DISRXF221*/ ++#define RSTV0910_P1_DISRXF221 0xf714 ++#define FSTV0910_P1_F22RX1 0xf714000f ++ ++/*P1_DISRXF220*/ ++#define RSTV0910_P1_DISRXF220 0xf715 ++#define FSTV0910_P1_F22RX0 0xf71500ff ++ ++/*P1_DISRXF100*/ ++#define RSTV0910_P1_DISRXF100 0xf716 ++#define FSTV0910_P1_F100RX 0xf71600ff ++ ++/*P1_DISRXSHORT22K*/ ++#define RSTV0910_P1_DISRXSHORT22K 0xf71c ++#define FSTV0910_P1_SHORT22K_LENGTH 0xf71c001f ++ ++/*P1_ACRPRESC*/ ++#define RSTV0910_P1_ACRPRESC 0xf71e ++#define FSTV0910_P1_ACR_CODFRDY 0xf71e0008 ++#define FSTV0910_P1_ACR_PRESC 0xf71e0007 ++ ++/*P1_ACRDIV*/ ++#define RSTV0910_P1_ACRDIV 0xf71f ++#define FSTV0910_P1_ACR_DIV 0xf71f00ff ++ ++/*P2_DISIRQCFG*/ ++#define RSTV0910_P2_DISIRQCFG 0xf740 ++#define FSTV0910_P2_ENRXEND 0xf7400040 ++#define FSTV0910_P2_ENRXFIFO8B 0xf7400020 ++#define FSTV0910_P2_ENTRFINISH 0xf7400010 ++#define FSTV0910_P2_ENTIMEOUT 0xf7400008 ++#define FSTV0910_P2_ENTXEND 0xf7400004 ++#define FSTV0910_P2_ENTXFIFO64B 0xf7400002 ++#define FSTV0910_P2_ENGAPBURST 0xf7400001 ++ ++/*P2_DISIRQSTAT*/ ++#define RSTV0910_P2_DISIRQSTAT 0xf741 ++#define FSTV0910_P2_IRQRXEND 0xf7410040 ++#define FSTV0910_P2_IRQRXFIFO8B 0xf7410020 ++#define FSTV0910_P2_IRQTRFINISH 0xf7410010 ++#define FSTV0910_P2_IRQTIMEOUT 0xf7410008 ++#define FSTV0910_P2_IRQTXEND 0xf7410004 ++#define FSTV0910_P2_IRQTXFIFO64B 0xf7410002 ++#define FSTV0910_P2_IRQGAPBURST 0xf7410001 ++ ++/*P2_DISTXCFG*/ ++#define RSTV0910_P2_DISTXCFG 0xf742 ++#define FSTV0910_P2_DISTX_RESET 0xf7420080 ++#define FSTV0910_P2_TIM_OFF 0xf7420040 ++#define FSTV0910_P2_TIM_CMD 0xf7420030 ++#define FSTV0910_P2_ENVELOP 0xf7420008 ++#define FSTV0910_P2_DIS_PRECHARGE 0xf7420004 ++#define FSTV0910_P2_DISEQC_MODE 0xf7420003 ++ ++/*P2_DISTXSTATUS*/ ++#define RSTV0910_P2_DISTXSTATUS 0xf743 ++#define FSTV0910_P2_TX_FIFO_FULL 0xf7430040 ++#define FSTV0910_P2_TX_IDLE 0xf7430020 ++#define FSTV0910_P2_GAP_BURST 0xf7430010 ++#define FSTV0910_P2_TX_FIFO64B 0xf7430008 ++#define FSTV0910_P2_TX_END 0xf7430004 ++#define FSTV0910_P2_TR_TIMEOUT 0xf7430002 ++#define FSTV0910_P2_TR_FINISH 0xf7430001 ++ ++/*P2_DISTXBYTES*/ ++#define RSTV0910_P2_DISTXBYTES 0xf744 ++#define FSTV0910_P2_TXFIFO_BYTES 0xf74400ff ++ ++/*P2_DISTXFIFO*/ ++#define RSTV0910_P2_DISTXFIFO 0xf745 ++#define FSTV0910_P2_DISEQC_TX_FIFO 0xf74500ff ++ ++/*P2_DISTXF22*/ ++#define RSTV0910_P2_DISTXF22 0xf746 ++#define FSTV0910_P2_F22TX 0xf74600ff ++ ++/*P2_DISTIMEOCFG*/ ++#define RSTV0910_P2_DISTIMEOCFG 0xf748 ++#define FSTV0910_P2_RXCHOICE 0xf7480006 ++#define FSTV0910_P2_TIMEOUT_OFF 0xf7480001 ++ ++/*P2_DISTIMEOUT*/ ++#define RSTV0910_P2_DISTIMEOUT 0xf749 ++#define FSTV0910_P2_TIMEOUT_COUNT 0xf74900ff ++ ++/*P2_DISRXCFG*/ ++#define RSTV0910_P2_DISRXCFG 0xf74a ++#define FSTV0910_P2_DISRX_RESET 0xf74a0080 ++#define FSTV0910_P2_EXTENVELOP 0xf74a0040 ++#define FSTV0910_P2_PINSELECT 0xf74a0038 ++#define FSTV0910_P2_IGNORE_SHORT22K 0xf74a0004 ++#define FSTV0910_P2_SIGNED_RXIN 0xf74a0002 ++#define FSTV0910_P2_DISRX_ON 0xf74a0001 ++ ++/*P2_DISRXSTAT1*/ ++#define RSTV0910_P2_DISRXSTAT1 0xf74b ++#define FSTV0910_P2_RXEND 0xf74b0080 ++#define FSTV0910_P2_RXACTIVE 0xf74b0040 ++#define FSTV0910_P2_RXDETECT 0xf74b0020 ++#define FSTV0910_P2_CONTTONE 0xf74b0010 ++#define FSTV0910_P2_8BFIFOREADY 0xf74b0008 ++#define FSTV0910_P2_FIFOEMPTY 0xf74b0004 ++ ++/*P2_DISRXSTAT0*/ ++#define RSTV0910_P2_DISRXSTAT0 0xf74c ++#define FSTV0910_P2_RXFAIL 0xf74c0080 ++#define FSTV0910_P2_FIFOPFAIL 0xf74c0040 ++#define FSTV0910_P2_RXNONBYTE 0xf74c0020 ++#define FSTV0910_P2_FIFOOVF 0xf74c0010 ++#define FSTV0910_P2_SHORT22K 0xf74c0008 ++#define FSTV0910_P2_RXMSGLOST 0xf74c0004 ++ ++/*P2_DISRXBYTES*/ ++#define RSTV0910_P2_DISRXBYTES 0xf74d ++#define FSTV0910_P2_RXFIFO_BYTES 0xf74d001f ++ ++/*P2_DISRXPARITY1*/ ++#define RSTV0910_P2_DISRXPARITY1 0xf74e ++#define FSTV0910_P2_DISRX_PARITY1 0xf74e00ff ++ ++/*P2_DISRXPARITY0*/ ++#define RSTV0910_P2_DISRXPARITY0 0xf74f ++#define FSTV0910_P2_DISRX_PARITY0 0xf74f00ff ++ ++/*P2_DISRXFIFO*/ ++#define RSTV0910_P2_DISRXFIFO 0xf750 ++#define FSTV0910_P2_DISEQC_RX_FIFO 0xf75000ff ++ ++/*P2_DISRXDC1*/ ++#define RSTV0910_P2_DISRXDC1 0xf751 ++#define FSTV0910_P2_DC_VALUE1 0xf7510103 ++ ++/*P2_DISRXDC0*/ ++#define RSTV0910_P2_DISRXDC0 0xf752 ++#define FSTV0910_P2_DC_VALUE0 0xf75200ff ++ ++/*P2_DISRXF221*/ ++#define RSTV0910_P2_DISRXF221 0xf754 ++#define FSTV0910_P2_F22RX1 0xf754000f ++ ++/*P2_DISRXF220*/ ++#define RSTV0910_P2_DISRXF220 0xf755 ++#define FSTV0910_P2_F22RX0 0xf75500ff ++ ++/*P2_DISRXF100*/ ++#define RSTV0910_P2_DISRXF100 0xf756 ++#define FSTV0910_P2_F100RX 0xf75600ff ++ ++/*P2_DISRXSHORT22K*/ ++#define RSTV0910_P2_DISRXSHORT22K 0xf75c ++#define FSTV0910_P2_SHORT22K_LENGTH 0xf75c001f ++ ++/*P2_ACRPRESC*/ ++#define RSTV0910_P2_ACRPRESC 0xf75e ++#define FSTV0910_P2_ACR_CODFRDY 0xf75e0008 ++#define FSTV0910_P2_ACR_PRESC 0xf75e0007 ++ ++/*P2_ACRDIV*/ ++#define RSTV0910_P2_ACRDIV 0xf75f ++#define FSTV0910_P2_ACR_DIV 0xf75f00ff ++ ++/*P1_NBITER_NF4*/ ++#define RSTV0910_P1_NBITER_NF4 0xfa03 ++#define FSTV0910_P1_NBITER_NF_QPSK_1_2 0xfa0300ff ++ ++/*P1_NBITER_NF5*/ ++#define RSTV0910_P1_NBITER_NF5 0xfa04 ++#define FSTV0910_P1_NBITER_NF_QPSK_3_5 0xfa0400ff ++ ++/*P1_NBITER_NF6*/ ++#define RSTV0910_P1_NBITER_NF6 0xfa05 ++#define FSTV0910_P1_NBITER_NF_QPSK_2_3 0xfa0500ff ++ ++/*P1_NBITER_NF7*/ ++#define RSTV0910_P1_NBITER_NF7 0xfa06 ++#define FSTV0910_P1_NBITER_NF_QPSK_3_4 0xfa0600ff ++ ++/*P1_NBITER_NF8*/ ++#define RSTV0910_P1_NBITER_NF8 0xfa07 ++#define FSTV0910_P1_NBITER_NF_QPSK_4_5 0xfa0700ff ++ ++/*P1_NBITER_NF9*/ ++#define RSTV0910_P1_NBITER_NF9 0xfa08 ++#define FSTV0910_P1_NBITER_NF_QPSK_5_6 0xfa0800ff ++ ++/*P1_NBITER_NF10*/ ++#define RSTV0910_P1_NBITER_NF10 0xfa09 ++#define FSTV0910_P1_NBITER_NF_QPSK_8_9 0xfa0900ff ++ ++/*P1_NBITER_NF11*/ ++#define RSTV0910_P1_NBITER_NF11 0xfa0a ++#define FSTV0910_P1_NBITER_NF_QPSK_9_10 0xfa0a00ff ++ ++/*P1_NBITER_NF12*/ ++#define RSTV0910_P1_NBITER_NF12 0xfa0b ++#define FSTV0910_P1_NBITER_NF_8PSK_3_5 0xfa0b00ff ++ ++/*P1_NBITER_NF13*/ ++#define RSTV0910_P1_NBITER_NF13 0xfa0c ++#define FSTV0910_P1_NBITER_NF_8PSK_2_3 0xfa0c00ff ++ ++/*P1_NBITER_NF14*/ ++#define RSTV0910_P1_NBITER_NF14 0xfa0d ++#define FSTV0910_P1_NBITER_NF_8PSK_3_4 0xfa0d00ff ++ ++/*P1_NBITER_NF15*/ ++#define RSTV0910_P1_NBITER_NF15 0xfa0e ++#define FSTV0910_P1_NBITER_NF_8PSK_5_6 0xfa0e00ff ++ ++/*P1_NBITER_NF16*/ ++#define RSTV0910_P1_NBITER_NF16 0xfa0f ++#define FSTV0910_P1_NBITER_NF_8PSK_8_9 0xfa0f00ff ++ ++/*P1_NBITER_NF17*/ ++#define RSTV0910_P1_NBITER_NF17 0xfa10 ++#define FSTV0910_P1_NBITER_NF_8PSK_9_10 0xfa1000ff ++ ++/*GAINLLR_NF4*/ ++#define RSTV0910_GAINLLR_NF4 0xfa43 ++#define FSTV0910_GAINLLR_NF_QPSK_1_2 0xfa43007f ++ ++/*GAINLLR_NF5*/ ++#define RSTV0910_GAINLLR_NF5 0xfa44 ++#define FSTV0910_GAINLLR_NF_QPSK_3_5 0xfa44007f ++ ++/*GAINLLR_NF6*/ ++#define RSTV0910_GAINLLR_NF6 0xfa45 ++#define FSTV0910_GAINLLR_NF_QPSK_2_3 0xfa45007f ++ ++/*GAINLLR_NF7*/ ++#define RSTV0910_GAINLLR_NF7 0xfa46 ++#define FSTV0910_GAINLLR_NF_QPSK_3_4 0xfa46007f ++ ++/*GAINLLR_NF8*/ ++#define RSTV0910_GAINLLR_NF8 0xfa47 ++#define FSTV0910_GAINLLR_NF_QPSK_4_5 0xfa47007f ++ ++/*GAINLLR_NF9*/ ++#define RSTV0910_GAINLLR_NF9 0xfa48 ++#define FSTV0910_GAINLLR_NF_QPSK_5_6 0xfa48007f ++ ++/*GAINLLR_NF10*/ ++#define RSTV0910_GAINLLR_NF10 0xfa49 ++#define FSTV0910_GAINLLR_NF_QPSK_8_9 0xfa49007f ++ ++/*GAINLLR_NF11*/ ++#define RSTV0910_GAINLLR_NF11 0xfa4a ++#define FSTV0910_GAINLLR_NF_QPSK_9_10 0xfa4a007f ++ ++/*GAINLLR_NF12*/ ++#define RSTV0910_GAINLLR_NF12 0xfa4b ++#define FSTV0910_GAINLLR_NF_8PSK_3_5 0xfa4b007f ++ ++/*GAINLLR_NF13*/ ++#define RSTV0910_GAINLLR_NF13 0xfa4c ++#define FSTV0910_GAINLLR_NF_8PSK_2_3 0xfa4c007f ++ ++/*GAINLLR_NF14*/ ++#define RSTV0910_GAINLLR_NF14 0xfa4d ++#define FSTV0910_GAINLLR_NF_8PSK_3_4 0xfa4d007f ++ ++/*GAINLLR_NF15*/ ++#define RSTV0910_GAINLLR_NF15 0xfa4e ++#define FSTV0910_GAINLLR_NF_8PSK_5_6 0xfa4e007f ++ ++/*GAINLLR_NF16*/ ++#define RSTV0910_GAINLLR_NF16 0xfa4f ++#define FSTV0910_GAINLLR_NF_8PSK_8_9 0xfa4f007f ++ ++/*GAINLLR_NF17*/ ++#define RSTV0910_GAINLLR_NF17 0xfa50 ++#define FSTV0910_GAINLLR_NF_8PSK_9_10 0xfa50007f ++ ++/*CFGEXT*/ ++#define RSTV0910_CFGEXT 0xfa80 ++#define FSTV0910_BYPFIFOBCH 0xfa800080 ++#define FSTV0910_BYPBCH 0xfa800040 ++#define FSTV0910_BYPLDPC 0xfa800020 ++#define FSTV0910_BYPFIFOBCHF 0xfa800010 ++#define FSTV0910_INVLLRSIGN 0xfa800008 ++#define FSTV0910_SHORTMULT 0xfa800004 ++#define FSTV0910_ENSTOPDEC 0xfa800002 ++ ++/*GENCFG*/ ++#define RSTV0910_GENCFG 0xfa86 ++#define FSTV0910_LEG_ITER 0xfa860040 ++#define FSTV0910_NOSHFRD1 0xfa860020 ++#define FSTV0910_BROADCAST 0xfa860010 ++#define FSTV0910_NOSHFRD2 0xfa860008 ++#define FSTV0910_BCHERRFLAG 0xfa860004 ++#define FSTV0910_CROSSINPUT 0xfa860002 ++#define FSTV0910_DDEMOD 0xfa860001 ++ ++/*LDPCERR1*/ ++#define RSTV0910_LDPCERR1 0xfa96 ++#define FSTV0910_LDPC_ERRORS1 0xfa9600ff ++ ++/*LDPCERR0*/ ++#define RSTV0910_LDPCERR0 0xfa97 ++#define FSTV0910_LDPC_ERRORS0 0xfa9700ff ++ ++/*BCHERR*/ ++#define RSTV0910_BCHERR 0xfa98 ++#define FSTV0910_ERRORFLAG 0xfa980010 ++#define FSTV0910_BCH_ERRORS_COUNTER 0xfa98000f ++ ++/*P1_MAXEXTRAITER*/ ++#define RSTV0910_P1_MAXEXTRAITER 0xfab1 ++#define FSTV0910_P1_MAX_EXTRA_ITER 0xfab100ff ++ ++/*P2_MAXEXTRAITER*/ ++#define RSTV0910_P2_MAXEXTRAITER 0xfab6 ++#define FSTV0910_P2_MAX_EXTRA_ITER 0xfab600ff ++ ++/*P1_STATUSITER*/ ++#define RSTV0910_P1_STATUSITER 0xfabc ++#define FSTV0910_P1_STATUS_ITER 0xfabc00ff ++ ++/*P1_STATUSMAXITER*/ ++#define RSTV0910_P1_STATUSMAXITER 0xfabd ++#define FSTV0910_P1_STATUS_MAX_ITER 0xfabd00ff ++ ++/*P2_STATUSITER*/ ++#define RSTV0910_P2_STATUSITER 0xfabe ++#define FSTV0910_P2_STATUS_ITER 0xfabe00ff ++ ++/*P2_STATUSMAXITER*/ ++#define RSTV0910_P2_STATUSMAXITER 0xfabf ++#define FSTV0910_P2_STATUS_MAX_ITER 0xfabf00ff ++ ++/*P2_NBITER_NF4*/ ++#define RSTV0910_P2_NBITER_NF4 0xfac3 ++#define FSTV0910_P2_NBITER_NF_QPSK_1_2 0xfac300ff ++ ++/*P2_NBITER_NF5*/ ++#define RSTV0910_P2_NBITER_NF5 0xfac4 ++#define FSTV0910_P2_NBITER_NF_QPSK_3_5 0xfac400ff ++ ++/*P2_NBITER_NF6*/ ++#define RSTV0910_P2_NBITER_NF6 0xfac5 ++#define FSTV0910_P2_NBITER_NF_QPSK_2_3 0xfac500ff ++ ++/*P2_NBITER_NF7*/ ++#define RSTV0910_P2_NBITER_NF7 0xfac6 ++#define FSTV0910_P2_NBITER_NF_QPSK_3_4 0xfac600ff ++ ++/*P2_NBITER_NF8*/ ++#define RSTV0910_P2_NBITER_NF8 0xfac7 ++#define FSTV0910_P2_NBITER_NF_QPSK_4_5 0xfac700ff ++ ++/*P2_NBITER_NF9*/ ++#define RSTV0910_P2_NBITER_NF9 0xfac8 ++#define FSTV0910_P2_NBITER_NF_QPSK_5_6 0xfac800ff ++ ++/*P2_NBITER_NF10*/ ++#define RSTV0910_P2_NBITER_NF10 0xfac9 ++#define FSTV0910_P2_NBITER_NF_QPSK_8_9 0xfac900ff ++ ++/*P2_NBITER_NF11*/ ++#define RSTV0910_P2_NBITER_NF11 0xfaca ++#define FSTV0910_P2_NBITER_NF_QPSK_9_10 0xfaca00ff ++ ++/*P2_NBITER_NF12*/ ++#define RSTV0910_P2_NBITER_NF12 0xfacb ++#define FSTV0910_P2_NBITER_NF_8PSK_3_5 0xfacb00ff ++ ++/*P2_NBITER_NF13*/ ++#define RSTV0910_P2_NBITER_NF13 0xfacc ++#define FSTV0910_P2_NBITER_NF_8PSK_2_3 0xfacc00ff ++ ++/*P2_NBITER_NF14*/ ++#define RSTV0910_P2_NBITER_NF14 0xfacd ++#define FSTV0910_P2_NBITER_NF_8PSK_3_4 0xfacd00ff ++ ++/*P2_NBITER_NF15*/ ++#define RSTV0910_P2_NBITER_NF15 0xface ++#define FSTV0910_P2_NBITER_NF_8PSK_5_6 0xface00ff ++ ++/*P2_NBITER_NF16*/ ++#define RSTV0910_P2_NBITER_NF16 0xfacf ++#define FSTV0910_P2_NBITER_NF_8PSK_8_9 0xfacf00ff ++ ++/*P2_NBITER_NF17*/ ++#define RSTV0910_P2_NBITER_NF17 0xfad0 ++#define FSTV0910_P2_NBITER_NF_8PSK_9_10 0xfad000ff ++ ++/*TSTRES0*/ ++#define RSTV0910_TSTRES0 0xff11 ++#define FSTV0910_FRESFEC 0xff110080 ++#define FSTV0910_FRESTS 0xff110040 ++#define FSTV0910_FRESVIT1 0xff110020 ++#define FSTV0910_FRESVIT2 0xff110010 ++#define FSTV0910_FRESSYM1 0xff110008 ++#define FSTV0910_FRESSYM2 0xff110004 ++#define FSTV0910_FRESMAS 0xff110002 ++#define FSTV0910_FRESINT 0xff110001 ++ ++/*P2_TCTL4*/ ++#define RSTV0910_P2_TCTL4 0xff28 ++#define FSTV0910_P2_CFR2TOCFR1_DVBS1 0xff2800c0 ++#define FSTV0910_P2_TSTINV_PHERR 0xff280020 ++#define FSTV0910_P2_EN_PLHCALC 0xff280010 ++#define FSTV0910_P2_TETA3L_RSTTETA3D 0xff280008 ++#define FSTV0910_P2_DIS_FORCEBETA2 0xff280004 ++#define FSTV0910_P2_CAR3_NOTRACEBACK 0xff280002 ++#define FSTV0910_P2_CAR3_NOFORWARD 0xff280001 ++ ++/*P1_TCTL4*/ ++#define RSTV0910_P1_TCTL4 0xff48 ++#define FSTV0910_P1_CFR2TOCFR1_DVBS1 0xff4800c0 ++#define FSTV0910_P1_TSTINV_PHERR 0xff480020 ++#define FSTV0910_P1_EN_PLHCALC 0xff480010 ++#define FSTV0910_P1_TETA3L_RSTTETA3D 0xff480008 ++#define FSTV0910_P1_DIS_FORCEBETA2 0xff480004 ++#define FSTV0910_P1_CAR3_NOTRACEBACK 0xff480002 ++#define FSTV0910_P1_CAR3_NOFORWARD 0xff480001 ++ ++#define STV0910_NBREGS 735 ++#define STV0910_NBFIELDS 1776 +diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c +new file mode 100644 +index 0000000..fbd6365 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv6111.c +@@ -0,0 +1,450 @@ ++/* ++ * Driver for the ST STV6111 tuner ++ * ++ * Copyright (C) 2014 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++static inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++ ++struct stv { ++ struct i2c_adapter *i2c; ++ u8 adr; ++ ++ u8 reg[11]; ++ u32 ref_freq; ++}; ++ ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ pr_err("stv6111: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ pr_err("stv6111: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int write_regs(struct stv *state, int reg, int len) ++{ ++ u8 d[12]; ++ ++ memcpy(&d[1], &state->reg[reg], len); ++ d[0] = reg; ++ return i2c_write(state->i2c, state->adr, d, len + 1); ++} ++ ++#if 0 ++static int write_reg(struct stv *state, u8 reg, u8 val) ++{ ++ u8 d[2] = {reg, val}; ++ ++ return i2c_write(state->i2c, state->adr, d, 2); ++} ++#endif ++ ++static int read_reg(struct stv *state, u8 reg, u8 *val) ++{ ++ return i2c_read(state->i2c, state->adr, ®, 1, val, 1); ++} ++ ++static int read_regs(struct stv *state, u8 reg, u8 *val, int len) ++{ ++ return i2c_read(state->i2c, state->adr, ®, 1, val, len); ++} ++ ++static void dump_regs(struct stv *state) ++{ ++ u8 d[11], *c = &state->reg[0]; ++ ++ read_regs(state, 0, d, 11); ++ pr_info("stv6111_regs = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], ++ d[8], d[9], d[10]); ++ pr_info("reg[] = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], ++ c[8], c[9], c[10]); ++} ++ ++static int wait_for_call_done(struct stv *state, u8 mask) ++{ ++ int status = 0; ++ u32 LockRetryCount = 10; ++ ++ while (LockRetryCount > 0) { ++ u8 Status; ++ ++ status = read_reg(state, 9, &Status); ++ if (status < 0) ++ return status; ++ ++ if ((Status & mask) == 0) ++ break; ++ usleep_range(4000, 6000); ++ LockRetryCount -= 1; ++ ++ status = -1; ++ } ++ return status; ++} ++ ++static void init_state(struct stv *state) ++{ ++ u32 clkdiv = 0; ++ u32 agcmode = 0; ++ u32 agcref = 2; ++ u32 agcset = 0xffffffff; ++ u32 bbmode = 0xffffffff; ++ ++ state->reg[0] = 0x08; ++ state->reg[1] = 0x41; ++ state->reg[2] = 0x8f; ++ state->reg[3] = 0x00; ++ state->reg[4] = 0xce; ++ state->reg[5] = 0x54; ++ state->reg[6] = 0x55; ++ state->reg[7] = 0x45; ++ state->reg[8] = 0x46; ++ state->reg[9] = 0xbd; ++ state->reg[10] = 0x11; ++ ++ state->ref_freq = 16000; ++ ++ ++ if (clkdiv <= 3) ++ state->reg[0x00] |= (clkdiv & 0x03); ++ if (agcmode <= 3) { ++ state->reg[0x03] |= (agcmode << 5); ++ if (agcmode == 0x01) ++ state->reg[0x01] |= 0x30; ++ } ++ if (bbmode <= 3) ++ state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4); ++ if (agcref <= 7) ++ state->reg[0x03] |= agcref; ++ if (agcset <= 31) ++ state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40; ++} ++ ++static int attach_init(struct stv *state) ++{ ++ if (write_regs(state, 0, 11)) ++ return -1; ++ pr_info("attach_init OK\n"); ++ dump_regs(state); ++ return 0; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ ++ pr_info("tuner sleep\n"); ++ return 0; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ pr_info("init\n"); ++ return 0; ++} ++ ++static int release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++ ++static int set_bandwidth(struct dvb_frontend *fe, u32 CutOffFrequency) ++{ ++ struct stv *state = fe->tuner_priv; ++ u32 index = (CutOffFrequency + 999999) / 1000000; ++ ++ if (index < 6) ++ index = 6; ++ if (index > 50) ++ index = 50; ++ if ((state->reg[0x08] & ~0xFC) == ((index-6) << 2)) ++ return 0; ++ ++ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index-6) << 2); ++ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x08; ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ write_regs(state, 0x08, 2); ++ wait_for_call_done(state, 0x08); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return 0; ++} ++ ++static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) ++{ ++ u32 index = (CutOffFrequency + 999999) / 1000000; ++ u32 Frequency = (LocalFrequency + 500) / 1000; ++ u32 p = 1, psel = 0, fvco, div, frac; ++ u8 Icp, tmp; ++ ++ pr_info("F = %u, COF = %u\n", Frequency, CutOffFrequency); ++ if (index < 6) ++ index = 6; ++ if (index > 50) ++ index = 50; ++ ++ if (Frequency <= 1300000) { ++ p = 4; ++ psel = 1; ++ } else { ++ p = 2; ++ psel = 0; ++ } ++ fvco = Frequency * p; ++ div = fvco / state->ref_freq; ++ frac = fvco % state->ref_freq; ++ frac = MulDiv32(frac, 0x40000, state->ref_freq); ++ ++ Icp = 0; ++ if (fvco < 2700000) ++ Icp = 0; ++ else if (fvco < 2950000) ++ Icp = 1; ++ else if (fvco < 3300000) ++ Icp = 2; ++ else if (fvco < 3700000) ++ Icp = 3; ++ else if (fvco < 4200000) ++ Icp = 5; ++ else if (fvco < 4800000) ++ Icp = 6; ++ else ++ Icp = 7; ++ ++ state->reg[0x02] |= 0x80; /* LNA IIP3 Mode */ ++ ++ state->reg[0x03] = (state->reg[0x03] & ~0x80) | (psel << 7); ++ state->reg[0x04] = (div & 0xFF); ++ state->reg[0x05] = (((div >> 8) & 0x01) | ((frac & 0x7F) << 1)) & 0xff; ++ state->reg[0x06] = ((frac >> 7) & 0xFF); ++ state->reg[0x07] = (state->reg[0x07] & ~0x07) | ((frac >> 15) & 0x07); ++ state->reg[0x07] = (state->reg[0x07] & ~0xE0) | (Icp << 5); ++ ++ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2); ++ /* Start cal vco,CF */ ++ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x0C; ++ write_regs(state, 2, 8); ++ ++ wait_for_call_done(state, 0x0C); ++ ++ usleep_range(10000, 12000); ++ ++ read_reg(state, 0x03, &tmp); ++ if (tmp & 0x10) { ++ state->reg[0x02] &= ~0x80; /* LNA NF Mode */ ++ write_regs(state, 2, 1); ++ } ++ read_reg(state, 0x08, &tmp); ++ ++ dump_regs(state); ++ return 0; ++} ++ ++static int set_params(struct dvb_frontend *fe) ++{ ++ struct stv *state = fe->tuner_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int status; ++ u32 freq, symb, cutoff; ++ ++ if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2) ++ return -EINVAL; ++ ++ freq = p->frequency * 1000; ++ symb = p->symbol_rate; ++ cutoff = 5000000 + MulDiv32(p->symbol_rate, 135, 200); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ set_lof(state, freq, cutoff); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return status; ++} ++ ++static int get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ return 0; ++} ++ ++static u32 AGC_Gain[] = { ++ 000, /* 0.0 */ ++ 000, /* 0.1 */ ++ 1000, /* 0.2 */ ++ 2000, /* 0.3 */ ++ 3000, /* 0.4 */ ++ 4000, /* 0.5 */ ++ 5000, /* 0.6 */ ++ 6000, /* 0.7 */ ++ 7000, /* 0.8 */ ++ 14000, /* 0.9 */ ++ 20000, /* 1.0 */ ++ 27000, /* 1.1 */ ++ 32000, /* 1.2 */ ++ 37000, /* 1.3 */ ++ 42000, /* 1.4 */ ++ 47000, /* 1.5 */ ++ 50000, /* 1.6 */ ++ 53000, /* 1.7 */ ++ 56000, /* 1.8 */ ++ 58000, /* 1.9 */ ++ 60000, /* 2.0 */ ++ 62000, /* 2.1 */ ++ 63000, /* 2.2 */ ++ 64000, /* 2.3 */ ++ 64500, /* 2.4 */ ++ 65000, /* 2.5 */ ++ 65500, /* 2.6 */ ++ 66000, /* 2.7 */ ++ 66500, /* 2.8 */ ++ 67000, /* 2.9 */ ++}; ++ ++static int get_rf_strength(struct dvb_frontend *fe, u16 *st) ++{ ++ *st = 0; ++#if 0 ++ struct stv *state = fe->tuner_priv; ++ s32 Gain; ++ u32 Index = RFAgc / 100; ++ if (Index >= (sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1)) ++ Gain = AGC_Gain[sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1]; ++ else ++ Gain = AGC_Gain[Index] + ++ ((AGC_Gain[Index+1] - AGC_Gain[Index]) * ++ (RFAgc % 100)) / 100; ++ *st = Gain; ++#endif ++ return 0; ++} ++ ++static int get_if(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ return 0; ++} ++ ++static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ return 0; ++} ++ ++static struct dvb_tuner_ops tuner_ops = { ++ .info = { ++ .name = "STV6111", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_step = 0 ++ }, ++ .init = init, ++ .sleep = sleep, ++ .set_params = set_params, ++ .release = release, ++ .get_frequency = get_frequency, ++ .get_if_frequency = get_if, ++ .get_bandwidth = get_bandwidth, ++ .get_rf_strength = get_rf_strength, ++ .set_bandwidth = set_bandwidth, ++}; ++ ++struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr) ++{ ++ struct stv *state; ++ int stat; ++ ++ state = kzalloc(sizeof(struct stv), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ state->adr = adr; ++ state->i2c = i2c; ++ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); ++ init_state(state); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ stat = attach_init(state); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ if (stat < 0) { ++ kfree(state); ++ return 0; ++ } ++ fe->tuner_priv = state; ++ return fe; ++} ++EXPORT_SYMBOL_GPL(stv6111_attach); ++ ++MODULE_DESCRIPTION("STV6111 driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Local variables: ++ * c-basic-offset: 8 ++ * End: ++ */ +diff --git a/drivers/media/dvb-frontends/stv6111.h b/drivers/media/dvb-frontends/stv6111.h +new file mode 100644 +index 0000000..31d200c +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv6111.h +@@ -0,0 +1,5 @@ ++#ifndef _STV6111_H_ ++#define _STV6111_H_ ++struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr); ++#endif +diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c +new file mode 100644 +index 0000000..7d99fd5 +--- /dev/null ++++ b/drivers/media/dvb-frontends/tda18212dd.c +@@ -0,0 +1,974 @@ ++/* ++ * tda18212: Driver for the TDA18212 tuner ++ * ++ * Copyright (C) 2011-2013 Digital Devices GmbH ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++#ifndef CHK_ERROR ++#define CHK_ERROR(s) if ((status = s) < 0) break ++#endif ++ ++#define MASTER_PSM_AGC1 0 ++#define MASTER_AGC1_6_15dB 1 ++ ++#define SLAVE_PSM_AGC1 1 ++#define SLAVE_AGC1_6_15dB 0 ++ ++/* 0 = 2 Vpp ... 2 = 1 Vpp, 7 = 0.5 Vpp */ ++#define IF_LEVEL_DVBC 2 ++#define IF_LEVEL_DVBT 2 ++ ++enum { ++ ID_1 = 0x00, ++ ID_2 = 0x01, ++ ID_3 = 0x02, ++ THERMO_1, ++ THERMO_2, ++ POWER_STATE_1, ++ POWER_STATE_2, ++ INPUT_POWER_LEVEL, ++ IRQ_STATUS, ++ IRQ_ENABLE, ++ IRQ_CLEAR, ++ IRQ_SET, ++ AGC1_1, ++ AGC2_1, ++ AGCK_1, ++ RF_AGC_1, ++ IR_MIXER_1 = 0x10, ++ AGC5_1, ++ IF_AGC, ++ IF_1, ++ REFERENCE, ++ IF_FREQUENCY_1, ++ RF_FREQUENCY_1, ++ RF_FREQUENCY_2, ++ RF_FREQUENCY_3, ++ MSM_1, ++ MSM_2, ++ PSM_1, ++ DCC_1, ++ FLO_MAX, ++ IR_CAL_1, ++ IR_CAL_2, ++ IR_CAL_3 = 0x20, ++ IR_CAL_4, ++ VSYNC_MGT, ++ IR_MIXER_2, ++ AGC1_2, ++ AGC5_2, ++ RF_CAL_1, ++ RF_CAL_2, ++ RF_CAL_3, ++ RF_CAL_4, ++ RF_CAL_5, ++ RF_CAL_6, ++ RF_FILTER_1, ++ RF_FILTER_2, ++ RF_FILTER_3, ++ RF_BAND_PASS_FILTER, ++ CP_CURRENT = 0x30, ++ AGC_DET_OUT = 0x31, ++ RF_AGC_GAIN_1 = 0x32, ++ RF_AGC_GAIN_2 = 0x33, ++ IF_AGC_GAIN = 0x34, ++ POWER_1 = 0x35, ++ POWER_2 = 0x36, ++ MISC_1, ++ RFCAL_LOG_1, ++ RFCAL_LOG_2, ++ RFCAL_LOG_3, ++ RFCAL_LOG_4, ++ RFCAL_LOG_5, ++ RFCAL_LOG_6, ++ RFCAL_LOG_7, ++ RFCAL_LOG_8, ++ RFCAL_LOG_9 = 0x40, ++ RFCAL_LOG_10 = 0x41, ++ RFCAL_LOG_11 = 0x42, ++ RFCAL_LOG_12 = 0x43, ++ REG_MAX, ++}; ++ ++enum HF_Standard { ++ HF_None = 0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio, ++ HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ, ++ HF_DVBT, HF_ATSC, HF_DVBC_6MHZ, HF_DVBC_7MHZ, ++ HF_DVBC_8MHZ, HF_DVBC ++}; ++ ++struct SStandardParams { ++ s32 m_IFFrequency; ++ u32 m_BandWidth; ++ u8 m_IF_1; /* FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3 */ ++ u8 m_IR_MIXER_2; /* 03 :6 HI_Pass:1 DC_Notch:1 */ ++ u8 m_AGC1_1; /* 0F :4 AGC1_Top:4 */ ++ u8 m_AGC2_1; /* 0F :4 AGC2_Top:4 */ ++ /*EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 */ ++ u8 m_RF_AGC_1_Low; ++ /*EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 */ ++ u8 m_RF_AGC_1_High; ++ u8 m_IR_MIXER_1; /* 0F :4 IR_mixer_Top:4 */ ++ u8 m_AGC5_1; /* 1F :3 AGC5_Ana AGC5_Top:4 */ ++ u8 m_AGCK_1; /* 0F :4 AGCK_Step:2 AGCK_Mode:2 */ ++ u8 m_PSM_1; /* 20 :2 PSM_StoB:1 :5 */ ++ bool m_AGC1_Freeze; ++ bool m_LTO_STO_immune; ++}; ++ ++#if 0 ++static struct SStandardParams ++m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = { ++ { 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_6MHZ */ ++ { 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_7MHZ */ ++ { 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_8MHZ */ ++ { 0000000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, /* HF_DVBT (Unused) */ ++ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, ++ 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, /* HF_ATSC */ ++ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_6MHZ */ ++ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, ++ /* HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) */ ++ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_8MHZ */ ++}; ++#else ++static struct SStandardParams ++m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = { ++ { 4000000, 6000000, 0x41, 0x03, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_6MHZ */ ++ { 4500000, 7000000, 0x42, 0x03, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_7MHZ */ ++ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x2B, ++ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_8MHZ */ ++ /* ------------------------------ */ ++ { 0000000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, /* HF_DVBT (Unused)*/ ++ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, ++ 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, /* HF_ATSC */ ++ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_6MHZ */ ++ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, ++ /* HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) */ ++ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, ++ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_8MHZ */ ++}; ++#endif ++ ++struct tda_state { ++ struct i2c_adapter *i2c; ++ u8 adr; ++ ++ enum HF_Standard m_Standard; ++ u32 m_Frequency; ++ u32 IF; ++ ++ bool m_isMaster; ++ bool m_bPowerMeasurement; ++ bool m_bLTEnable; ++ bool m_bEnableFreeze; ++ ++ u16 m_ID; ++ ++ s32 m_SettlingTime; ++ ++ u8 m_IFLevelDVBC; ++ u8 m_IFLevelDVBT; ++ u8 Regs[REG_MAX]; ++ u8 m_LastPowerLevel; ++}; ++ ++static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, ++ .buf = data, .len = len} }; ++ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ pr_err("tda18212dd: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ pr_err("tda18212: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int write_regs(struct tda_state *state, ++ u8 SubAddr, u8 *Regs, u16 nRegs) ++{ ++ u8 data[REG_MAX + 1]; ++ ++ data[0] = SubAddr; ++ memcpy(data + 1, Regs, nRegs); ++ return i2c_write(state->i2c, state->adr, data, nRegs + 1); ++} ++ ++static int write_reg(struct tda_state *state, u8 SubAddr, u8 Reg) ++{ ++ u8 msg[2] = {SubAddr, Reg}; ++ ++ return i2c_write(state->i2c, state->adr, msg, 2); ++} ++ ++static int Read(struct tda_state *state, u8 *Regs) ++{ ++ return i2c_readn(state->i2c, state->adr, Regs, REG_MAX); ++} ++ ++static int update_regs(struct tda_state *state, u8 RegFrom, u8 RegTo) ++{ ++ return write_regs(state, RegFrom, ++ &state->Regs[RegFrom], RegTo-RegFrom + 1); ++} ++ ++static int update_reg(struct tda_state *state, u8 Reg) ++{ ++ return write_reg(state, Reg, state->Regs[Reg]); ++} ++ ++ ++static int read_regs(struct tda_state *state, ++ u8 SubAddr, u8 *Regs, u16 nRegs) ++{ ++ return i2c_read(state->i2c, state->adr, ++ &SubAddr, 1, Regs, nRegs); ++} ++ ++static int read_reg(struct tda_state *state, ++ u8 SubAddr, u8 *Reg) ++{ ++ return i2c_read(state->i2c, state->adr, ++ &SubAddr, 1, Reg, 1); ++} ++ ++static int read_reg1(struct tda_state *state, u8 Reg) ++{ ++ return read_reg(state, Reg, &state->Regs[Reg]); ++} ++ ++static void init_state(struct tda_state *state) ++{ ++ u32 ulIFLevelDVBC = IF_LEVEL_DVBC; ++ u32 ulIFLevelDVBT = IF_LEVEL_DVBT; ++ u32 ulPowerMeasurement = 1; ++ u32 ulLTEnable = 1; ++ u32 ulEnableFreeze = 0; ++ ++ state->m_Frequency = 0; ++ state->m_isMaster = true; ++ state->m_ID = 0; ++ state->m_LastPowerLevel = 0xFF; ++ state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07); ++ state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07); ++ state->m_bPowerMeasurement = (ulPowerMeasurement != 0); ++ state->m_bLTEnable = (ulLTEnable != 0); ++ state->m_bEnableFreeze = (ulEnableFreeze != 0); ++} ++ ++static int StartCalibration(struct tda_state *state) ++{ ++ int status = 0; ++ do { ++ state->Regs[POWER_2] &= ~0x02; /* RSSI CK = 31.25 kHz */ ++ CHK_ERROR(update_reg(state, POWER_2)); ++ ++ /* AGC1 Do Step = 2 */ ++ state->Regs[AGC1_2] = (state->Regs[AGC1_2] & ~0x60) | 0x40; ++ CHK_ERROR(update_reg(state, AGC1_2)); /* AGC */ ++ ++ /* AGC2 Do Step = 1 */ ++ state->Regs[RF_FILTER_3] = ++ (state->Regs[RF_FILTER_3] & ~0xC0) | 0x40; ++ CHK_ERROR(update_reg(state, RF_FILTER_3)); ++ ++ /* AGCs Assym Up Step = 3 // Datasheet sets all bits to 1! */ ++ state->Regs[AGCK_1] |= 0xC0; ++ CHK_ERROR(update_reg(state, AGCK_1)); ++ ++ /* AGCs Assym Do Step = 2 */ ++ state->Regs[AGC5_1] = (state->Regs[AGC5_1] & ~0x60) | 0x40; ++ CHK_ERROR(update_reg(state, AGC5_1)); ++ ++ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ state->Regs[MSM_1] = 0x3B; /* Set Calibration */ ++ state->Regs[MSM_2] = 0x01; /* Start MSM */ ++ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); ++ state->Regs[MSM_2] = 0x00; ++ } while (0); ++ return status; ++} ++ ++static int FinishCalibration(struct tda_state *state) ++{ ++ int status = 0; ++ u8 RFCal_Log[12]; ++ ++ do { ++ u8 IRQ = 0; ++ int Timeout = 150; /* 1.5 s */ ++ while (true) { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if ((IRQ & 0x80) != 0) ++ break; ++ Timeout -= 1; ++ if (Timeout == 0) { ++ status = -1; ++ break; ++ } ++ usleep_range(10000, 12000); ++ } ++ CHK_ERROR(status); ++ ++ state->Regs[FLO_MAX] = 0x0A; ++ CHK_ERROR(update_reg(state, FLO_MAX)); ++ ++ state->Regs[AGC1_1] &= ~0xC0; ++ if (state->m_bLTEnable) ++ state->Regs[AGC1_1] |= 0x80; /* LTEnable */ ++ ++ state->Regs[AGC1_1] |= (state->m_isMaster ? ++ MASTER_AGC1_6_15dB : ++ SLAVE_AGC1_6_15dB) << 6; ++ CHK_ERROR(update_reg(state, AGC1_1)); ++ ++ state->Regs[PSM_1] &= ~0xC0; ++ state->Regs[PSM_1] |= (state->m_isMaster ? ++ MASTER_PSM_AGC1 : SLAVE_PSM_AGC1) << 6; ++ CHK_ERROR(update_reg(state, PSM_1)); ++ ++ state->Regs[REFERENCE] |= 0x03; /* XTOUT = 3 */ ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ CHK_ERROR(read_regs(state, RFCAL_LOG_1, ++ RFCal_Log, sizeof(RFCal_Log))); ++ } while (0); ++ return status; ++} ++ ++static int PowerOn(struct tda_state *state) ++{ ++ state->Regs[POWER_STATE_2] &= ~0x0F; ++ update_reg(state, POWER_STATE_2); ++ /* Digital clock source = Sigma Delta */ ++ state->Regs[REFERENCE] |= 0x40; ++ update_reg(state, REFERENCE); ++ return 0; ++} ++ ++static int Standby(struct tda_state *state) ++{ ++ int status = 0; ++ ++ do { ++ /* Digital clock source = Quarz */ ++ state->Regs[REFERENCE] &= ~0x40; ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ state->Regs[POWER_STATE_2] &= ~0x0F; ++ state->Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E; ++ CHK_ERROR(update_reg(state, POWER_STATE_2)); ++ } while (0); ++ return status; ++} ++ ++static int attach_init(struct tda_state *state) ++{ ++ int stat = 0; ++ u8 Id[2]; ++ u8 PowerState = 0x00; ++ ++ state->m_Standard = HF_None; ++ ++ /* first read after cold reset sometimes fails on some cards, ++ try twice */ ++ stat = read_regs(state, ID_1, Id, sizeof(Id)); ++ stat = read_regs(state, ID_1, Id, sizeof(Id)); ++ if (stat < 0) ++ return -1; ++ ++ state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1]; ++ state->m_isMaster = ((Id[0] & 0x80) != 0); ++ if (!state->m_isMaster) ++ state->m_bLTEnable = false; ++ ++ pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID, ++ state->m_isMaster ? "master" : "slave"); ++ ++ if (state->m_ID != 18212) ++ return -1; ++ ++ stat = read_reg(state, POWER_STATE_1 , &PowerState); ++ if (stat < 0) ++ return stat; ++ ++ pr_info("tda18212dd: PowerState %02x\n", PowerState); ++ ++ if (state->m_isMaster) { ++ if (PowerState & 0x02) { ++ /* msleep for XTAL Calibration ++ (on a PC this should be long done) */ ++ u8 IRQStatus = 0; ++ int Timeout = 10; ++ ++ while (Timeout > 0) { ++ read_reg(state, IRQ_STATUS, &IRQStatus); ++ if (IRQStatus & 0x20) ++ break; ++ Timeout -= 1; ++ usleep_range(10000, 12000); ++ } ++ if ((IRQStatus & 0x20) == 0) ++ stat = -ETIMEDOUT; ++ } ++ } else { ++ write_reg(state, FLO_MAX, 0x00); ++ write_reg(state, CP_CURRENT, 0x68); ++ } ++ Read(state, state->Regs); ++ ++ PowerOn(state); ++ StartCalibration(state); ++ FinishCalibration(state); ++ Standby(state); ++ ++ { ++ u8 RFCal_Log[12]; ++ ++ read_regs(state, RFCAL_LOG_1, RFCal_Log, sizeof(RFCal_Log)); ++ pr_info("RFCal Log: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ RFCal_Log[0], RFCal_Log[1], ++ RFCal_Log[2], RFCal_Log[3], ++ RFCal_Log[4], RFCal_Log[5], ++ RFCal_Log[6], RFCal_Log[7], ++ RFCal_Log[8], RFCal_Log[9], ++ RFCal_Log[10], RFCal_Log[11]); ++ } ++ return stat; ++} ++ ++static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) ++{ ++ int status = 0; ++ ++ do { ++ u8 IRQ = 0; ++ int Timeout = 70; /* 700 ms */ ++ ++ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ state->Regs[MSM_1] = 0x80; /* power measurement */ ++ state->Regs[MSM_2] = 0x01; /* Start MSM */ ++ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); ++ state->Regs[MSM_2] = 0x00; ++ ++ while (true) { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if ((IRQ & 0x80) != 0) ++ break; ++ Timeout -= 1; ++ if (Timeout == 0) { ++ status = -1; ++ break; ++ } ++ usleep_range(10000, 12000); ++ } ++ CHK_ERROR(status); ++ ++ CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL)); ++ *pPowerLevel = state->Regs[INPUT_POWER_LEVEL] & 0x7F; ++ ++ if (*pPowerLevel > 110) ++ *pPowerLevel = 110; ++ } while (0); ++ /* pr_info("PL %d\n", *pPowerLevel); */ ++ return status; ++} ++ ++static int SetFrequency(struct tda_state *state, u32 Frequency, ++ enum HF_Standard Standard) ++{ ++ int status = 0; ++ struct SStandardParams *StandardParams; ++ u32 f = Frequency / 1000; ++ u8 IRQ = 0; ++ int Timeout = 25; /* 250 ms */ ++ u32 fRatio = Frequency / 16000000; ++ u32 fDelta = Frequency - fRatio * 16000000; ++ ++ if (Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ) ++ return -EINVAL; ++ StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ]; ++ ++ if (StandardParams->m_IFFrequency == 0) ++ return -EINVAL; ++ state->m_Standard = HF_None; ++ state->m_Frequency = 0; ++ ++ do { ++ /* IF Level */ ++ state->Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? ++ state->m_IFLevelDVBC : state->m_IFLevelDVBT; ++ CHK_ERROR(update_reg(state, IF_AGC)); ++ ++ /* Standard setup */ ++ state->Regs[IF_1] = StandardParams->m_IF_1; ++ CHK_ERROR(update_reg(state, IF_1)); ++ ++ state->Regs[IR_MIXER_2] = (state->Regs[IR_MIXER_2] & ~0x03) | ++ StandardParams->m_IR_MIXER_2; ++ CHK_ERROR(update_reg(state, IR_MIXER_2)); ++ ++ state->Regs[AGC1_1] = (state->Regs[AGC1_1] & ~0x0F) | ++ StandardParams->m_AGC1_1; ++ CHK_ERROR(update_reg(state, AGC1_1)); ++ ++ state->Regs[AGC2_1] = (state->Regs[AGC2_1] & ~0x0F) | ++ StandardParams->m_AGC2_1; ++ CHK_ERROR(update_reg(state, AGC2_1)); ++ ++ state->Regs[RF_AGC_1] &= ~0xEF; ++ if (Frequency < 291000000) ++ state->Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low; ++ else ++ state->Regs[RF_AGC_1] |= ++ StandardParams->m_RF_AGC_1_High; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ ++ state->Regs[IR_MIXER_1] = ++ (state->Regs[IR_MIXER_1] & ~0x0F) | ++ StandardParams->m_IR_MIXER_1; ++ CHK_ERROR(update_reg(state, IR_MIXER_1)); ++ ++ state->Regs[AGC5_1] = (state->Regs[AGC5_1] & ~0x1F) | ++ StandardParams->m_AGC5_1; ++ CHK_ERROR(update_reg(state, AGC5_1)); ++ ++ state->Regs[AGCK_1] = (state->Regs[AGCK_1] & ~0x0F) | ++ StandardParams->m_AGCK_1; ++ CHK_ERROR(update_reg(state, AGCK_1)); ++ ++ state->Regs[PSM_1] = (state->Regs[PSM_1] & ~0x20) | ++ StandardParams->m_PSM_1; ++ CHK_ERROR(update_reg(state, PSM_1)); ++ ++ state->Regs[IF_FREQUENCY_1] = (StandardParams->m_IFFrequency / ++ 50000); ++ CHK_ERROR(update_reg(state, IF_FREQUENCY_1)); ++ ++ if (state->m_isMaster && StandardParams->m_LTO_STO_immune) { ++ u8 tmp; ++ u8 RF_Filter_Gain; ++ ++ CHK_ERROR(read_reg(state, RF_AGC_GAIN_1, &tmp)); ++ RF_Filter_Gain = (tmp & 0x30) >> 4; ++ ++ state->Regs[RF_FILTER_1] = ++ (state->Regs[RF_FILTER_1] & ~0x0C) | ++ (RF_Filter_Gain << 2); ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ ++ state->Regs[RF_FILTER_1] |= 0x10; /* Force */ ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ ++ while (RF_Filter_Gain != 0) { ++ RF_Filter_Gain -= 1; ++ state->Regs[RF_FILTER_1] = ++ (state->Regs[RF_FILTER_1] & ~0x0C) | ++ (RF_Filter_Gain << 2); ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ usleep_range(10000, 12000); ++ } ++ CHK_ERROR(status); ++ ++ state->Regs[RF_AGC_1] |= 0x08; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ } ++ ++ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ CHK_ERROR(PowerOn(state)); ++ ++ state->Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF); ++ state->Regs[RF_FREQUENCY_2] = ((f >> 8) & 0xFF); ++ state->Regs[RF_FREQUENCY_3] = (f & 0xFF); ++ CHK_ERROR(update_regs(state, RF_FREQUENCY_1, RF_FREQUENCY_3)); ++ ++ state->Regs[MSM_1] = 0x41; /* Tune */ ++ state->Regs[MSM_2] = 0x01; /* Start MSM */ ++ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); ++ state->Regs[MSM_2] = 0x00; ++ ++ while (true) { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if ((IRQ & 0x80) != 0) ++ break; ++ Timeout -= 1; ++ if (Timeout == 0) { ++ status = -1; ++ break; ++ } ++ usleep_range(10000, 12000); ++ } ++ CHK_ERROR(status); ++ ++ if (state->m_isMaster && StandardParams->m_LTO_STO_immune) { ++ state->Regs[RF_AGC_1] &= ~0x08; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ ++ msleep(50); ++ ++ state->Regs[RF_FILTER_1] &= ~0x10; /* remove force */ ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ } ++ ++ /* Spur reduction */ ++ ++ if (Frequency < 72000000) ++ state->Regs[REFERENCE] |= 0x40; /* Set digital clock */ ++ else if (Frequency < 104000000) ++ state->Regs[REFERENCE] &= ~0x40; /*Clear digital clock*/ ++ else if (Frequency < 120000000) ++ state->Regs[REFERENCE] |= 0x40; /* Set digital clock */ ++ else { ++ if (fDelta <= 8000000) { ++ /* Clear or set digital clock */ ++ if (fRatio & 1) ++ state->Regs[REFERENCE] &= ~0x40; ++ else ++ state->Regs[REFERENCE] |= 0x40; ++ } else { ++ /* Set or clear digital clock */ ++ if (fRatio & 1) ++ state->Regs[REFERENCE] |= 0x40; ++ else ++ state->Regs[REFERENCE] &= ~0x40; ++ } ++ ++ } ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ if (StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze) { ++ u8 tmp; ++ int AGC1GainMin = 0; ++ int nSteps = 10; ++ int Step = 0; ++ ++ CHK_ERROR(read_reg(state, AGC1_2, &tmp)); ++ if ((tmp & 0x80) == 0) { ++ state->Regs[AGC1_2] |= 0x80; /* Loop off */ ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ state->Regs[AGC1_2] |= 0x10; /* Force gain */ ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ /* Adapt */ ++ if (state->Regs[AGC1_1] & 0x40) { /* AGC1_6_15dB set */ ++ AGC1GainMin = 6; ++ nSteps = 4; ++ } ++ while (Step < nSteps) { ++ int Down = 0; ++ int Up = 0, i; ++ u8 AGC1_Gain; ++ ++ Step = Step + 1; ++ ++ for (i = 0; i < 40; i += 1) { ++ CHK_ERROR(read_reg(state, AGC_DET_OUT, ++ &tmp)); ++ Up += (tmp & 0x02) ? 1 : -4; ++ Down += (tmp & 0x01) ? 14 : -1; ++ usleep_range(1000, 2000); ++ } ++ CHK_ERROR(status); ++ AGC1_Gain = (state->Regs[AGC1_2] & 0x0F); ++ if (Up >= 15 && AGC1_Gain != 9) { ++ state->Regs[AGC1_2] = ++ (state->Regs[AGC1_2] & ~0x0F) | ++ (AGC1_Gain + 1); ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } else if (Down >= 10 && ++ AGC1_Gain != AGC1GainMin) { ++ state->Regs[AGC1_2] = ++ (state->Regs[AGC1_2] & ~0x0F) | ++ (AGC1_Gain - 1); ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } else ++ Step = nSteps; ++ } ++ } else { ++ state->Regs[AGC1_2] &= ~0x10; /* unforce gain */ ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ state->Regs[AGC1_2] &= ~0x80; /* Loop on */ ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ ++ state->m_Standard = Standard; ++ state->m_Frequency = Frequency; ++ ++ if (state->m_bPowerMeasurement) ++ PowerMeasurement(state, &state->m_LastPowerLevel); ++ } while (0); ++ ++ return status; ++} ++ ++static int sleep(struct dvb_frontend *fe) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ Standby(state); ++ return 0; ++} ++ ++static int init(struct dvb_frontend *fe) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ return 0; ++} ++ ++static int release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++ ++#ifndef USE_API3 ++static int set_params(struct dvb_frontend *fe) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int status = 0; ++ int Standard; ++ u32 bw; ++ ++ bw = (p->bandwidth_hz + 999999) / 1000000; ++ state->m_Frequency = p->frequency; ++ /*pr_info("tuner bw=%u freq=%u\n", bw, state->m_Frequency);*/ ++ if (p->delivery_system == SYS_DVBT || ++ p->delivery_system == SYS_DVBT2 || ++ p->delivery_system == SYS_ISDBT) { ++ switch (bw) { ++ case 6: ++ Standard = HF_DVBT_6MHZ; ++ break; ++ case 7: ++ Standard = HF_DVBT_7MHZ; ++ break; ++ default: ++ case 8: ++ Standard = HF_DVBT_8MHZ; ++ break; ++ } ++ } else if (p->delivery_system == SYS_DVBC_ANNEX_A) { ++ switch (bw) { ++ case 6: ++ Standard = HF_DVBC_6MHZ; ++ break; ++ case 7: ++ Standard = HF_DVBC_7MHZ; ++ break; ++ default: ++ case 8: ++ Standard = HF_DVBC_8MHZ; ++ break; ++ } ++ } else ++ return -EINVAL; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ SetFrequency(state, state->m_Frequency, Standard); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return status; ++} ++#else ++static int set_params(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *params) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ int status = 0; ++ int Standard; ++ ++ state->m_Frequency = params->frequency; ++ ++ if (fe->ops.info.type == FE_OFDM) ++ switch (params->u.ofdm.bandwidth) { ++ case BANDWIDTH_6_MHZ: ++ Standard = HF_DVBT_6MHZ; ++ break; ++ case BANDWIDTH_7_MHZ: ++ Standard = HF_DVBT_7MHZ; ++ break; ++ default: ++ case BANDWIDTH_8_MHZ: ++ Standard = HF_DVBT_8MHZ; ++ break; ++ } ++ else if (fe->ops.info.type == FE_QAM) { ++ Standard = HF_DVBC_8MHZ; ++ } else ++ return -EINVAL; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ SetFrequency(state, state->m_Frequency, Standard); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return status; ++} ++#endif ++ ++static int get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ *frequency = state->IF; ++ return 0; ++} ++ ++static int get_rf_strength(struct dvb_frontend *fe, u16 *st) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ *st = state->m_LastPowerLevel; ++ return 0; ++} ++ ++static int get_if(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ state->IF = 0; ++ if (state->m_Standard < HF_DVBT_6MHZ || ++ state->m_Standard > HF_DVBC_8MHZ) ++ return 0; ++ state->IF = m_StandardTable[state->m_Standard - ++ HF_DVBT_6MHZ].m_IFFrequency; ++ *frequency = state->IF; ++ return 0; ++} ++ ++static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ /* struct tda_state *state = fe->tuner_priv; */ ++ /* *bandwidth = priv->bandwidth; */ ++ return 0; ++} ++ ++ ++static struct dvb_tuner_ops tuner_ops = { ++ .info = { ++ .name = "NXP TDA18212", ++ .frequency_min = 47125000, ++ .frequency_max = 865000000, ++ .frequency_step = 62500 ++ }, ++ .init = init, ++ .sleep = sleep, ++ .set_params = set_params, ++ .release = release, ++ .get_frequency = get_frequency, ++ .get_if_frequency = get_if, ++ .get_bandwidth = get_bandwidth, ++ .get_rf_strength = get_rf_strength, ++}; ++ ++struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr) ++{ ++ struct tda_state *state; ++ int stat; ++ ++ state = kzalloc(sizeof(struct tda_state), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ state->adr = adr; ++ state->i2c = i2c; ++ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); ++ init_state(state); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ stat = attach_init(state); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ if (stat < 0) { ++ kfree(state); ++ return 0; ++ } ++ fe->tuner_priv = state; ++ return fe; ++} ++EXPORT_SYMBOL_GPL(tda18212dd_attach); ++ ++MODULE_DESCRIPTION("TDA18212 driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Local variables: ++ * c-basic-offset: 8 ++ * End: ++ */ +diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h +new file mode 100644 +index 0000000..687fab4a +--- /dev/null ++++ b/drivers/media/dvb-frontends/tda18212dd.h +@@ -0,0 +1,5 @@ ++#ifndef _TDA18212DD_H_ ++#define _TDA18212DD_H_ ++struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr); ++#endif +diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c +index de0a1c1..ad7c72e 100644 +--- a/drivers/media/dvb-frontends/tda18271c2dd.c ++++ b/drivers/media/dvb-frontends/tda18271c2dd.c +@@ -32,10 +32,6 @@ + #include + + #include "dvb_frontend.h" +-#include "tda18271c2dd.h" +- +-/* Max transfer size done by I2C transfer functions */ +-#define MAX_XFER_SIZE 64 + + struct SStandardParam { + s32 m_IFFrequency; +@@ -142,18 +138,11 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) + static int WriteRegs(struct tda_state *state, + u8 SubAddr, u8 *Regs, u16 nRegs) + { +- u8 data[MAX_XFER_SIZE]; +- +- if (1 + nRegs > sizeof(data)) { +- printk(KERN_WARNING +- "%s: i2c wr: len=%d is too big!\n", +- KBUILD_MODNAME, nRegs); +- return -EINVAL; +- } ++ u8 data[nRegs+1]; + + data[0] = SubAddr; + memcpy(data + 1, Regs, nRegs); +- return i2c_write(state->i2c, state->adr, data, nRegs + 1); ++ return i2c_write(state->i2c, state->adr, data, nRegs+1); + } + + static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg) +@@ -1030,7 +1019,7 @@ static int ChannelConfiguration(struct tda_state *state, + state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; + + if ((Standard == HF_FM_Radio) && state->m_bFMInput) +- state->m_Regs[EP4] |= 0x80; ++ state->m_Regs[EP4] |= 80; + + state->m_Regs[MPD] &= ~0x80; + if (Standard > HF_AnalogMax) +diff --git a/drivers/media/dvb-frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h +index 7ebd8ea..31f7926 100644 +--- a/drivers/media/dvb-frontends/tda18271c2dd.h ++++ b/drivers/media/dvb-frontends/tda18271c2dd.h +@@ -1,9 +1,7 @@ + #ifndef _TDA18271C2DD_H_ + #define _TDA18271C2DD_H_ +- +-#include +- +-#if IS_REACHABLE(CONFIG_DVB_TDA18271C2DD) ++#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \ ++ && defined(MODULE)) + struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 adr); + #else +diff --git a/drivers/media/dvb-frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h +index f3bca5c..b87661b 100644 +--- a/drivers/media/dvb-frontends/tda18271c2dd_maps.h ++++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h +@@ -5,7 +5,7 @@ enum HF_S { + HF_DVBC_8MHZ, HF_DVBC + }; + +-static struct SStandardParam m_StandardTable[] = { ++struct SStandardParam m_StandardTable[] = { + { 0, 0, 0x00, 0x00 }, /* HF_None */ + { 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */ + { 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */ +@@ -27,7 +27,7 @@ static struct SStandardParam m_StandardTable[] = { + { 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */ + }; + +-static struct SMap m_BP_Filter_Map[] = { ++struct SMap m_BP_Filter_Map[] = { + { 62000000, 0x00 }, + { 84000000, 0x01 }, + { 100000000, 0x02 }, +@@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = { + { 865000000, 489500000, 697500000, 842000000}, + }; + +-static u8 m_Thermometer_Map_1[16] = { ++u8 m_Thermometer_Map_1[16] = { + 60, 62, 66, 64, + 74, 72, 68, 70, + 90, 88, 84, 86, + 76, 78, 82, 80, + }; + +-static u8 m_Thermometer_Map_2[16] = { ++u8 m_Thermometer_Map_2[16] = { + 92, 94, 98, 96, + 106, 104, 100, 102, + 122, 120, 116, 118, +diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig +index 44e5dc1..d283008 100644 +--- a/drivers/media/pci/ddbridge/Kconfig ++++ b/drivers/media/pci/ddbridge/Kconfig +@@ -1,18 +1,23 @@ + config DVB_DDBRIDGE + tristate "Digital Devices bridge support" + depends on DVB_CORE && PCI && I2C ++ select DVB_CXD2099 + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + Support for cards with the Digital Devices PCI express bridge: + - Octopus PCIe Bridge + - Octopus mini PCIe Bridge + - Octopus LE +- - DuoFlex S2 Octopus +- - DuoFlex CT Octopus +- - cineS2(v6) ++ - DuoFlex S2 ++ - DuoFlex CT ++ - cineS2(v6.x) ++ - cineCT(v6.x, v7) + + Say Y if you own such a card and want to use it. +diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile +index 7446c8b..2610161 100644 +--- a/drivers/media/pci/ddbridge/Makefile ++++ b/drivers/media/pci/ddbridge/Makefile +@@ -2,8 +2,6 @@ + # Makefile for the ddbridge device driver + # + +-ddbridge-objs := ddbridge-core.o +- + obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o + + ccflags-y += -Idrivers/media/dvb-core/ +diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c +index 9e3492e..c2fc010 100644 +--- a/drivers/media/pci/ddbridge/ddbridge-core.c ++++ b/drivers/media/pci/ddbridge/ddbridge-core.c +@@ -1,7 +1,8 @@ + /* +- * ddbridge.c: Digital Devices PCIe bridge driver ++ * ddbridge-core.c: Digital Devices bridge core functions + * +- * Copyright (C) 2010-2011 Digital Devices GmbH ++ * Copyright (C) 2010-2013 Digital Devices GmbH ++ * Ralph Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +@@ -21,268 +22,245 @@ + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "ddbridge.h" +- +-#include "ddbridge-regs.h" +- +-#include "tda18271c2dd.h" +-#include "stv6110x.h" +-#include "stv090x.h" +-#include "lnbh24.h" +-#include "drxk.h" ++DEFINE_MUTEX(redirect_lock); ++ ++static int ci_bitrate = 72000; ++module_param(ci_bitrate, int, 0444); ++MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI."); ++ ++static int ts_loop = -1; ++module_param(ts_loop, int, 0444); ++MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop"); ++ ++static int vlan; ++module_param(vlan, int, 0444); ++MODULE_PARM_DESC(vlan, "VLAN and QoS IDs enabled"); ++ ++static int tt; ++module_param(tt, int, 0444); ++MODULE_PARM_DESC(tt, ""); ++ ++#define DDB_MAX_ADAPTER 32 ++static struct ddb *ddbs[DDB_MAX_ADAPTER]; + + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +-/* MSI had problems with lost interrupts, fixed but needs testing */ +-#undef CONFIG_PCI_MSI ++#include "ddbridge-mod.c" ++#include "ddbridge-i2c.c" ++#include "ddbridge-ns.c" + +-/******************************************************************************/ + +-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) ++static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) + { +- struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, +- .buf = val, .len = 1 } }; +- return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; +-} ++ u32 i, base; ++ u64 mem; + +-static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) +-{ +- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, +- .buf = ®, .len = 1 }, +- {.addr = adr, .flags = I2C_M_RD, +- .buf = val, .len = 1 } }; +- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++ if (!dma) ++ return; ++ base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100; ++ for (i = 0; i < dma->num; i++) { ++ mem = dma->pbuf[i]; ++ ddbwritel(dev, mem & 0xffffffff, base + i * 8); ++ ddbwritel(dev, mem >> 32, base + i * 8 + 4); ++ } ++ dma->bufreg = (dma->div << 16) | ++ ((dma->num & 0x1f) << 11) | ++ ((dma->size >> 7) & 0x7ff); + } + +-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, +- u16 reg, u8 *val) ++static void ddb_set_dma_tables(struct ddb *dev) + { +- u8 msg[2] = {reg>>8, reg&0xff}; +- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, +- .buf = msg, .len = 2}, +- {.addr = adr, .flags = I2C_M_RD, +- .buf = val, .len = 1} }; +- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++ u32 i; ++ ++ for (i = 0; i < dev->info->port_num * 2; i++) ++ ddb_set_dma_table(dev, dev->input[i].dma); ++ for (i = 0; i < dev->info->port_num; i++) ++ ddb_set_dma_table(dev, dev->output[i].dma); + } + +-static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static void ddb_redirect_dma(struct ddb *dev, ++ struct ddb_dma *sdma, ++ struct ddb_dma *ddma) + { +- struct ddb *dev = i2c->dev; +- int stat; +- u32 val; ++ u32 i, base; ++ u64 mem; + +- i2c->done = 0; +- ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); +- stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); +- if (stat <= 0) { +- printk(KERN_ERR "I2C timeout\n"); +- { /* MSI debugging*/ +- u32 istat = ddbreadl(INTERRUPT_STATUS); +- printk(KERN_ERR "IRS %08x\n", istat); +- ddbwritel(istat, INTERRUPT_ACK); +- } +- return -EIO; ++ sdma->bufreg = ddma->bufreg; ++ base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; ++ for (i = 0; i < ddma->num; i++) { ++ mem = ddma->pbuf[i]; ++ ddbwritel(dev, mem & 0xffffffff, base + i * 8); ++ ddbwritel(dev, mem >> 32, base + i * 8 + 4); + } +- val = ddbreadl(i2c->regs+I2C_COMMAND); +- if (val & 0x70000) +- return -EIO; +- return 0; + } + +-static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, +- struct i2c_msg msg[], int num) ++static int ddb_unredirect(struct ddb_port *port) + { +- struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); +- struct ddb *dev = i2c->dev; +- u8 addr = 0; +- +- if (num) +- addr = msg[0].addr; ++ struct ddb_input *oredi, *iredi = 0; ++ struct ddb_output *iredo = 0; + +- if (num == 2 && msg[1].flags & I2C_M_RD && +- !(msg[0].flags & I2C_M_RD)) { +- memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, +- msg[0].buf, msg[0].len); +- ddbwritel(msg[0].len|(msg[1].len << 16), +- i2c->regs+I2C_TASKLENGTH); +- if (!ddb_i2c_cmd(i2c, addr, 1)) { +- memcpy_fromio(msg[1].buf, +- dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, +- msg[1].len); +- return num; +- } +- } +- +- if (num == 1 && !(msg[0].flags & I2C_M_RD)) { +- ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); +- ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); +- if (!ddb_i2c_cmd(i2c, addr, 2)) +- return num; ++ /*pr_info("unredirect %d.%d\n", port->dev->nr, port->nr);*/ ++ mutex_lock(&redirect_lock); ++ if (port->output->dma->running) { ++ mutex_unlock(&redirect_lock); ++ return -EBUSY; + } +- if (num == 1 && (msg[0].flags & I2C_M_RD)) { +- ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); +- if (!ddb_i2c_cmd(i2c, addr, 3)) { +- ddbcpyfrom(msg[0].buf, +- I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); +- return num; ++ oredi = port->output->redi; ++ if (!oredi) ++ goto done; ++ if (port->input[0]) { ++ iredi = port->input[0]->redi; ++ iredo = port->input[0]->redo; ++ ++ if (iredo) { ++ iredo->port->output->redi = oredi; ++ if (iredo->port->input[0]) { ++ iredo->port->input[0]->redi = iredi; ++ ddb_redirect_dma(oredi->port->dev, ++ oredi->dma, iredo->dma); ++ } ++ port->input[0]->redo = 0; ++ ddb_set_dma_table(port->dev, port->input[0]->dma); + } ++ oredi->redi = iredi; ++ port->input[0]->redi = 0; + } +- return -EIO; +-} ++ oredi->redo = 0; ++ port->output->redi = 0; + ++ ddb_set_dma_table(oredi->port->dev, oredi->dma); ++done: ++ mutex_unlock(&redirect_lock); ++ return 0; ++} + +-static u32 ddb_i2c_functionality(struct i2c_adapter *adap) ++static int ddb_redirect(u32 i, u32 p) + { +- return I2C_FUNC_SMBUS_EMUL; +-} ++ struct ddb *idev = ddbs[(i >> 4) & 0x1f]; ++ struct ddb_input *input, *input2; ++ struct ddb *pdev = ddbs[(p >> 4) & 0x1f]; ++ struct ddb_port *port; + +-static struct i2c_algorithm ddb_i2c_algo = { +- .master_xfer = ddb_i2c_master_xfer, +- .functionality = ddb_i2c_functionality, +-}; ++ if (!idev->has_dma || !pdev->has_dma) ++ return -EINVAL; ++ if (!idev || !pdev) ++ return -EINVAL; + +-static void ddb_i2c_release(struct ddb *dev) +-{ +- int i; +- struct ddb_i2c *i2c; +- struct i2c_adapter *adap; ++ port = &pdev->port[p & 0x0f]; ++ if (!port->output) ++ return -EINVAL; ++ if (ddb_unredirect(port)) ++ return -EBUSY; + +- for (i = 0; i < dev->info->port_num; i++) { +- i2c = &dev->i2c[i]; +- adap = &i2c->adap; +- i2c_del_adapter(adap); +- } +-} ++ if (i == 8) ++ return 0; + +-static int ddb_i2c_init(struct ddb *dev) +-{ +- int i, j, stat = 0; +- struct ddb_i2c *i2c; +- struct i2c_adapter *adap; ++ input = &idev->input[i & 7]; ++ if (!input) ++ return -EINVAL; + +- for (i = 0; i < dev->info->port_num; i++) { +- i2c = &dev->i2c[i]; +- i2c->dev = dev; +- i2c->nr = i; +- i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); +- i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); +- i2c->regs = 0x80 + i * 0x20; +- ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING); +- ddbwritel((i2c->rbuf << 16) | i2c->wbuf, +- i2c->regs + I2C_TASKADDRESS); +- init_waitqueue_head(&i2c->wq); +- +- adap = &i2c->adap; +- i2c_set_adapdata(adap, i2c); +-#ifdef I2C_ADAP_CLASS_TV_DIGITAL +- adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; +-#else +-#ifdef I2C_CLASS_TV_ANALOG +- adap->class = I2C_CLASS_TV_ANALOG; +-#endif +-#endif +- strcpy(adap->name, "ddbridge"); +- adap->algo = &ddb_i2c_algo; +- adap->algo_data = (void *)i2c; +- adap->dev.parent = &dev->pdev->dev; +- stat = i2c_add_adapter(adap); +- if (stat) +- break; ++ mutex_lock(&redirect_lock); ++ if (port->output->dma->running || input->dma->running) { ++ mutex_unlock(&redirect_lock); ++ return -EBUSY; + } +- if (stat) +- for (j = 0; j < i; j++) { +- i2c = &dev->i2c[j]; +- adap = &i2c->adap; +- i2c_del_adapter(adap); +- } +- return stat; +-} ++ input2 = port->input[0]; ++ if (input2) { ++ if (input->redi) { ++ input2->redi = input->redi; ++ input->redi = 0; ++ } else ++ input2->redi = input; ++ } ++ input->redo = port->output; ++ port->output->redi = input; + ++ ddb_redirect_dma(input->port->dev, input->dma, port->output->dma); ++ mutex_unlock(&redirect_lock); ++ return 0; ++} + +-/******************************************************************************/ +-/******************************************************************************/ +-/******************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ + +-#if 0 +-static void set_table(struct ddb *dev, u32 off, +- dma_addr_t *pbuf, u32 num) ++#ifdef DDB_ALT_DMA ++static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) + { +- u32 i, base; +- u64 mem; ++ int i; + +- base = DMA_BASE_ADDRESS_TABLE + off; +- for (i = 0; i < num; i++) { +- mem = pbuf[i]; +- ddbwritel(mem & 0xffffffff, base + i * 8); +- ddbwritel(mem >> 32, base + i * 8 + 4); ++ if (!dma) ++ return; ++ for (i = 0; i < dma->num; i++) { ++ if (dma->vbuf[i]) { ++ dma_unmap_single(&pdev->dev, dma->pbuf[i], ++ dma->size, ++ dir ? DMA_TO_DEVICE : ++ DMA_FROM_DEVICE); ++ kfree(dma->vbuf[i]); ++ dma->vbuf[i] = 0; ++ } + } + } +-#endif + +-static void ddb_address_table(struct ddb *dev) ++static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) + { +- u32 i, j, base; +- u64 mem; +- dma_addr_t *pbuf; ++ int i; + +- for (i = 0; i < dev->info->port_num * 2; i++) { +- base = DMA_BASE_ADDRESS_TABLE + i * 0x100; +- pbuf = dev->input[i].pbuf; +- for (j = 0; j < dev->input[i].dma_buf_num; j++) { +- mem = pbuf[j]; +- ddbwritel(mem & 0xffffffff, base + j * 8); +- ddbwritel(mem >> 32, base + j * 8 + 4); +- } +- } +- for (i = 0; i < dev->info->port_num; i++) { +- base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100; +- pbuf = dev->output[i].pbuf; +- for (j = 0; j < dev->output[i].dma_buf_num; j++) { +- mem = pbuf[j]; +- ddbwritel(mem & 0xffffffff, base + j * 8); +- ddbwritel(mem >> 32, base + j * 8 + 4); ++ if (!dma) ++ return 0; ++ for (i = 0; i < dma->num; i++) { ++ dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT); ++ if (!dma->vbuf[i]) ++ return -ENOMEM; ++ dma->pbuf[i] = dma_map_single(&pdev->dev, dma->vbuf[i], ++ dma->size, ++ dir ? DMA_TO_DEVICE : ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(&pdev->dev, dma->pbuf[i])) { ++ kfree(dma->vbuf[i]); ++ return -ENOMEM; + } + } ++ return 0; + } ++#else + +-static void io_free(struct pci_dev *pdev, u8 **vbuf, +- dma_addr_t *pbuf, u32 size, int num) ++static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) + { + int i; + +- for (i = 0; i < num; i++) { +- if (vbuf[i]) { +- pci_free_consistent(pdev, size, vbuf[i], pbuf[i]); +- vbuf[i] = NULL; ++ if (!dma) ++ return; ++ for (i = 0; i < dma->num; i++) { ++ if (dma->vbuf[i]) { ++ pci_free_consistent(pdev, dma->size, ++ dma->vbuf[i], dma->pbuf[i]); ++ dma->vbuf[i] = 0; + } + } + } + +-static int io_alloc(struct pci_dev *pdev, u8 **vbuf, +- dma_addr_t *pbuf, u32 size, int num) ++static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) + { + int i; + +- for (i = 0; i < num; i++) { +- vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]); +- if (!vbuf[i]) ++ if (!dma) ++ return 0; ++ for (i = 0; i < dma->num; i++) { ++ dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size, ++ &dma->pbuf[i]); ++ if (!dma->vbuf[i]) + return -ENOMEM; + } + return 0; + } ++#endif + + static int ddb_buffers_alloc(struct ddb *dev) + { +@@ -293,34 +271,24 @@ static int ddb_buffers_alloc(struct ddb *dev) + port = &dev->port[i]; + switch (port->class) { + case DDB_PORT_TUNER: +- if (io_alloc(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num) < 0) ++ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0) + return -1; +- if (io_alloc(dev->pdev, port->input[1]->vbuf, +- port->input[1]->pbuf, +- port->input[1]->dma_buf_size, +- port->input[1]->dma_buf_num) < 0) ++ if (dma_alloc(dev->pdev, port->input[1]->dma, 0) < 0) + return -1; + break; + case DDB_PORT_CI: +- if (io_alloc(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num) < 0) ++ case DDB_PORT_LOOP: ++ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0) + return -1; +- if (io_alloc(dev->pdev, port->output->vbuf, +- port->output->pbuf, +- port->output->dma_buf_size, +- port->output->dma_buf_num) < 0) ++ case DDB_PORT_MOD: ++ if (dma_alloc(dev->pdev, port->output->dma, 1) < 0) + return -1; + break; + default: + break; + } + } +- ddb_address_table(dev); ++ ddb_set_dma_tables(dev); + return 0; + } + +@@ -331,287 +299,839 @@ static void ddb_buffers_free(struct ddb *dev) + + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; +- io_free(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num); +- io_free(dev->pdev, port->input[1]->vbuf, +- port->input[1]->pbuf, +- port->input[1]->dma_buf_size, +- port->input[1]->dma_buf_num); +- io_free(dev->pdev, port->output->vbuf, +- port->output->pbuf, +- port->output->dma_buf_size, +- port->output->dma_buf_num); ++ ++ if (port->input[0]) ++ dma_free(dev->pdev, port->input[0]->dma, 0); ++ if (port->input[1]) ++ dma_free(dev->pdev, port->input[1]->dma, 0); ++ if (port->output) ++ dma_free(dev->pdev, port->output->dma, 1); + } + } + +-static void ddb_input_start(struct ddb_input *input) ++static void ddb_output_start(struct ddb_output *output) + { +- struct ddb *dev = input->port->dev; ++ struct ddb *dev = output->port->dev; ++ u32 con2; + +- spin_lock_irq(&input->lock); +- input->cbuf = 0; +- input->coff = 0; ++ con2 = ((output->port->obr << 13) + 71999) / 72000; ++ con2 = (con2 << 16) | output->port->gap; + +- /* reset */ +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(2, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); ++ if (output->dma) { ++ spin_lock_irq(&output->dma->lock); ++ output->dma->cbuf = 0; ++ output->dma->coff = 0; ++ output->dma->stat = 0; ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); ++ } ++ if (output->port->class == DDB_PORT_MOD) ++ ddbridge_mod_output_start(output); ++ else { ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr)); ++ } ++ if (output->dma) { ++ ddbwritel(dev, output->dma->bufreg, ++ DMA_BUFFER_SIZE(output->dma->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); ++ ddbwritel(dev, 1, DMA_BASE_READ); ++ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); ++ } ++ if (output->port->class != DDB_PORT_MOD) { ++ if (output->port->input[0]->port->class == DDB_PORT_LOOP) ++ /*ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0x45, ++ TS_OUTPUT_CONTROL(output->nr));*/ ++ ddbwritel(dev, (1 << 13) | 0x15, ++ TS_OUTPUT_CONTROL(output->nr)); ++ else ++ ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr)); ++ } ++ if (output->dma) { ++ output->dma->running = 1; ++ spin_unlock_irq(&output->dma->lock); ++ } ++} + +- ddbwritel((1 << 16) | +- (input->dma_buf_num << 11) | +- (input->dma_buf_size >> 7), +- DMA_BUFFER_SIZE(input->nr)); +- ddbwritel(0, DMA_BUFFER_ACK(input->nr)); ++static void ddb_output_stop(struct ddb_output *output) ++{ ++ struct ddb *dev = output->port->dev; + +- ddbwritel(1, DMA_BASE_WRITE); +- ddbwritel(3, DMA_BUFFER_CONTROL(input->nr)); +- ddbwritel(9, TS_INPUT_CONTROL(input->nr)); +- input->running = 1; +- spin_unlock_irq(&input->lock); ++ if (output->dma) ++ spin_lock_irq(&output->dma->lock); ++ if (output->port->class == DDB_PORT_MOD) ++ ddbridge_mod_output_stop(output); ++ else ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ if (output->dma) { ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); ++ output->dma->running = 0; ++ spin_unlock_irq(&output->dma->lock); ++ } + } + + static void ddb_input_stop(struct ddb_input *input) + { + struct ddb *dev = input->port->dev; + +- spin_lock_irq(&input->lock); +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(0, DMA_BUFFER_CONTROL(input->nr)); +- input->running = 0; +- spin_unlock_irq(&input->lock); ++ if (input->dma) ++ spin_lock_irq(&input->dma->lock); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); ++ if (input->dma) { ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); ++ input->dma->running = 0; ++ spin_unlock_irq(&input->dma->lock); ++ } ++ /*pr_info("input_stop %d.%d\n", dev->nr, input->nr);*/ + } + +-static void ddb_output_start(struct ddb_output *output) ++static void ddb_input_start(struct ddb_input *input) + { +- struct ddb *dev = output->port->dev; ++ struct ddb *dev = input->port->dev; + +- spin_lock_irq(&output->lock); +- output->cbuf = 0; +- output->coff = 0; +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(2, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel((1 << 16) | +- (output->dma_buf_num << 11) | +- (output->dma_buf_size >> 7), +- DMA_BUFFER_SIZE(output->nr + 8)); +- ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8)); +- +- ddbwritel(1, DMA_BASE_READ); +- ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8)); +- /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */ +- ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr)); +- output->running = 1; +- spin_unlock_irq(&output->lock); ++ if (input->dma) { ++ spin_lock_irq(&input->dma->lock); ++ input->dma->cbuf = 0; ++ input->dma->coff = 0; ++ input->dma->stat = 0; ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); ++ } ++ ddbwritel(dev, 0, TS_INPUT_CONTROL2(input->nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); ++ ++ if (input->dma) { ++ ddbwritel(dev, input->dma->bufreg, ++ DMA_BUFFER_SIZE(input->dma->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); ++ ddbwritel(dev, 1, DMA_BASE_WRITE); ++ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); ++ } ++ if (dev->info->type == DDB_OCTONET) ++ ddbwritel(dev, 0x01, TS_INPUT_CONTROL(input->nr)); ++ else ++ ddbwritel(dev, 0x09, TS_INPUT_CONTROL(input->nr)); ++ if (input->dma) { ++ input->dma->running = 1; ++ spin_unlock_irq(&input->dma->lock); ++ } ++ /*pr_info("input_start %d.%d\n", dev->nr, input->nr);*/ + } + +-static void ddb_output_stop(struct ddb_output *output) ++ ++static int ddb_dvb_input_start(struct ddb_input *input) + { +- struct ddb *dev = output->port->dev; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ ++ if (!dvb->users) ++ ddb_input_start(input); ++ ++ return ++dvb->users; ++} ++ ++static int ddb_dvb_input_stop(struct ddb_input *input) ++{ ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; + +- spin_lock_irq(&output->lock); +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8)); +- output->running = 0; +- spin_unlock_irq(&output->lock); ++ if (--dvb->users) ++ return dvb->users; ++ ++ ddb_input_stop(input); ++ return 0; ++} ++ ++static void ddb_input_start_all(struct ddb_input *input) ++{ ++ struct ddb_input *i = input; ++ struct ddb_output *o; ++ ++ mutex_lock(&redirect_lock); ++ while (i && (o = i->redo)) { ++ ddb_output_start(o); ++ i = o->port->input[0]; ++ if (i) ++ ddb_input_start(i); ++ } ++ ddb_input_start(input); ++ mutex_unlock(&redirect_lock); ++} ++ ++static void ddb_input_stop_all(struct ddb_input *input) ++{ ++ struct ddb_input *i = input; ++ struct ddb_output *o; ++ ++ mutex_lock(&redirect_lock); ++ ddb_input_stop(input); ++ while (i && (o = i->redo)) { ++ ddb_output_stop(o); ++ i = o->port->input[0]; ++ if (i) ++ ddb_input_stop(i); ++ } ++ mutex_unlock(&redirect_lock); + } + + static u32 ddb_output_free(struct ddb_output *output) + { +- u32 idx, off, stat = output->stat; ++ u32 idx, off, stat = output->dma->stat; + s32 diff; + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + +- if (output->cbuf != idx) { +- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && +- (output->dma_buf_size - output->coff <= 188)) ++ if (output->dma->cbuf != idx) { ++ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && ++ (output->dma->size - output->dma->coff <= 188)) + return 0; + return 188; + } +- diff = off - output->coff; ++ diff = off - output->dma->coff; + if (diff <= 0 || diff > 188) + return 188; + return 0; + } + ++#if 0 ++static u32 ddb_dma_free(struct ddb_dma *dma) ++{ ++ u32 idx, off, stat = dma->stat; ++ s32 p1, p2, diff; ++ ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ ++ p1 = idx * dma->size + off; ++ p2 = dma->cbuf * dma->size + dma->coff; ++ ++ diff = p1 - p2; ++ if (diff <= 0) ++ diff += dma->num * dma->size; ++ return diff; ++} ++#endif ++ + static ssize_t ddb_output_write(struct ddb_output *output, +- const __user u8 *buf, size_t count) ++ const u8 *buf, size_t count) + { + struct ddb *dev = output->port->dev; +- u32 idx, off, stat = output->stat; ++ u32 idx, off, stat = output->dma->stat; + u32 left = count, len; + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + + while (left) { +- len = output->dma_buf_size - output->coff; +- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && ++ len = output->dma->size - output->dma->coff; ++ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && + (off == 0)) { + if (len <= 188) + break; + len -= 188; + } +- if (output->cbuf == idx) { +- if (off > output->coff) { +-#if 1 +- len = off - output->coff; ++ if (output->dma->cbuf == idx) { ++ if (off > output->dma->coff) { ++ len = off - output->dma->coff; + len -= (len % 188); + if (len <= 188) +- +-#endif + break; + len -= 188; + } + } + if (len > left) + len = left; +- if (copy_from_user(output->vbuf[output->cbuf] + output->coff, ++ if (copy_from_user(output->dma->vbuf[output->dma->cbuf] + ++ output->dma->coff, + buf, len)) + return -EIO; ++#ifdef DDB_ALT_DMA ++ dma_sync_single_for_device(dev->dev, ++ output->dma->pbuf[ ++ output->dma->cbuf], ++ output->dma->size, DMA_TO_DEVICE); ++#endif + left -= len; + buf += len; +- output->coff += len; +- if (output->coff == output->dma_buf_size) { +- output->coff = 0; +- output->cbuf = ((output->cbuf + 1) % output->dma_buf_num); ++ output->dma->coff += len; ++ if (output->dma->coff == output->dma->size) { ++ output->dma->coff = 0; ++ output->dma->cbuf = ((output->dma->cbuf + 1) % ++ output->dma->num); + } +- ddbwritel((output->cbuf << 11) | (output->coff >> 7), +- DMA_BUFFER_ACK(output->nr + 8)); ++ ddbwritel(dev, ++ (output->dma->cbuf << 11) | ++ (output->dma->coff >> 7), ++ DMA_BUFFER_ACK(output->dma->nr)); + } + return count - left; + } + ++#if 0 ++static u32 ddb_input_free_bytes(struct ddb_input *input) ++{ ++ struct ddb *dev = input->port->dev; ++ u32 idx, off, stat = input->dma->stat; ++ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); ++ ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ ++ if (ctrl & 4) ++ return 0; ++ if (input->dma->cbuf != idx) ++ return 1; ++ return 0; ++} ++ ++ ++ ++static s32 ddb_output_used_bufs(struct ddb_output *output) ++{ ++ u32 idx, off, stat, ctrl; ++ s32 diff; ++ ++ spin_lock_irq(&output->dma->lock); ++ stat = output->dma->stat; ++ ctrl = output->dma->ctrl; ++ spin_unlock_irq(&output->dma->lock); ++ ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ ++ if (ctrl & 4) ++ return 0; ++ diff = output->dma->cbuf - idx; ++ if (diff == 0 && off < output->dma->coff) ++ return 0; ++ if (diff <= 0) ++ diff += output->dma->num; ++ return diff; ++} ++ ++static s32 ddb_input_free_bufs(struct ddb_input *input) ++{ ++ u32 idx, off, stat, ctrl; ++ s32 free; ++ ++ spin_lock_irq(&input->dma->lock); ++ ctrl = input->dma->ctrl; ++ stat = input->dma->stat; ++ spin_unlock_irq(&input->dma->lock); ++ if (ctrl & 4) ++ return 0; ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ free = input->dma->cbuf - idx; ++ if (free == 0 && off < input->dma->coff) ++ return 0; ++ if (free <= 0) ++ free += input->dma->num; ++ return free - 1; ++} ++ ++static u32 ddb_output_ok(struct ddb_output *output) ++{ ++ struct ddb_input *input = output->port->input[0]; ++ s32 diff; ++ ++ diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output); ++ if (diff > 0) ++ return 1; ++ return 0; ++} ++#endif ++ + static u32 ddb_input_avail(struct ddb_input *input) + { + struct ddb *dev = input->port->dev; +- u32 idx, off, stat = input->stat; +- u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr)); ++ u32 idx, off, stat = input->dma->stat; ++ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + + if (ctrl & 4) { +- printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); +- ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); ++ pr_err("IA %d %d %08x\n", idx, off, ctrl); ++ ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); + return 0; + } +- if (input->cbuf != idx) ++ if (input->dma->cbuf != idx) + return 188; + return 0; + } + +-static ssize_t ddb_input_read(struct ddb_input *input, __user u8 *buf, size_t count) ++static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) + { + struct ddb *dev = input->port->dev; + u32 left = count; +- u32 idx, free, stat = input->stat; ++ u32 idx, off, free, stat = input->dma->stat; + int ret; + + idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; + + while (left) { +- if (input->cbuf == idx) ++ if (input->dma->cbuf == idx) + return count - left; +- free = input->dma_buf_size - input->coff; ++ free = input->dma->size - input->dma->coff; + if (free > left) + free = left; +- ret = copy_to_user(buf, input->vbuf[input->cbuf] + +- input->coff, free); ++#ifdef DDB_ALT_DMA ++ dma_sync_single_for_cpu(dev->dev, ++ input->dma->pbuf[input->dma->cbuf], ++ input->dma->size, DMA_FROM_DEVICE); ++#endif ++ ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + ++ input->dma->coff, free); + if (ret) + return -EFAULT; +- input->coff += free; +- if (input->coff == input->dma_buf_size) { +- input->coff = 0; +- input->cbuf = (input->cbuf+1) % input->dma_buf_num; ++ input->dma->coff += free; ++ if (input->dma->coff == input->dma->size) { ++ input->dma->coff = 0; ++ input->dma->cbuf = (input->dma->cbuf + 1) % ++ input->dma->num; + } + left -= free; +- ddbwritel((input->cbuf << 11) | (input->coff >> 7), +- DMA_BUFFER_ACK(input->nr)); ++ ddbwritel(dev, ++ (input->dma->cbuf << 11) | (input->dma->coff >> 7), ++ DMA_BUFFER_ACK(input->dma->nr)); + } + return count; + } + +-/******************************************************************************/ +-/******************************************************************************/ +-/******************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ + +-#if 0 +-static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) ++static ssize_t ts_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) + { +- int i; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb *dev = output->port->dev; ++ size_t left = count; ++ int stat; + +- for (i = 0; i < dev->info->port_num * 2; i++) { +- if (dev->input[i].fe == fe) +- return &dev->input[i]; ++ if (!dev->has_dma) ++ return -EINVAL; ++ while (left) { ++ if (ddb_output_free(output) < 188) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible( ++ output->dma->wq, ++ ddb_output_free(output) >= 188) < 0) ++ break; ++ } ++ stat = ddb_output_write(output, buf, left); ++ if (stat < 0) ++ return stat; ++ buf += stat; ++ left -= stat; + } +- return NULL; ++ return (left == count) ? -EAGAIN : (count - left); + } +-#endif + +-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++static ssize_t ts_read(struct file *file, char *buf, ++ size_t count, loff_t *ppos) + { +- struct ddb_input *input = fe->sec_priv; +- struct ddb_port *port = input->port; +- int status; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; ++ struct ddb *dev = output->port->dev; ++ size_t left = count; ++ int stat; + +- if (enable) { +- mutex_lock(&port->i2c_gate_lock); +- status = input->gate_ctrl(fe, 1); +- } else { +- status = input->gate_ctrl(fe, 0); +- mutex_unlock(&port->i2c_gate_lock); ++ if (!dev->has_dma) ++ return -EINVAL; ++ while (left) { ++ if (ddb_input_avail(input) < 188) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible( ++ input->dma->wq, ++ ddb_input_avail(input) >= 188) < 0) ++ break; ++ } ++ stat = ddb_input_read(input, buf, left); ++ if (stat < 0) ++ return stat; ++ left -= stat; ++ buf += stat; + } +- return status; ++ return (count && (left == count)) ? -EAGAIN : (count - left); + } + +-static int demod_attach_drxk(struct ddb_input *input) ++static unsigned int ts_poll(struct file *file, poll_table *wait) + { +- struct i2c_adapter *i2c = &input->port->i2c->adap; +- struct dvb_frontend *fe; +- struct drxk_config config; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; + +- memset(&config, 0, sizeof(config)); +- config.microcode_name = "drxk_a3.mc"; +- config.qam_demod_parameter_count = 4; +- config.adr = 0x29 + (input->nr & 1); ++ unsigned int mask = 0; + +- fe = input->fe = dvb_attach(drxk_attach, &config, i2c); +- if (!input->fe) { +- printk(KERN_ERR "No DRXK found!\n"); +- return -ENODEV; +- } +- fe->sec_priv = input; +- input->gate_ctrl = fe->ops.i2c_gate_ctrl; +- fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; +- return 0; ++ poll_wait(file, &input->dma->wq, wait); ++ poll_wait(file, &output->dma->wq, wait); ++ if (ddb_input_avail(input) >= 188) ++ mask |= POLLIN | POLLRDNORM; ++ if (ddb_output_free(output) >= 188) ++ mask |= POLLOUT | POLLWRNORM; ++ return mask; + } + +-static int tuner_attach_tda18271(struct ddb_input *input) ++static int ts_release(struct inode *inode, struct file *file) + { +- struct i2c_adapter *i2c = &input->port->i2c->adap; +- struct dvb_frontend *fe; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { ++ if (!input) ++ return -EINVAL; ++ ddb_input_stop(input); ++ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { ++ if (!output) ++ return -EINVAL; ++ ddb_output_stop(output); ++ } ++ return dvb_generic_release(inode, file); ++} ++ ++static int ts_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { ++ if (!input) ++ return -EINVAL; ++ if (input->redo || input->redi) ++ return -EBUSY; ++ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { ++ if (!output) ++ return -EINVAL; ++ } ++ err = dvb_generic_open(inode, file); ++ if (err < 0) ++ return err; ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ ddb_input_start(input); ++ else if ((file->f_flags & O_ACCMODE) == O_WRONLY) ++ ddb_output_start(output); ++ return err; ++} ++ ++static int mod_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ ++ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { ++ if (!output) ++ return -EINVAL; ++ ddb_output_stop(output); ++ } ++ return dvb_generic_release(inode, file); ++} ++ ++static int mod_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ ++ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { ++ if (!output) ++ return -EINVAL; ++ } ++ err = dvb_generic_open(inode, file); ++ if (err < 0) ++ return err; ++ if ((file->f_flags & O_ACCMODE) == O_WRONLY) ++ ddb_output_start(output); ++ return err; ++} ++static const struct file_operations ci_fops = { ++ .owner = THIS_MODULE, ++ .read = ts_read, ++ .write = ts_write, ++ .open = ts_open, ++ .release = ts_release, ++ .poll = ts_poll, ++ .mmap = 0, ++}; ++ ++static struct dvb_device dvbdev_ci = { ++ .priv = 0, ++ .readers = 1, ++ .writers = 1, ++ .users = 2, ++ .fops = &ci_fops, ++}; ++ ++ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static long mod_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl); ++} ++ ++static const struct file_operations mod_fops = { ++ .owner = THIS_MODULE, ++ .read = ts_read, ++ .write = ts_write, ++ .open = mod_open, ++ .release = mod_release, ++ .poll = ts_poll, ++ .mmap = 0, ++ .unlocked_ioctl = mod_ioctl, ++}; ++ ++static struct dvb_device dvbdev_mod = { ++ .priv = 0, ++ .readers = 1, ++ .writers = 1, ++ .users = 2, ++ .fops = &mod_fops, ++}; ++ ++ ++#if 0 ++static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) ++{ ++ int i; ++ ++ for (i = 0; i < dev->info->port_num * 2; i++) { ++ if (dev->input[i].fe == fe) ++ return &dev->input[i]; ++ } ++ return NULL; ++} ++#endif ++ ++static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct ddb_input *input = fe->sec_priv; ++ struct ddb_port *port = input->port; ++ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; ++ int status; ++ ++ if (enable) { ++ mutex_lock(&port->i2c_gate_lock); ++ status = dvb->i2c_gate_ctrl(fe, 1); ++ } else { ++ status = dvb->i2c_gate_ctrl(fe, 0); ++ mutex_unlock(&port->i2c_gate_lock); ++ } ++ return status; ++} ++ ++#if IS_ENABLED(CONFIG_DVB_DRXK) ++static int demod_attach_drxk(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ struct drxk_config config; ++ ++ memset(&config, 0, sizeof(config)); ++ config.adr = 0x29 + (input->nr & 1); ++ config.microcode_name = "drxk_a3.mc"; ++ ++ fe = dvb->fe = dvb_attach(drxk_attach, &config, i2c); ++ if (!fe) { ++ pr_err("No DRXK found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++#endif ++ ++#if 0 ++struct stv0367_config stv0367_0 = { ++ .demod_address = 0x1f, ++ .xtal = 27000000, ++ .if_khz = 5000, ++ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, ++ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, ++ .clk_pol = STV0367_RISINGEDGE_CLOCK, ++}; ++ ++struct stv0367_config stv0367_1 = { ++ .demod_address = 0x1e, ++ .xtal = 27000000, ++ .if_khz = 5000, ++ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, ++ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, ++ .clk_pol = STV0367_RISINGEDGE_CLOCK, ++}; ++ ++ ++static int demod_attach_stv0367(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ ++ fe = dvb->fe = dvb_attach(stv0367ter_attach, ++ (input->nr & 1) ? &stv0367_1 : &stv0367_0, ++ i2c); ++ if (!dvb->fe) { ++ pr_err("No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++#endif ++ ++struct cxd2843_cfg cxd2843_0 = { ++ .adr = 0x6c, ++}; ++ ++struct cxd2843_cfg cxd2843_1 = { ++ .adr = 0x6d, ++}; ++ ++struct cxd2843_cfg cxd2843p_0 = { ++ .adr = 0x6c, ++ .parallel = 1, ++}; + +- if (input->fe->ops.i2c_gate_ctrl) +- input->fe->ops.i2c_gate_ctrl(input->fe, 1); +- fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); ++struct cxd2843_cfg cxd2843p_1 = { ++ .adr = 0x6d, ++ .parallel = 1, ++}; ++ ++static int demod_attach_cxd2843(struct ddb_input *input, int par) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ ++ if (par) ++ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, ++ (input->nr & 1) ? ++ &cxd2843p_1 : &cxd2843p_0); ++ else ++ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, ++ (input->nr & 1) ? ++ &cxd2843_1 : &cxd2843_0); ++ if (!dvb->fe) { ++ pr_err("No cxd2837/38/43 found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++struct stv0367_cfg stv0367dd_0 = { ++ .adr = 0x1f, ++ .xtal = 27000000, ++}; ++ ++struct stv0367_cfg stv0367dd_1 = { ++ .adr = 0x1e, ++ .xtal = 27000000, ++}; ++ ++static int demod_attach_stv0367dd(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ ++ fe = dvb->fe = dvb_attach(stv0367_attach, i2c, ++ (input->nr & 1) ? ++ &stv0367dd_1 : &stv0367dd_0, ++ &dvb->fe2); ++ if (!dvb->fe) { ++ pr_err("No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++static int tuner_attach_tda18271(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ ++ if (dvb->fe->ops.i2c_gate_ctrl) ++ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1); ++ fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60); ++ if (dvb->fe->ops.i2c_gate_ctrl) ++ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0); + if (!fe) { +- printk(KERN_ERR "No TDA18271 found!\n"); ++ pr_err("No TDA18271 found!\n"); + return -ENODEV; + } +- if (input->fe->ops.i2c_gate_ctrl) +- input->fe->ops.i2c_gate_ctrl(input->fe, 0); + return 0; + } + +-/******************************************************************************/ +-/******************************************************************************/ +-/******************************************************************************/ ++static int tuner_attach_tda18212dd(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ ++ fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c, ++ (input->nr & 1) ? 0x63 : 0x60); ++ if (!fe) { ++ pr_err("No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_DVB_TDA18212 ++struct tda18212_config tda18212_0 = { ++ .i2c_address = 0x60, ++}; ++ ++struct tda18212_config tda18212_1 = { ++ .i2c_address = 0x63, ++}; ++ ++static int tuner_attach_tda18212(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; ++ struct tda18212_config *cfg; ++ ++ cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0; ++ fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg); ++ if (!fe) { ++ pr_err("No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++#endif ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ + + static struct stv090x_config stv0900 = { + .device = STV0900, +@@ -624,6 +1144,9 @@ static struct stv090x_config stv0900 = { + .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + ++ .ts1_tei = 1, ++ .ts2_tei = 1, ++ + .repeater_level = STV090x_RPTLEVEL_16, + + .adc1_range = STV090x_ADC_1Vpp, +@@ -643,6 +1166,9 @@ static struct stv090x_config stv0900_aa = { + .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + ++ .ts1_tei = 1, ++ .ts2_tei = 1, ++ + .repeater_level = STV090x_RPTLEVEL_16, + + .adc1_range = STV090x_ADC_1Vpp, +@@ -667,18 +1193,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) + { + struct i2c_adapter *i2c = &input->port->i2c->adap; + struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; + +- input->fe = dvb_attach(stv090x_attach, feconf, i2c, +- (input->nr & 1) ? STV090x_DEMODULATOR_1 +- : STV090x_DEMODULATOR_0); +- if (!input->fe) { +- printk(KERN_ERR "No STV0900 found!\n"); ++ dvb->fe = dvb_attach(stv090x_attach, feconf, i2c, ++ (input->nr & 1) ? STV090x_DEMODULATOR_1 ++ : STV090x_DEMODULATOR_0); ++ if (!dvb->fe) { ++ pr_err("No STV0900 found!\n"); + return -ENODEV; + } +- if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, ++ if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0, + 0, (input->nr & 1) ? + (0x09 - type) : (0x0b - type))) { +- printk(KERN_ERR "No LNBH24 found!\n"); ++ pr_err("No LNBH24 found!\n"); + return -ENODEV; + } + return 0; +@@ -687,18 +1214,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) + static int tuner_attach_stv6110(struct ddb_input *input, int type) + { + struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; + struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; + struct stv6110x_config *tunerconf = (input->nr & 1) ? + &stv6110b : &stv6110a; + struct stv6110x_devctl *ctl; + +- ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); ++ ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c); + if (!ctl) { +- printk(KERN_ERR "No STV6110X found!\n"); ++ pr_err("No STV6110X found!\n"); + return -ENODEV; + } +- printk(KERN_INFO "attach tuner input %d adr %02x\n", +- input->nr, tunerconf->addr); ++ pr_info("attach tuner input %d adr %02x\n", ++ input->nr, tunerconf->addr); + + feconf->tuner_init = ctl->tuner_init; + feconf->tuner_sleep = ctl->tuner_sleep; +@@ -715,329 +1243,919 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) + return 0; + } + +-static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, +- int (*start_feed)(struct dvb_demux_feed *), +- int (*stop_feed)(struct dvb_demux_feed *), +- void *priv) ++static struct stv0910_cfg stv0910 = { ++ .adr = 0x68, ++ .parallel = 1, ++ .rptlvl = 4, ++ .clk = 30000000, ++}; ++ ++static int demod_attach_stv0910(struct ddb_input *input, int type) + { +- dvbdemux->priv = priv; ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; + +- dvbdemux->filternum = 256; +- dvbdemux->feednum = 256; +- dvbdemux->start_feed = start_feed; +- dvbdemux->stop_feed = stop_feed; +- dvbdemux->write_to_decoder = NULL; +- dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | +- DMX_SECTION_FILTERING | +- DMX_MEMORY_BASED_FILTERING); +- return dvb_dmx_init(dvbdemux); ++ dvb->fe = dvb_attach(stv0910_attach, i2c, &stv0910, (input->nr & 1)); ++ if (!dvb->fe) { ++ pr_err("No STV0910 found!\n"); ++ return -ENODEV; ++ } ++ if (!dvb_attach(lnbh25_attach, dvb->fe, i2c, ++ (input->nr & 1) ? 0x09 : 0x08)) { ++ pr_err("No LNBH25 found!\n"); ++ return -ENODEV; ++ } ++ return 0; + } + +-static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, +- struct dvb_demux *dvbdemux, +- struct dmx_frontend *hw_frontend, +- struct dmx_frontend *mem_frontend, +- struct dvb_adapter *dvb_adapter) ++static int tuner_attach_stv6111(struct ddb_input *input) + { +- int ret; +- +- dmxdev->filternum = 256; +- dmxdev->demux = &dvbdemux->dmx; +- dmxdev->capabilities = 0; +- ret = dvb_dmxdev_init(dmxdev, dvb_adapter); +- if (ret < 0) +- return ret; ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_frontend *fe; + +- hw_frontend->source = DMX_FRONTEND_0; +- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); +- mem_frontend->source = DMX_MEMORY_FE; +- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); +- return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); ++ fe = dvb_attach(stv6111_attach, dvb->fe, i2c, ++ (input->nr & 1) ? 0x63 : 0x60); ++ if (!fe) { ++ pr_err("No STV6111 found!\n"); ++ return -ENODEV; ++ } ++ return 0; + } + +-static int start_feed(struct dvb_demux_feed *dvbdmxfeed) ++static int lnb_command(struct ddb *dev, u32 lnb, u32 cmd) + { +- struct dvb_demux *dvbdmx = dvbdmxfeed->demux; +- struct ddb_input *input = dvbdmx->priv; ++ u32 c, v = 0; + +- if (!input->users) +- ddb_input_start(input); +- +- return ++input->users; ++ v = LNB_TONE & (dev->lnb_tone << (15 - lnb)); ++ pr_info("lnb_control[%u] = %08x\n", lnb, cmd | v); ++ ddbwritel(dev, cmd | v, LNB_CONTROL(lnb)); ++ for (c = 0; c < 10; c++) { ++ v = ddbreadl(dev, LNB_CONTROL(lnb)); ++ pr_info("ctrl = %08x\n", v); ++ if ((v & LNB_BUSY) == 0) ++ break; ++ msleep(20); ++ } ++ return 0; + } + +-static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++static int dd_send_master_cmd(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *cmd) + { +- struct dvb_demux *dvbdmx = dvbdmxfeed->demux; +- struct ddb_input *input = dvbdmx->priv; +- +- if (--input->users) +- return input->users; ++ struct ddb_input *input = fe->sec_priv; ++ struct ddb_port *port = input->port; ++ struct ddb *dev = port->dev; ++ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; ++ int i; + +- ddb_input_stop(input); ++ mutex_lock(&dev->lnb_lock); ++ ddbwritel(dev, 0, LNB_BUF_LEVEL(dvb->input)); ++ for (i = 0; i < cmd->msg_len; i++) ++ ddbwritel(dev, cmd->msg[i], LNB_BUF_WRITE(dvb->input)); ++ lnb_command(dev, dvb->input, LNB_CMD_DISEQC); ++ mutex_unlock(&dev->lnb_lock); + return 0; + } + +- +-static void dvb_input_detach(struct ddb_input *input) ++static int dd_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) + { +- struct dvb_adapter *adap = &input->adap; +- struct dvb_demux *dvbdemux = &input->demux; +- +- switch (input->attached) { +- case 5: +- if (input->fe2) +- dvb_unregister_frontend(input->fe2); +- if (input->fe) { +- dvb_unregister_frontend(input->fe); +- dvb_frontend_detach(input->fe); +- input->fe = NULL; +- } +- case 4: +- dvb_net_release(&input->dvbnet); +- +- case 3: +- dvbdemux->dmx.close(&dvbdemux->dmx); +- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, +- &input->hw_frontend); +- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, +- &input->mem_frontend); +- dvb_dmxdev_release(&input->dmxdev); ++ struct ddb_input *input = fe->sec_priv; ++ struct ddb_port *port = input->port; ++ struct ddb *dev = port->dev; ++ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; ++ int s = 0; + +- case 2: +- dvb_dmx_release(&input->demux); ++ mutex_lock(&dev->lnb_lock); ++ switch (tone) { ++ case SEC_TONE_OFF: ++ dev->lnb_tone &= ~(1ULL << dvb->input); ++ break; ++ case SEC_TONE_ON: ++ dev->lnb_tone |= (1ULL << dvb->input); ++ break; ++ default: ++ s = -EINVAL; ++ break; ++ }; ++ if (!s) ++ s = lnb_command(dev, dvb->input, LNB_CMD_NOP); ++ mutex_unlock(&dev->lnb_lock); ++ return 0; ++} + +- case 1: +- dvb_unregister_adapter(adap); +- } +- input->attached = 0; ++static int dd_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) ++{ ++ ++ return 0; + } + +-static int dvb_input_attach(struct ddb_input *input) ++static int dd_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) + { +- int ret; ++ struct ddb_input *input = fe->sec_priv; + struct ddb_port *port = input->port; +- struct dvb_adapter *adap = &input->adap; +- struct dvb_demux *dvbdemux = &input->demux; +- +- ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, +- &input->port->dev->pdev->dev, +- adapter_nr); +- if (ret < 0) { +- printk(KERN_ERR "ddbridge: Could not register adapter." +- "Check if you enabled enough adapters in dvb-core!\n"); ++ struct ddb *dev = port->dev; ++ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; ++ int s = 0; ++ ++ mutex_lock(&dev->lnb_lock); ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ lnb_command(dev, dvb->input, LNB_CMD_OFF); ++ break; ++ case SEC_VOLTAGE_13: ++ lnb_command(dev, dvb->input, LNB_CMD_LOW); ++ break; ++ case SEC_VOLTAGE_18: ++ lnb_command(dev, dvb->input, LNB_CMD_HIGH); ++ break; ++ default: ++ s = -EINVAL; ++ break; ++ }; ++ mutex_unlock(&dev->lnb_lock); ++ return s; ++} ++ ++static int dd_set_input(struct dvb_frontend *fe) ++{ ++ ++ return 0; ++} ++ ++static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, ++ int (*start_feed)(struct dvb_demux_feed *), ++ int (*stop_feed)(struct dvb_demux_feed *), ++ void *priv) ++{ ++ dvbdemux->priv = priv; ++ ++ dvbdemux->filternum = 256; ++ dvbdemux->feednum = 256; ++ dvbdemux->start_feed = start_feed; ++ dvbdemux->stop_feed = stop_feed; ++ dvbdemux->write_to_decoder = NULL; ++ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING); ++ return dvb_dmx_init(dvbdemux); ++} ++ ++static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, ++ struct dvb_demux *dvbdemux, ++ struct dmx_frontend *hw_frontend, ++ struct dmx_frontend *mem_frontend, ++ struct dvb_adapter *dvb_adapter) ++{ ++ int ret; ++ ++ dmxdev->filternum = 256; ++ dmxdev->demux = &dvbdemux->dmx; ++ dmxdev->capabilities = 0; ++ ret = dvb_dmxdev_init(dmxdev, dvb_adapter); ++ if (ret < 0) + return ret; ++ ++ hw_frontend->source = DMX_FRONTEND_0; ++ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); ++ mem_frontend->source = DMX_MEMORY_FE; ++ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); ++ return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); ++} ++ ++#if 0 ++static int start_input(struct ddb_input *input) ++{ ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ ++ if (!dvb->users) ++ ddb_input_start_all(input); ++ ++ return ++dvb->users; ++} ++ ++static int stop_input(struct ddb_input *input) ++{ ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ ++ if (--dvb->users) ++ return dvb->users; ++ ++ ddb_input_stop_all(input); ++ return 0; ++} ++#endif ++ ++static int start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct ddb_input *input = dvbdmx->priv; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ ++ if (!dvb->users) ++ ddb_input_start_all(input); ++ ++ return ++dvb->users; ++} ++ ++static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct ddb_input *input = dvbdmx->priv; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ ++ if (--dvb->users) ++ return dvb->users; ++ ++ ddb_input_stop_all(input); ++ return 0; ++} ++ ++static void dvb_input_detach(struct ddb_input *input) ++{ ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_demux *dvbdemux = &dvb->demux; ++ ++ switch (dvb->attached) { ++ case 0x31: ++ if (dvb->fe2) ++ dvb_unregister_frontend(dvb->fe2); ++ if (dvb->fe) ++ dvb_unregister_frontend(dvb->fe); ++ /* fallthrough */ ++ case 0x30: ++ dvb_frontend_detach(dvb->fe); ++ dvb->fe = dvb->fe2 = NULL; ++ /* fallthrough */ ++ case 0x21: ++ if (input->port->dev->ns_num) ++ dvb_netstream_release(&dvb->dvbns); ++ /* fallthrough */ ++ case 0x20: ++ dvb_net_release(&dvb->dvbnet); ++ /* fallthrough */ ++ case 0x11: ++ dvbdemux->dmx.close(&dvbdemux->dmx); ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, ++ &dvb->hw_frontend); ++ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, ++ &dvb->mem_frontend); ++ dvb_dmxdev_release(&dvb->dmxdev); ++ /* fallthrough */ ++ case 0x10: ++ dvb_dmx_release(&dvb->demux); ++ /* fallthrough */ ++ case 0x01: ++ break; ++ } ++ dvb->attached = 0x00; ++} ++ ++static int dvb_register_adapters(struct ddb *dev) ++{ ++ int i, ret = 0; ++ struct ddb_port *port; ++ struct dvb_adapter *adap; ++ ++ if (adapter_alloc == 3 || dev->info->type == DDB_MOD) { ++ port = &dev->port[0]; ++ adap = port->dvb[0].adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ port->dev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->dvb[0].adap_registered = 1; ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ port->dvb[0].adap = adap; ++ port->dvb[1].adap = adap; ++ } ++ return 0; ++ } ++ ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ switch (port->class) { ++ case DDB_PORT_TUNER: ++ adap = port->dvb[0].adap; ++ ret = dvb_register_adapter(adap, "DDBridge", ++ THIS_MODULE, ++ port->dev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->dvb[0].adap_registered = 1; ++ ++ if (adapter_alloc > 0) { ++ port->dvb[1].adap = port->dvb[0].adap; ++ break; ++ } ++ adap = port->dvb[1].adap; ++ ret = dvb_register_adapter(adap, "DDBridge", ++ THIS_MODULE, ++ port->dev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->dvb[1].adap_registered = 1; ++ break; ++ ++ case DDB_PORT_CI: ++ case DDB_PORT_LOOP: ++ adap = port->dvb[0].adap; ++ ret = dvb_register_adapter(adap, "DDBridge", ++ THIS_MODULE, ++ port->dev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->dvb[0].adap_registered = 1; ++ break; ++ default: ++ if (adapter_alloc < 2) ++ break; ++ adap = port->dvb[0].adap; ++ ret = dvb_register_adapter(adap, "DDBridge", ++ THIS_MODULE, ++ port->dev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->dvb[0].adap_registered = 1; ++ break; ++ } ++ } ++ return ret; ++} ++ ++static void dvb_unregister_adapters(struct ddb *dev) ++{ ++ int i; ++ struct ddb_port *port; ++ struct ddb_dvb *dvb; ++ ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ ++ dvb = &port->dvb[0]; ++ if (dvb->adap_registered) ++ dvb_unregister_adapter(dvb->adap); ++ dvb->adap_registered = 0; ++ ++ dvb = &port->dvb[1]; ++ if (dvb->adap_registered) ++ dvb_unregister_adapter(dvb->adap); ++ dvb->adap_registered = 0; + } +- input->attached = 1; ++} ++ ++static int dvb_input_attach(struct ddb_input *input) ++{ ++ int ret = 0; ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct ddb_port *port = input->port; ++ struct dvb_adapter *adap = dvb->adap; ++ struct dvb_demux *dvbdemux = &dvb->demux; ++ ++ dvb->attached = 0x01; + + ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", + start_feed, + stop_feed, input); + if (ret < 0) + return ret; +- input->attached = 2; ++ dvb->attached = 0x10; + +- ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux, +- &input->hw_frontend, +- &input->mem_frontend, adap); ++ ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev, ++ &dvb->demux, ++ &dvb->hw_frontend, ++ &dvb->mem_frontend, adap); + if (ret < 0) + return ret; +- input->attached = 3; ++ dvb->attached = 0x11; + +- ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux); ++ ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux); + if (ret < 0) + return ret; +- input->attached = 4; ++ dvb->attached = 0x20; + +- input->fe = NULL; ++ if (input->port->dev->ns_num) { ++ ret = netstream_init(input); ++ if (ret < 0) ++ return ret; ++ dvb->attached = 0x21; ++ } ++ dvb->fe = dvb->fe2 = 0; + switch (port->type) { + case DDB_TUNER_DVBS_ST: + if (demod_attach_stv0900(input, 0) < 0) + return -ENODEV; + if (tuner_attach_stv6110(input, 0) < 0) + return -ENODEV; +- if (input->fe) { +- if (dvb_register_frontend(adap, input->fe) < 0) +- return -ENODEV; +- } ++ break; ++ case DDB_TUNER_DVBS_STV0910: ++ case DDB_TUNER_DVBS_STV0910_P: ++ if (demod_attach_stv0910(input, 0) < 0) ++ return -ENODEV; ++ if (tuner_attach_stv6111(input) < 0) ++ return -ENODEV; + break; + case DDB_TUNER_DVBS_ST_AA: + if (demod_attach_stv0900(input, 1) < 0) + return -ENODEV; + if (tuner_attach_stv6110(input, 1) < 0) + return -ENODEV; +- if (input->fe) { +- if (dvb_register_frontend(adap, input->fe) < 0) +- return -ENODEV; +- } + break; ++#if IS_ENABLED(CONFIG_DVB_DRXK) + case DDB_TUNER_DVBCT_TR: + if (demod_attach_drxk(input) < 0) + return -ENODEV; + if (tuner_attach_tda18271(input) < 0) + return -ENODEV; +- if (dvb_register_frontend(adap, input->fe) < 0) ++ break; ++#endif ++ case DDB_TUNER_DVBCT_ST: ++ if (demod_attach_stv0367dd(input) < 0) ++ return -ENODEV; ++ if (tuner_attach_tda18212dd(input) < 0) ++ return -ENODEV; ++ break; ++ case DDB_TUNER_DVBCT2_SONY: ++ case DDB_TUNER_DVBC2T2_SONY: ++ case DDB_TUNER_ISDBT_SONY: ++ if (demod_attach_cxd2843(input, 0) < 0) ++ return -ENODEV; ++ if (tuner_attach_tda18212dd(input) < 0) ++ return -ENODEV; ++ break; ++ case DDB_TUNER_DVBCT2_SONY_P: ++ case DDB_TUNER_DVBC2T2_SONY_P: ++ case DDB_TUNER_ISDBT_SONY_P: ++ if (demod_attach_cxd2843(input, 1) < 0) ++ return -ENODEV; ++ if (tuner_attach_tda18212dd(input) < 0) + return -ENODEV; +- if (input->fe2) { +- if (dvb_register_frontend(adap, input->fe2) < 0) +- return -ENODEV; +- input->fe2->tuner_priv = input->fe->tuner_priv; +- memcpy(&input->fe2->ops.tuner_ops, +- &input->fe->ops.tuner_ops, +- sizeof(struct dvb_tuner_ops)); +- } + break; ++ default: ++ return 0; + } +- input->attached = 5; ++ dvb->attached = 0x30; ++ if (dvb->fe) { ++ if (dvb_register_frontend(adap, dvb->fe) < 0) ++ return -ENODEV; ++ } ++ if (dvb->fe2) { ++ if (dvb_register_frontend(adap, dvb->fe2) < 0) ++ return -ENODEV; ++ dvb->fe2->tuner_priv = dvb->fe->tuner_priv; ++ memcpy(&dvb->fe2->ops.tuner_ops, ++ &dvb->fe->ops.tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ } ++ dvb->attached = 0x31; + return 0; + } + +-/****************************************************************************/ +-/****************************************************************************/ + +-static ssize_t ts_write(struct file *file, const __user char *buf, +- size_t count, loff_t *ppos) ++static int port_has_encti(struct ddb_port *port) + { +- struct dvb_device *dvbdev = file->private_data; +- struct ddb_output *output = dvbdev->priv; +- size_t left = count; +- int stat; ++ u8 val; ++ int ret = i2c_read_reg(&port->i2c->adap, 0x20, 0, &val); + +- while (left) { +- if (ddb_output_free(output) < 188) { +- if (file->f_flags & O_NONBLOCK) +- break; +- if (wait_event_interruptible( +- output->wq, ddb_output_free(output) >= 188) < 0) +- break; +- } +- stat = ddb_output_write(output, buf, left); +- if (stat < 0) +- break; +- buf += stat; +- left -= stat; +- } +- return (left == count) ? -EAGAIN : (count - left); ++ if (!ret) ++ pr_info("[0x20]=0x%02x\n", val); ++ return ret ? 0 : 1; + } + +-static ssize_t ts_read(struct file *file, __user char *buf, +- size_t count, loff_t *ppos) ++static int port_has_cxd(struct ddb_port *port, u8 *type) + { +- struct dvb_device *dvbdev = file->private_data; +- struct ddb_output *output = dvbdev->priv; +- struct ddb_input *input = output->port->input[0]; +- int left, read; ++ u8 val; ++ u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; ++ struct i2c_msg msgs[2] = {{ .addr = 0x40, .flags = 0, ++ .buf = probe, .len = 4 }, ++ { .addr = 0x40, .flags = I2C_M_RD, ++ .buf = data, .len = 4 } }; ++ val = i2c_transfer(&port->i2c->adap, msgs, 2); ++ if (val != 2) ++ return 0; + +- count -= count % 188; +- left = count; +- while (left) { +- if (ddb_input_avail(input) < 188) { +- if (file->f_flags & O_NONBLOCK) +- break; +- if (wait_event_interruptible( +- input->wq, ddb_input_avail(input) >= 188) < 0) +- break; +- } +- read = ddb_input_read(input, buf, left); +- if (read < 0) +- return read; +- left -= read; +- buf += read; +- } +- return (left == count) ? -EAGAIN : (count - left); ++ if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43) ++ *type = 2; ++ else ++ *type = 1; ++ return 1; + } + +-static unsigned int ts_poll(struct file *file, poll_table *wait) ++static int port_has_xo2(struct ddb_port *port, u8 *id) + { +- /* +- struct dvb_device *dvbdev = file->private_data; +- struct ddb_output *output = dvbdev->priv; +- struct ddb_input *input = output->port->input[0]; +- */ +- unsigned int mask = 0; ++ u8 val; ++ u8 probe[1] = { 0x00 }, data[4]; ++ struct i2c_msg msgs[2] = {{ .addr = 0x10, .flags = 0, ++ .buf = probe, .len = 1 }, ++ { .addr = 0x10, .flags = I2C_M_RD, ++ .buf = data, .len = 4 } }; ++ val = i2c_transfer(&port->i2c->adap, msgs, 2); ++ if (val != 2) ++ return 0; ++ ++ if (data[0] != 'D' || data[1] != 'F') ++ return 0; ++ ++ *id = data[2]; ++ return 1; ++} ++ ++static int port_has_stv0900(struct ddb_port *port) ++{ ++ u8 val; ++ if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) ++ return 0; ++ return 1; ++} ++ ++static int port_has_stv0900_aa(struct ddb_port *port, u8 *id) ++{ ++ if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, id) < 0) ++ return 0; ++ return 1; ++} ++ ++static int port_has_drxks(struct ddb_port *port) ++{ ++ u8 val; ++ if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) ++ return 0; ++ if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) ++ return 0; ++ return 1; ++} ++ ++static int port_has_stv0367(struct ddb_port *port) ++{ ++ u8 val; ++ ++ if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ return 1; ++} + + #if 0 +- if (data_avail_to_read) +- mask |= POLLIN | POLLRDNORM; +- if (data_avail_to_write) +- mask |= POLLOUT | POLLWRNORM; ++static int init_xo2_old(struct ddb_port *port) ++{ ++ struct i2c_adapter *i2c = &port->i2c->adap; ++ u8 val; ++ int res; ++ ++ res = i2c_read_reg(i2c, 0x10, 0x04, &val); ++ if (res < 0) ++ return res; ++ ++ if (val != 0x02) { ++ pr_info("Port %d: invalid XO2\n", port->nr); ++ return -1; ++ } ++ i2c_write_reg(i2c, 0x10, 0xc0, 0x00); /* Disable XO2 I2C master */ ++ ++ i2c_read_reg(i2c, 0x10, 0x08, &val); ++ if (val != 0) { ++ i2c_write_reg(i2c, 0x10, 0x08, 0x00); ++ msleep(100); ++ } ++ /* Enable tuner power, disable pll, reset demods */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x04); ++ usleep_range(2000, 3000); ++ /* Release demod resets */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x07); ++ usleep_range(2000, 3000); ++ /* Start XO2 PLL */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x87); + +- poll_wait(file, &read_queue, wait); +- poll_wait(file, &write_queue, wait); ++ return 0; ++} + #endif +- return mask; ++ ++static int init_xo2(struct ddb_port *port) ++{ ++ struct i2c_adapter *i2c = &port->i2c->adap; ++ u8 val, data[2]; ++ int res; ++ ++ res = i2c_read_regs(i2c, 0x10, 0x04, data, 2); ++ if (res < 0) ++ return res; ++ ++ if (data[0] != 0x01) { ++ pr_info("Port %d: invalid XO2\n", port->nr); ++ return -1; ++ } ++ ++ i2c_read_reg(i2c, 0x10, 0x08, &val); ++ if (val != 0) { ++ i2c_write_reg(i2c, 0x10, 0x08, 0x00); ++ msleep(100); ++ } ++ /* Enable tuner power, disable pll, reset demods */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x04); ++ usleep_range(2000, 3000); ++ /* Release demod resets */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x07); ++ usleep_range(2000, 3000); ++ /* Start XO2 PLL */ ++ i2c_write_reg(i2c, 0x10, 0x08, 0x87); ++ ++ return 0; + } + +-static const struct file_operations ci_fops = { +- .owner = THIS_MODULE, +- .read = ts_read, +- .write = ts_write, +- .open = dvb_generic_open, +- .release = dvb_generic_release, +- .poll = ts_poll, ++static int port_has_cxd28xx(struct ddb_port *port, u8 *id) ++{ ++ struct i2c_adapter *i2c = &port->i2c->adap; ++ int status; ++ ++ status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0); ++ if (status) ++ return 0; ++ status = i2c_read_reg(i2c, 0x6e, 0xfd, id); ++ if (status) ++ return 0; ++ return 1; ++} ++ ++static char *xo2names[] = { ++ "DUAL DVB-S2", "DUAL DVB-C/T/T2", ++ "DUAL DVB-ISDBT", "DUAL DVB-C/C2/T/T2", ++ "DUAL ATSC", "DUAL DVB-C/C2/T/T2", ++ "", "" + }; + +-static struct dvb_device dvbdev_ci = { +- .readers = -1, +- .writers = -1, +- .users = -1, +- .fops = &ci_fops, +-}; ++static void ddb_port_probe(struct ddb_port *port) ++{ ++ struct ddb *dev = port->dev; ++ u8 id; ++ ++ port->name = "NO MODULE"; ++ port->class = DDB_PORT_NONE; ++ ++ if (dev->info->type == DDB_MOD) { ++ port->name = "MOD"; ++ port->class = DDB_PORT_MOD; ++ return; ++ } ++ ++ if (dev->info->type == DDB_OCTOPUS_MAX) { ++ port->name = "DUAL DVB-S2 MX"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_MXL5XX; ++ if (port->i2c) ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ return; ++ } ++ ++ if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) { ++ port->name = "CI internal"; ++ port->class = DDB_PORT_CI; ++ port->type = DDB_CI_INTERNAL; ++ } else if (port_has_cxd(port, &id)) { ++ if (id == 1) { ++ port->name = "CI"; ++ port->class = DDB_PORT_CI; ++ port->type = DDB_CI_EXTERNAL_SONY; ++ ddbwritel(dev, I2C_SPEED_400, ++ port->i2c->regs + I2C_TIMING); ++ } else { ++ pr_info(KERN_INFO "Port %d: Uninitialized DuoFlex\n", ++ port->nr); ++ return; ++ } ++ } else if (port_has_xo2(port, &id)) { ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ id >>= 2; ++ if (id > 5) { ++ port->name = "unknown XO2 DuoFlex"; ++ } else { ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_XO2 + id; ++ port->name = xo2names[id]; ++ init_xo2(port); ++ } ++ } else if (port_has_cxd28xx(port, &id)) { ++ switch (id) { ++ case 0xa4: ++ port->name = "DUAL DVB-CT2 CXD2843"; ++ port->type = DDB_TUNER_DVBC2T2_SONY_P; ++ break; ++ case 0xb1: ++ port->name = "DUAL DVB-CT2 CXD2837"; ++ port->type = DDB_TUNER_DVBCT2_SONY_P; ++ break; ++ case 0xb0: ++ port->name = "DUAL ISDB-T CXD2838"; ++ port->type = DDB_TUNER_ISDBT_SONY_P; ++ break; ++ default: ++ return; ++ } ++ port->class = DDB_PORT_TUNER; ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_stv0900(port)) { ++ port->name = "DUAL DVB-S2"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_DVBS_ST; ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_stv0900_aa(port, &id)) { ++ port->name = "DUAL DVB-S2"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_DVBS_ST_AA; ++ if (id == 0x51) ++ port->type = DDB_TUNER_DVBS_STV0910_P; ++ else ++ port->type = DDB_TUNER_DVBS_ST_AA; ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_drxks(port)) { ++ port->name = "DUAL DVB-C/T"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_DVBCT_TR; ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_stv0367(port)) { ++ port->name = "DUAL DVB-C/T"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_DVBCT_ST; ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_encti(port)) { ++ port->name = "ENCTI"; ++ port->class = DDB_PORT_LOOP; ++ } else if (port->nr == ts_loop) { ++ port->name = "TS LOOP"; ++ port->class = DDB_PORT_LOOP; ++ } ++} ++ ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static int wait_ci_ready(struct ddb_ci *ci) ++{ ++ u32 count = 10; ++ ++ ndelay(500); ++ do { ++ if (ddbreadl(ci->port->dev, ++ CI_CONTROL(ci->nr)) & CI_READY) ++ break; ++ usleep_range(1, 2); ++ if ((--count) == 0) ++ return -1; ++ } while (1); ++ return 0; ++} ++ ++static int read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct ddb_ci *ci = ca->data; ++ u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1); ++ ++ if (address > CI_BUFFER_SIZE) ++ return -1; ++ ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, ++ CI_DO_READ_ATTRIBUTES(ci->nr)); ++ wait_ci_ready(ci); ++ val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); ++ return val; ++} ++ ++static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, ++ int address, u8 value) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, ++ CI_DO_ATTRIBUTE_RW(ci->nr)); ++ wait_ci_ready(ci); ++ return 0; ++} ++ ++static int read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, u8 address) ++{ ++ u32 count = 100; ++ struct ddb_ci *ci = ca->data; ++ u32 res; ++ ++ ddbwritel(ci->port->dev, CI_READ_CMD | address, ++ CI_DO_IO_RW(ci->nr)); ++ ndelay(500); ++ do { ++ res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); ++ if (res & CI_READY) ++ break; ++ usleep_range(1, 2); ++ if ((--count) == 0) ++ return -1; ++ } while (1); ++ return 0xff & res; ++} ++ ++static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, ++ CI_DO_IO_RW(ci->nr)); ++ wait_ci_ready(ci); ++ return 0; ++} ++ ++static int slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ ddbwritel(ci->port->dev, CI_POWER_ON, ++ CI_CONTROL(ci->nr)); ++ msleep(100); ++ ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, ++ CI_CONTROL(ci->nr)); ++ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, ++ CI_CONTROL(ci->nr)); ++ udelay(20); ++ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, ++ CI_CONTROL(ci->nr)); ++ return 0; ++} + +-/****************************************************************************/ +-/****************************************************************************/ +-/****************************************************************************/ ++static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct ddb_ci *ci = ca->data; + +-static void input_tasklet(unsigned long data) ++ ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); ++ msleep(300); ++ return 0; ++} ++ ++static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) + { +- struct ddb_input *input = (struct ddb_input *) data; +- struct ddb *dev = input->port->dev; ++ struct ddb_ci *ci = ca->data; ++ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + +- spin_lock(&input->lock); +- if (!input->running) { +- spin_unlock(&input->lock); +- return; +- } +- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); ++ ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, ++ CI_CONTROL(ci->nr)); ++ return 0; ++} + +- if (input->port->class == DDB_PORT_TUNER) { +- if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) +- printk(KERN_ERR "Overflow input %d\n", input->nr); +- while (input->cbuf != ((input->stat >> 11) & 0x1f) +- || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { +- dvb_dmx_swfilter_packets(&input->demux, +- input->vbuf[input->cbuf], +- input->dma_buf_size / 188); ++static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) ++{ ++ struct ddb_ci *ci = ca->data; ++ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); ++ int stat = 0; + +- input->cbuf = (input->cbuf + 1) % input->dma_buf_num; +- ddbwritel((input->cbuf << 11), +- DMA_BUFFER_ACK(input->nr)); +- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); +- } +- } +- if (input->port->class == DDB_PORT_CI) +- wake_up(&input->wq); +- spin_unlock(&input->lock); ++ if (val & CI_CAM_DETECT) ++ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; ++ if (val & CI_CAM_READY) ++ stat |= DVB_CA_EN50221_POLL_CAM_READY; ++ return stat; + } + +-static void output_tasklet(unsigned long data) ++static struct dvb_ca_en50221 en_templ = { ++ .read_attribute_mem = read_attribute_mem, ++ .write_attribute_mem = write_attribute_mem, ++ .read_cam_control = read_cam_control, ++ .write_cam_control = write_cam_control, ++ .slot_reset = slot_reset, ++ .slot_shutdown = slot_shutdown, ++ .slot_ts_enable = slot_ts_enable, ++ .poll_slot_status = poll_slot_status, ++}; ++ ++static void ci_attach(struct ddb_port *port) + { +- struct ddb_output *output = (struct ddb_output *) data; +- struct ddb *dev = output->port->dev; ++ struct ddb_ci *ci = 0; + +- spin_lock(&output->lock); +- if (!output->running) { +- spin_unlock(&output->lock); ++ ci = kzalloc(sizeof(*ci), GFP_KERNEL); ++ if (!ci) + return; +- } +- output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8)); +- wake_up(&output->wq); +- spin_unlock(&output->lock); ++ memcpy(&ci->en, &en_templ, sizeof(en_templ)); ++ ci->en.data = ci; ++ port->en = &ci->en; ++ ci->port = port; ++ ci->nr = port->nr - 2; + } + ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ + +-static struct cxd2099_cfg cxd_cfg = { +- .bitrate = 62000, ++struct cxd2099_cfg cxd_cfg = { ++ .bitrate = 72000, + .adr = 0x40, + .polarity = 1, + .clock_mode = 1, +@@ -1045,28 +2163,21 @@ static struct cxd2099_cfg cxd_cfg = { + + static int ddb_ci_attach(struct ddb_port *port) + { +- int ret; +- +- ret = dvb_register_adapter(&port->output->adap, +- "DDBridge", +- THIS_MODULE, +- &port->dev->pdev->dev, +- adapter_nr); +- if (ret < 0) +- return ret; +- port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); +- if (!port->en) { +- dvb_unregister_adapter(&port->output->adap); +- return -ENODEV; ++ if (port->type == DDB_CI_EXTERNAL_SONY) { ++ cxd_cfg.bitrate = ci_bitrate; ++ port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); ++ if (!port->en) ++ return -ENODEV; ++ dvb_ca_en50221_init(port->dvb[0].adap, ++ port->en, 0, 1); + } +- ddb_input_start(port->input[0]); +- ddb_output_start(port->output); +- dvb_ca_en50221_init(&port->output->adap, +- port->en, 0, 1); +- ret = dvb_register_device(&port->output->adap, &port->output->dev, +- &dvbdev_ci, (void *) port->output, +- DVB_DEVICE_SEC); +- return ret; ++ if (port->type == DDB_CI_INTERNAL) { ++ ci_attach(port); ++ if (!port->en) ++ return -ENODEV; ++ dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); ++ } ++ return 0; + } + + static int ddb_port_attach(struct ddb_port *port) +@@ -1079,15 +2190,32 @@ static int ddb_port_attach(struct ddb_port *port) + if (ret < 0) + break; + ret = dvb_input_attach(port->input[1]); ++ if (ret < 0) ++ break; ++ port->input[0]->redi = port->input[0]; ++ port->input[1]->redi = port->input[1]; + break; + case DDB_PORT_CI: + ret = ddb_ci_attach(port); ++ if (ret < 0) ++ break; ++ case DDB_PORT_LOOP: ++ ret = dvb_register_device(port->dvb[0].adap, ++ &port->dvb[0].dev, ++ &dvbdev_ci, (void *) port->output, ++ DVB_DEVICE_CI); ++ break; ++ case DDB_PORT_MOD: ++ ret = dvb_register_device(port->dvb[0].adap, ++ &port->dvb[0].dev, ++ &dvbdev_mod, (void *) port->output, ++ DVB_DEVICE_MOD); + break; + default: + break; + } + if (ret < 0) +- printk(KERN_ERR "port_attach on port %d failed\n", port->nr); ++ pr_err("port_attach on port %d failed\n", port->nr); + return ret; + } + +@@ -1096,6 +2224,21 @@ static int ddb_ports_attach(struct ddb *dev) + int i, ret = 0; + struct ddb_port *port; + ++ if (dev->ids.devid == 0x0301dd01) ++ dev->ns_num = 15; ++ else ++ dev->ns_num = dev->info->ns_num; ++ for (i = 0; i < dev->ns_num; i++) ++ dev->ns[i].nr = i; ++ pr_info("%d netstream channels\n", dev->ns_num); ++ ++ if (dev->info->port_num) { ++ ret = dvb_register_adapters(dev); ++ if (ret < 0) { ++ pr_err("Registering adapters failed. Check DVB_MAX_ADAPTERS in config.\n"); ++ return ret; ++ } ++ } + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; + ret = ddb_port_attach(port); +@@ -1112,124 +2255,259 @@ static void ddb_ports_detach(struct ddb *dev) + + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; ++ + switch (port->class) { + case DDB_PORT_TUNER: + dvb_input_detach(port->input[0]); + dvb_input_detach(port->input[1]); + break; + case DDB_PORT_CI: +- dvb_unregister_device(port->output->dev); ++ case DDB_PORT_LOOP: ++ if (port->dvb[0].dev) ++ dvb_unregister_device(port->dvb[0].dev); + if (port->en) { +- ddb_input_stop(port->input[0]); +- ddb_output_stop(port->output); + dvb_ca_en50221_release(port->en); + kfree(port->en); +- port->en = NULL; +- dvb_unregister_adapter(&port->output->adap); ++ port->en = 0; + } + break; ++ case DDB_PORT_MOD: ++ if (port->dvb[0].dev) ++ dvb_unregister_device(port->dvb[0].dev); ++ break; + } + } ++ dvb_unregister_adapters(dev); + } + +-/****************************************************************************/ +-/****************************************************************************/ + +-static int port_has_ci(struct ddb_port *port) ++/* Copy input DMA pointers to output DMA and ACK. */ ++ ++static void input_write_output(struct ddb_input *input, ++ struct ddb_output *output) + { +- u8 val; +- return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1; ++ ddbwritel(output->port->dev, ++ input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); ++ output->dma->cbuf = (input->dma->stat >> 11) & 0x1f; ++ output->dma->coff = (input->dma->stat & 0x7ff) << 7; + } + +-static int port_has_stv0900(struct ddb_port *port) ++static void output_ack_input(struct ddb_output *output, ++ struct ddb_input *input) + { +- u8 val; +- if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) +- return 0; +- return 1; ++ ddbwritel(input->port->dev, ++ output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); + } + +-static int port_has_stv0900_aa(struct ddb_port *port) ++static void input_write_dvb(struct ddb_input *input, ++ struct ddb_input *input2) + { +- u8 val; +- if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0) +- return 0; +- return 1; ++ struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1]; ++ struct ddb_dma *dma, *dma2; ++ struct ddb *dev = input->port->dev; ++ int noack = 0; ++ ++ dma = dma2 = input->dma; ++ /* if there also is an output connected, do not ACK. ++ input_write_output will ACK. */ ++ if (input->redo) { ++ dma2 = input->redo->dma; ++ noack = 1; ++ } ++ while (dma->cbuf != ((dma->stat >> 11) & 0x1f) ++ || (4 & dma->ctrl)) { ++ if (4 & dma->ctrl) { ++ /*pr_err("Overflow dma %d\n", dma->nr);*/ ++ if (noack) ++ noack = 0; ++ } ++#ifdef DDB_ALT_DMA ++ dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], ++ dma2->size, DMA_FROM_DEVICE); ++#endif ++ dvb_dmx_swfilter_packets(&dvb->demux, ++ dma2->vbuf[dma->cbuf], ++ dma2->size / 188); ++ dma->cbuf = (dma->cbuf + 1) % dma2->num; ++ if (!noack) ++ ddbwritel(dev, (dma->cbuf << 11), ++ DMA_BUFFER_ACK(dma->nr)); ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); ++ } + } + +-static int port_has_drxks(struct ddb_port *port) ++#ifdef DDB_USE_WORK ++static void input_work(struct work_struct *work) + { +- u8 val; +- if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) +- return 0; +- if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) +- return 0; +- return 1; ++ struct ddb_dma *dma = container_of(work, struct ddb_dma, work); ++ struct ddb_input *input = (struct ddb_input *) dma->io; ++#else ++static void input_tasklet(unsigned long data) ++{ ++ struct ddb_input *input = (struct ddb_input *) data; ++ struct ddb_dma *dma = input->dma; ++#endif ++ struct ddb *dev = input->port->dev; ++ ++ spin_lock(&dma->lock); ++ if (!dma->running) { ++ spin_unlock(&dma->lock); ++ return; ++ } ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); ++ ++#if 0 ++ if (4 & dma->ctrl) ++ pr_err("Overflow dma %d\n", dma->nr); ++#endif ++ if (input->redi) ++ input_write_dvb(input, input->redi); ++ if (input->redo) ++ input_write_output(input, input->redo); ++ wake_up(&dma->wq); ++ spin_unlock(&dma->lock); + } + +-static void ddb_port_probe(struct ddb_port *port) ++static void input_handler(unsigned long data) + { +- struct ddb *dev = port->dev; +- char *modname = "NO MODULE"; ++ struct ddb_input *input = (struct ddb_input *) data; ++ struct ddb_dma *dma = input->dma; + +- port->class = DDB_PORT_NONE; + +- if (port_has_ci(port)) { +- modname = "CI"; +- port->class = DDB_PORT_CI; +- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); +- } else if (port_has_stv0900(port)) { +- modname = "DUAL DVB-S2"; +- port->class = DDB_PORT_TUNER; +- port->type = DDB_TUNER_DVBS_ST; +- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); +- } else if (port_has_stv0900_aa(port)) { +- modname = "DUAL DVB-S2"; +- port->class = DDB_PORT_TUNER; +- port->type = DDB_TUNER_DVBS_ST_AA; +- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); +- } else if (port_has_drxks(port)) { +- modname = "DUAL DVB-C/T"; +- port->class = DDB_PORT_TUNER; +- port->type = DDB_TUNER_DVBCT_TR; +- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ /* If there is no input connected, input_tasklet() will ++ just copy pointers and ACK. So, there is no need to go ++ through the tasklet scheduler. */ ++#ifdef DDB_USE_WORK ++ if (input->redi) ++ queue_work(ddb_wq, &dma->work); ++ else ++ input_work(&dma->work); ++#else ++ if (input->redi) ++ tasklet_schedule(&dma->tasklet); ++ else ++ input_tasklet(data); ++#endif ++} ++ ++/* hmm, don't really need this anymore. ++ The output IRQ just copies some pointers, acks and wakes. */ ++ ++#ifdef DDB_USE_WORK ++static void output_work(struct work_struct *work) ++{ ++} ++#else ++static void output_tasklet(unsigned long data) ++{ ++} ++#endif ++ ++static void output_handler(unsigned long data) ++{ ++ struct ddb_output *output = (struct ddb_output *) data; ++ struct ddb_dma *dma = output->dma; ++ struct ddb *dev = output->port->dev; ++ ++ spin_lock(&dma->lock); ++ if (!dma->running) { ++ spin_unlock(&dma->lock); ++ return; ++ } ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); ++ if (output->redi) ++ output_ack_input(output, output->redi); ++ wake_up(&dma->wq); ++ spin_unlock(&dma->lock); ++} ++ ++ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++ ++static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out) ++{ ++#ifndef DDB_USE_WORK ++ unsigned long priv = (unsigned long) io; ++#endif ++ ++ dma->io = io; ++ dma->nr = nr; ++ spin_lock_init(&dma->lock); ++ init_waitqueue_head(&dma->wq); ++ if (out) { ++#ifdef DDB_USE_WORK ++ INIT_WORK(&dma->work, output_work); ++#else ++ tasklet_init(&dma->tasklet, output_tasklet, priv); ++#endif ++ dma->num = OUTPUT_DMA_BUFS; ++ dma->size = OUTPUT_DMA_SIZE; ++ dma->div = OUTPUT_DMA_IRQ_DIV; ++ } else { ++#ifdef DDB_USE_WORK ++ INIT_WORK(&dma->work, input_work); ++#else ++ tasklet_init(&dma->tasklet, input_tasklet, priv); ++#endif ++ dma->num = INPUT_DMA_BUFS; ++ dma->size = INPUT_DMA_SIZE; ++ dma->div = INPUT_DMA_IRQ_DIV; + } +- printk(KERN_INFO "Port %d (TAB %d): %s\n", +- port->nr, port->nr+1, modname); + } + +-static void ddb_input_init(struct ddb_port *port, int nr) ++static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int dma_nr) + { + struct ddb *dev = port->dev; + struct ddb_input *input = &dev->input[nr]; + ++ if (dev->has_dma) { ++ dev->handler[dma_nr + 8] = input_handler; ++ dev->handler_data[dma_nr + 8] = (unsigned long) input; ++ } ++ port->input[pnr] = input; + input->nr = nr; + input->port = port; +- input->dma_buf_num = INPUT_DMA_BUFS; +- input->dma_buf_size = INPUT_DMA_SIZE; +- ddbwritel(0, TS_INPUT_CONTROL(nr)); +- ddbwritel(2, TS_INPUT_CONTROL(nr)); +- ddbwritel(0, TS_INPUT_CONTROL(nr)); +- ddbwritel(0, DMA_BUFFER_ACK(nr)); +- tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input); +- spin_lock_init(&input->lock); +- init_waitqueue_head(&input->wq); ++ if (dev->has_dma) { ++ input->dma = &dev->dma[dma_nr]; ++ ddb_dma_init(input->dma, dma_nr, (void *) input, 0); ++ } ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); ++ ddbwritel(dev, 2, TS_INPUT_CONTROL(nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); ++ if (dev->has_dma) ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); + } + +-static void ddb_output_init(struct ddb_port *port, int nr) ++static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr) + { + struct ddb *dev = port->dev; + struct ddb_output *output = &dev->output[nr]; ++ ++ if (dev->has_dma) { ++ dev->handler[dma_nr + 8] = output_handler; ++ dev->handler_data[dma_nr + 8] = (unsigned long) output; ++ } ++ port->output = output; + output->nr = nr; + output->port = port; +- output->dma_buf_num = OUTPUT_DMA_BUFS; +- output->dma_buf_size = OUTPUT_DMA_SIZE; +- +- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); +- ddbwritel(2, TS_OUTPUT_CONTROL(nr)); +- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); +- tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output); +- init_waitqueue_head(&output->wq); ++ if (dev->has_dma) { ++ output->dma = &dev->dma[dma_nr]; ++ ddb_dma_init(output->dma, dma_nr, (void *) output, 1); ++ } ++ if (output->port->class == DDB_PORT_MOD) { ++ /*ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));*/ ++ } else { ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); ++ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr)); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); ++ } ++ if (dev->has_dma) ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); + } + + static void ddb_ports_init(struct ddb *dev) +@@ -1237,20 +2515,53 @@ static void ddb_ports_init(struct ddb *dev) + int i; + struct ddb_port *port; + ++ if (dev->info->board_control) { ++ ddbwritel(dev, 0, BOARD_CONTROL); ++ msleep(100); ++ ddbwritel(dev, 4, BOARD_CONTROL); ++ usleep_range(2000, 3000); ++ ddbwritel(dev, 4 | dev->info->board_control, BOARD_CONTROL); ++ usleep_range(2000, 3000); ++ } ++ + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; + port->dev = dev; + port->nr = i; +- port->i2c = &dev->i2c[i]; +- port->input[0] = &dev->input[2 * i]; +- port->input[1] = &dev->input[2 * i + 1]; +- port->output = &dev->output[i]; +- ++ if (dev->info->i2c_num > i) ++ port->i2c = &dev->i2c[i]; ++ port->gap = 4; ++ port->obr = ci_bitrate; + mutex_init(&port->i2c_gate_lock); + ddb_port_probe(port); +- ddb_input_init(port, 2 * i); +- ddb_input_init(port, 2 * i + 1); +- ddb_output_init(port, i); ++ pr_info("Port %d (TAB %d): %s\n", ++ port->nr, port->nr + 1, port->name); ++ ++ port->dvb[0].adap = &dev->adap[2 * i]; ++ port->dvb[1].adap = &dev->adap[2 * i + 1]; ++ ++ if ((dev->info->type == DDB_OCTOPUS_CI) || ++ (dev->info->type == DDB_OCTONET) || ++ (dev->info->type == DDB_OCTOPUS)) { ++ if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) { ++ ddb_input_init(port, 2 + i, 0, 2 + i); ++ ddb_input_init(port, 4 + i, 1, 4 + i); ++ } else { ++ ddb_input_init(port, 2 * i, 0, 2 * i); ++ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1); ++ } ++ ddb_output_init(port, i, i + 8); ++ } ++ if (dev->info->type == DDB_OCTOPUS_MAX) { ++ ddb_input_init(port, 2 * i, 0, 2 * i); ++ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1); ++ } ++ if (dev->info->type == DDB_MOD) { ++ ddb_output_init(port, i, i); ++ dev->handler[i + 18] = ddbridge_mod_rate_handler; ++ dev->handler_data[i + 18] = ++ (unsigned long) &dev->output[i]; ++ } + } + } + +@@ -1259,12 +2570,25 @@ static void ddb_ports_release(struct ddb *dev) + int i; + struct ddb_port *port; + ++ if (!dev->has_dma) ++ return; + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; +- port->dev = dev; +- tasklet_kill(&port->input[0]->tasklet); +- tasklet_kill(&port->input[1]->tasklet); +- tasklet_kill(&port->output->tasklet); ++#ifdef DDB_USE_WORK ++ if (port->input[0]) ++ cancel_work_sync(&port->input[0]->dma->work); ++ if (port->input[1]) ++ cancel_work_sync(&port->input[1]->dma->work); ++ if (port->output) ++ cancel_work_sync(&port->output->dma->work); ++#else ++ if (port->input[0]) ++ tasklet_kill(&port->input[0]->dma->tasklet); ++ if (port->input[1]) ++ tasklet_kill(&port->input[1]->dma->tasklet); ++ if (port->output) ++ tasklet_kill(&port->output->dma->tasklet); ++#endif + } + } + +@@ -1272,90 +2596,306 @@ static void ddb_ports_release(struct ddb *dev) + /****************************************************************************/ + /****************************************************************************/ + +-static void irq_handle_i2c(struct ddb *dev, int n) ++#define IRQ_HANDLE(_nr) \ ++ do { if ((s & (1UL << _nr)) && dev->handler[_nr]) \ ++ dev->handler[_nr](dev->handler_data[_nr]); } \ ++ while (0) ++ ++static void irq_handle_msg(struct ddb *dev, u32 s) ++{ ++ dev->i2c_irq++; ++ IRQ_HANDLE(0); ++ IRQ_HANDLE(1); ++ IRQ_HANDLE(2); ++ IRQ_HANDLE(3); ++} ++ ++static void irq_handle_io(struct ddb *dev, u32 s) ++{ ++ dev->ts_irq++; ++ IRQ_HANDLE(8); ++ IRQ_HANDLE(9); ++ IRQ_HANDLE(10); ++ IRQ_HANDLE(11); ++ IRQ_HANDLE(12); ++ IRQ_HANDLE(13); ++ IRQ_HANDLE(14); ++ IRQ_HANDLE(15); ++ IRQ_HANDLE(16); ++ IRQ_HANDLE(17); ++ IRQ_HANDLE(18); ++ IRQ_HANDLE(19); ++ if (dev->info->type != DDB_MOD) ++ return; ++ IRQ_HANDLE(20); ++ IRQ_HANDLE(21); ++ IRQ_HANDLE(22); ++ IRQ_HANDLE(23); ++ IRQ_HANDLE(24); ++ IRQ_HANDLE(25); ++ IRQ_HANDLE(26); ++ IRQ_HANDLE(27); ++} ++ ++static irqreturn_t irq_handler0(int irq, void *dev_id) + { +- struct ddb_i2c *i2c = &dev->i2c[n]; ++ struct ddb *dev = (struct ddb *) dev_id; ++ u32 s = ddbreadl(dev, INTERRUPT_STATUS); ++ ++ do { ++ if (s & 0x80000000) ++ return IRQ_NONE; ++ if (!(s & 0xfff00)) ++ return IRQ_NONE; ++ ddbwritel(dev, s, INTERRUPT_ACK); ++ irq_handle_io(dev, s); ++ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t irq_handler1(int irq, void *dev_id) ++{ ++ struct ddb *dev = (struct ddb *) dev_id; ++ u32 s = ddbreadl(dev, INTERRUPT_STATUS); ++ ++ do { ++ if (s & 0x80000000) ++ return IRQ_NONE; ++ if (!(s & 0x0000f)) ++ return IRQ_NONE; ++ ddbwritel(dev, s, INTERRUPT_ACK); ++ irq_handle_msg(dev, s); ++ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); + +- i2c->done = 1; +- wake_up(&i2c->wq); ++ return IRQ_HANDLED; + } + + static irqreturn_t irq_handler(int irq, void *dev_id) + { + struct ddb *dev = (struct ddb *) dev_id; +- u32 s = ddbreadl(INTERRUPT_STATUS); ++ u32 s = ddbreadl(dev, INTERRUPT_STATUS); ++ int ret = IRQ_HANDLED; + + if (!s) + return IRQ_NONE; +- + do { +- ddbwritel(s, INTERRUPT_ACK); +- +- if (s & 0x00000001) +- irq_handle_i2c(dev, 0); +- if (s & 0x00000002) +- irq_handle_i2c(dev, 1); +- if (s & 0x00000004) +- irq_handle_i2c(dev, 2); +- if (s & 0x00000008) +- irq_handle_i2c(dev, 3); +- +- if (s & 0x00000100) +- tasklet_schedule(&dev->input[0].tasklet); +- if (s & 0x00000200) +- tasklet_schedule(&dev->input[1].tasklet); +- if (s & 0x00000400) +- tasklet_schedule(&dev->input[2].tasklet); +- if (s & 0x00000800) +- tasklet_schedule(&dev->input[3].tasklet); +- if (s & 0x00001000) +- tasklet_schedule(&dev->input[4].tasklet); +- if (s & 0x00002000) +- tasklet_schedule(&dev->input[5].tasklet); +- if (s & 0x00004000) +- tasklet_schedule(&dev->input[6].tasklet); +- if (s & 0x00008000) +- tasklet_schedule(&dev->input[7].tasklet); +- +- if (s & 0x00010000) +- tasklet_schedule(&dev->output[0].tasklet); +- if (s & 0x00020000) +- tasklet_schedule(&dev->output[1].tasklet); +- if (s & 0x00040000) +- tasklet_schedule(&dev->output[2].tasklet); +- if (s & 0x00080000) +- tasklet_schedule(&dev->output[3].tasklet); +- +- /* if (s & 0x000f0000) printk(KERN_DEBUG "%08x\n", istat); */ +- } while ((s = ddbreadl(INTERRUPT_STATUS))); ++ if (s & 0x80000000) ++ return IRQ_NONE; ++ ddbwritel(dev, s, INTERRUPT_ACK); ++ ++ if (s & 0x0000000f) ++ irq_handle_msg(dev, s); ++ if (s & 0x0fffff00) { ++ irq_handle_io(dev, s); ++#ifdef DDB_TEST_THREADED ++ ret = IRQ_WAKE_THREAD; ++#endif ++ } ++ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); ++ ++ return ret; ++} ++ ++#ifdef DDB_TEST_THREADED ++static irqreturn_t irq_thread(int irq, void *dev_id) ++{ ++ /* struct ddb *dev = (struct ddb *) dev_id; */ ++ ++ /*pr_info("%s\n", __func__);*/ + + return IRQ_HANDLED; + } ++#endif ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++#ifdef DVB_NSD ++ ++static ssize_t nsd_read(struct file *file, char *buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} + +-/******************************************************************************/ +-/******************************************************************************/ +-/******************************************************************************/ ++static unsigned int nsd_poll(struct file *file, poll_table *wait) ++{ ++ return 0; ++} ++ ++static int nsd_release(struct inode *inode, struct file *file) ++{ ++ return dvb_generic_release(inode, file); ++} ++ ++static int nsd_open(struct inode *inode, struct file *file) ++{ ++ return dvb_generic_open(inode, file); ++} ++ ++static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb *dev = dvbdev->priv; ++ ++ /* unsigned long arg = (unsigned long) parg; */ ++ int ret = 0; ++ ++ switch (cmd) { ++ case NSD_START_GET_TS: ++ { ++ struct dvb_nsd_ts *ts = parg; ++ u32 ctrl = ((ts->input & 7) << 8) | ++ ((ts->filter_mask & 3) << 2); ++ u32 to; ++ ++ if (ddbreadl(dev, TS_CAPTURE_CONTROL) & 1) { ++ pr_info("ts capture busy\n"); ++ return -EBUSY; ++ } ++ ddb_dvb_input_start(&dev->input[ts->input & 7]); ++ ++ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); ++ ddbwritel(dev, ts->pid, TS_CAPTURE_PID); ++ ddbwritel(dev, (ts->section_id << 16) | ++ (ts->table << 8) | ts->section, ++ TS_CAPTURE_TABLESECTION); ++ /* 1024 ms default timeout if timeout set to 0 */ ++ if (ts->timeout) ++ to = ts->timeout; ++ else ++ to = 1024; ++ /* 21 packets default if num set to 0 */ ++ if (ts->num) ++ to |= ((u32) ts->num << 16); ++ else ++ to |= (21 << 16); ++ ddbwritel(dev, to, TS_CAPTURE_TIMEOUT); ++ if (ts->mode) ++ ctrl |= 2; ++ ddbwritel(dev, ctrl | 1, TS_CAPTURE_CONTROL); ++ break; ++ } ++ case NSD_POLL_GET_TS: ++ { ++ struct dvb_nsd_ts *ts = parg; ++ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); ++ ++ if (ctrl & 1) ++ return -EBUSY; ++ if (ctrl & (1 << 14)) { ++ /*pr_info("ts capture timeout\n");*/ ++ return -EAGAIN; ++ } ++ ddbcpyfrom(dev, dev->tsbuf, TS_CAPTURE_MEMORY, ++ TS_CAPTURE_LEN); ++ ts->len = ddbreadl(dev, TS_CAPTURE_RECEIVED) & 0x1fff; ++ if (copy_to_user(ts->ts, dev->tsbuf, ts->len)) ++ return -EIO; ++ break; ++ } ++ case NSD_CANCEL_GET_TS: ++ { ++ u32 ctrl = 0; ++ pr_info("cancel ts capture: 0x%x\n", ctrl); ++ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); ++ ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); ++ /*pr_info("control register is 0x%x\n", ctrl);*/ ++ break; ++ } ++ case NSD_STOP_GET_TS: ++ { ++ struct dvb_nsd_ts *ts = parg; ++ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); ++ ++ if (ctrl & 1) { ++ pr_info("cannot stop ts capture, while it was neither finished not canceled\n"); ++ return -EBUSY; ++ } ++ /*pr_info("ts capture stopped\n");*/ ++ ddb_dvb_input_stop(&dev->input[ts->input & 7]); ++ break; ++ } ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++static long nsd_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return dvb_usercopy(file, cmd, arg, nsd_do_ioctl); ++} ++ ++static const struct file_operations nsd_fops = { ++ .owner = THIS_MODULE, ++ .read = nsd_read, ++ .open = nsd_open, ++ .release = nsd_release, ++ .poll = nsd_poll, ++ .unlocked_ioctl = nsd_ioctl, ++}; ++ ++static struct dvb_device dvbdev_nsd = { ++ .priv = 0, ++ .readers = 1, ++ .writers = 1, ++ .users = 1, ++ .fops = &nsd_fops, ++}; ++ ++static int ddb_nsd_attach(struct ddb *dev) ++{ ++ int ret; ++ ++ ret = dvb_register_device(&dev->adap[0], ++ &dev->nsd_dev, ++ &dvbdev_nsd, (void *) dev, ++ DVB_DEVICE_NSD); ++ return ret; ++} ++ ++static void ddb_nsd_detach(struct ddb *dev) ++{ ++ if (dev->nsd_dev->users > 2) { ++ wait_event(dev->nsd_dev->wait_queue, ++ dev->nsd_dev->users == 2); ++ } ++ dvb_unregister_device(dev->nsd_dev); ++} ++ ++#endif ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ + + static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) + { + u32 data, shift; + + if (wlen > 4) +- ddbwritel(1, SPI_CONTROL); ++ ddbwritel(dev, 1, SPI_CONTROL); + while (wlen > 4) { + /* FIXME: check for big-endian */ + data = swab32(*(u32 *)wbuf); + wbuf += 4; + wlen -= 4; +- ddbwritel(data, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, data, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + } + + if (rlen) +- ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); ++ ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), ++ SPI_CONTROL); + else +- ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); ++ ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), ++ SPI_CONTROL); + + data = 0; + shift = ((4 - wlen) * 8); +@@ -1367,33 +2907,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) + } + if (shift) + data <<= shift; +- ddbwritel(data, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, data, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + + if (!rlen) { +- ddbwritel(0, SPI_CONTROL); ++ ddbwritel(dev, 0, SPI_CONTROL); + return 0; + } + if (rlen > 4) +- ddbwritel(1, SPI_CONTROL); ++ ddbwritel(dev, 1, SPI_CONTROL); + + while (rlen > 4) { +- ddbwritel(0xffffffff, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, 0xffffffff, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; +- data = ddbreadl(SPI_DATA); ++ data = ddbreadl(dev, SPI_DATA); + *(u32 *) rbuf = swab32(data); + rbuf += 4; + rlen -= 4; + } +- ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); +- ddbwritel(0xffffffff, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); ++ ddbwritel(dev, 0xffffffff, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + +- data = ddbreadl(SPI_DATA); +- ddbwritel(0, SPI_CONTROL); ++ data = ddbreadl(dev, SPI_DATA); ++ ddbwritel(dev, 0, SPI_CONTROL); + + if (rlen < 4) + data <<= ((4 - rlen) * 8); +@@ -1407,28 +2947,107 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) + return 0; + } + ++int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len) ++{ ++ u8 cmd[4] = {0x03, (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, addr & 0xff}; ++ ++ return flashio(dev, cmd, 4, buf, len); ++} ++ ++static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val) ++{ ++ ddbwritel(dev, adr, MDIO_ADR); ++ ddbwritel(dev, reg, MDIO_REG); ++ ddbwritel(dev, val, MDIO_VAL); ++ ddbwritel(dev, 0x03, MDIO_CTRL); ++ while (ddbreadl(dev, MDIO_CTRL) & 0x02) ++ ndelay(500); ++ return 0; ++} ++ ++static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg) ++{ ++ ddbwritel(dev, adr, MDIO_ADR); ++ ddbwritel(dev, reg, MDIO_REG); ++ ddbwritel(dev, 0x07, MDIO_CTRL); ++ while (ddbreadl(dev, MDIO_CTRL) & 0x02) ++ ndelay(500); ++ return ddbreadl(dev, MDIO_VAL); ++} ++ + #define DDB_MAGIC 'd' + + struct ddb_flashio { +- __user __u8 *write_buf; ++ __u8 *write_buf; + __u32 write_len; +- __user __u8 *read_buf; ++ __u8 *read_buf; + __u32 read_len; + }; + +-#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) ++struct ddb_gpio { ++ __u32 mask; ++ __u32 data; ++}; ++ ++struct ddb_id { ++ __u16 vendor; ++ __u16 device; ++ __u16 subvendor; ++ __u16 subdevice; ++ __u32 hw; ++ __u32 regmap; ++}; ++ ++struct ddb_reg { ++ __u32 reg; ++ __u32 val; ++}; ++ ++struct ddb_mem { ++ __u32 off; ++ __u8 *buf; ++ __u32 len; ++}; ++ ++struct ddb_mdio { ++ __u8 adr; ++ __u8 reg; ++ __u16 val; ++}; ++ ++#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) ++#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) ++#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) ++#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id) ++#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) ++#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg) ++#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) ++#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem) ++#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) ++#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) + + #define DDB_NAME "ddbridge" + + static u32 ddb_num; +-static struct ddb *ddbs[32]; +-static struct class *ddb_class; + static int ddb_major; ++static DEFINE_MUTEX(ddb_mutex); ++ ++static int ddb_release(struct inode *inode, struct file *file) ++{ ++ struct ddb *dev = file->private_data; ++ ++ dev->ddb_dev_users--; ++ return 0; ++} + + static int ddb_open(struct inode *inode, struct file *file) + { + struct ddb *dev = ddbs[iminor(inode)]; + ++ if (dev->ddb_dev_users) ++ return -EBUSY; ++ dev->ddb_dev_users++; + file->private_data = dev; + return 0; + } +@@ -1436,7 +3055,7 @@ static int ddb_open(struct inode *inode, struct file *file) + static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + struct ddb *dev = file->private_data; +- __user void *parg = (__user void *)arg; ++ void *parg = (void *)arg; + int res; + + switch (cmd) { +@@ -1447,7 +3066,6 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + if (copy_from_user(&fio, parg, sizeof(fio))) + return -EFAULT; +- + if (fio.write_len > 1028 || fio.read_len > 1028) + return -EINVAL; + if (fio.write_len + fio.read_len > 1028) +@@ -1465,6 +3083,107 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return -EFAULT; + break; + } ++ case IOCTL_DDB_GPIO_OUT: ++ { ++ struct ddb_gpio gpio; ++ if (copy_from_user(&gpio, parg, sizeof(gpio))) ++ return -EFAULT; ++ ddbwritel(dev, gpio.mask, GPIO_DIRECTION); ++ ddbwritel(dev, gpio.data, GPIO_OUTPUT); ++ break; ++ } ++ case IOCTL_DDB_ID: ++ { ++ struct ddb_id ddbid; ++ ++ ddbid.vendor = dev->ids.vendor; ++ ddbid.device = dev->ids.device; ++ ddbid.subvendor = dev->ids.subvendor; ++ ddbid.subdevice = dev->ids.subdevice; ++ ddbid.hw = ddbreadl(dev, 0); ++ ddbid.regmap = ddbreadl(dev, 4); ++ if (copy_to_user(parg, &ddbid, sizeof(ddbid))) ++ return -EFAULT; ++ break; ++ } ++ case IOCTL_DDB_READ_REG: ++ { ++ struct ddb_reg reg; ++ ++ if (copy_from_user(®, parg, sizeof(reg))) ++ return -EFAULT; ++ if (reg.reg >= dev->regs_len) ++ return -EINVAL; ++ reg.val = ddbreadl(dev, reg.reg); ++ if (copy_to_user(parg, ®, sizeof(reg))) ++ return -EFAULT; ++ break; ++ } ++ case IOCTL_DDB_WRITE_REG: ++ { ++ struct ddb_reg reg; ++ ++ if (copy_from_user(®, parg, sizeof(reg))) ++ return -EFAULT; ++ if (reg.reg >= dev->regs_len) ++ return -EINVAL; ++ ddbwritel(dev, reg.val, reg.reg); ++ break; ++ } ++ case IOCTL_DDB_READ_MDIO: ++ { ++ struct ddb_mdio mdio; ++ ++ if (!dev->info->mdio_num) ++ return -EIO; ++ if (copy_from_user(&mdio, parg, sizeof(mdio))) ++ return -EFAULT; ++ mdio.val = mdio_read(dev, mdio.adr, mdio.reg); ++ if (copy_to_user(parg, &mdio, sizeof(mdio))) ++ return -EFAULT; ++ break; ++ } ++ case IOCTL_DDB_WRITE_MDIO: ++ { ++ struct ddb_mdio mdio; ++ ++ if (!dev->info->mdio_num) ++ return -EIO; ++ if (copy_from_user(&mdio, parg, sizeof(mdio))) ++ return -EFAULT; ++ mdio_write(dev, mdio.adr, mdio.reg, mdio.val); ++ break; ++ } ++ case IOCTL_DDB_READ_MEM: ++ { ++ struct ddb_mem mem; ++ u8 *buf = &dev->iobuf[0]; ++ ++ if (copy_from_user(&mem, parg, sizeof(mem))) ++ return -EFAULT; ++ if ((mem.len + mem.off > dev->regs_len) || ++ mem.len > 1024) ++ return -EINVAL; ++ ddbcpyfrom(dev, buf, mem.off, mem.len); ++ if (copy_to_user(mem.buf, buf, mem.len)) ++ return -EFAULT; ++ break; ++ } ++ case IOCTL_DDB_WRITE_MEM: ++ { ++ struct ddb_mem mem; ++ u8 *buf = &dev->iobuf[0]; ++ ++ if (copy_from_user(&mem, parg, sizeof(mem))) ++ return -EFAULT; ++ if ((mem.len + mem.off > dev->regs_len) || ++ mem.len > 1024) ++ return -EINVAL; ++ if (copy_from_user(buf, mem.buf, mem.len)) ++ return -EFAULT; ++ ddbcpyto(dev, mem.off, buf, mem.len); ++ break; ++ } + default: + return -ENOTTY; + } +@@ -1474,284 +3193,508 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + static const struct file_operations ddb_fops = { + .unlocked_ioctl = ddb_ioctl, + .open = ddb_open, ++ .release = ddb_release, + }; + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++static char *ddb_devnode(struct device *device, mode_t *mode) ++#else + static char *ddb_devnode(struct device *device, umode_t *mode) ++#endif + { + struct ddb *dev = dev_get_drvdata(device); + + return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); + } + +-static int ddb_class_create(void) +-{ +- ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); +- if (ddb_major < 0) +- return ddb_major; ++#define __ATTR_MRO(_name, _show) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = _show, \ ++} + +- ddb_class = class_create(THIS_MODULE, DDB_NAME); +- if (IS_ERR(ddb_class)) { +- unregister_chrdev(ddb_major, DDB_NAME); +- return PTR_ERR(ddb_class); +- } +- ddb_class->devnode = ddb_devnode; +- return 0; ++#define __ATTR_MWO(_name, _store) { \ ++ .attr = { .name = __stringify(_name), .mode = 0222 }, \ ++ .store = _store, \ + } + +-static void ddb_class_destroy(void) ++static ssize_t ports_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- class_destroy(ddb_class); +- unregister_chrdev(ddb_major, DDB_NAME); ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->info->port_num); + } + +-static int ddb_device_create(struct ddb *dev) ++static ssize_t ts_irq_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- dev->nr = ddb_num++; +- dev->ddb_dev = device_create(ddb_class, NULL, +- MKDEV(ddb_major, dev->nr), +- dev, "ddbridge%d", dev->nr); +- ddbs[dev->nr] = dev; +- if (IS_ERR(dev->ddb_dev)) +- return -1; +- return 0; ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->ts_irq); + } + +-static void ddb_device_destroy(struct ddb *dev) ++static ssize_t i2c_irq_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- ddb_num--; +- if (IS_ERR(dev->ddb_dev)) +- return; +- device_destroy(ddb_class, MKDEV(ddb_major, 0)); ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->i2c_irq); + } + ++static char *class_name[] = { ++ "NONE", "CI", "TUNER", "LOOP" ++}; + +-/****************************************************************************/ +-/****************************************************************************/ +-/****************************************************************************/ ++static char *type_name[] = { ++ "NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", ++ "DVBCT_ST", "INTERNAL", "CXD2099", "TYPE07", ++ "TYPE08", "TYPE09", "TYPE0A", "TYPE0B", ++ "TYPE0C", "TYPE0D", "TYPE0E", "TYPE0F", ++ "DVBS", "DVBCT2_SONY", "ISDBT_SONY", "DVBC2T2_SONY", ++ "ATSC_ST", "DVBC2T2_ST" ++}; + +-static void ddb_unmap(struct ddb *dev) ++static ssize_t fan_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- if (dev->regs) +- iounmap(dev->regs); +- vfree(dev); ++ struct ddb *dev = dev_get_drvdata(device); ++ u32 val; ++ ++ val = ddbreadl(dev, GPIO_OUTPUT) & 1; ++ return sprintf(buf, "%d\n", val); + } + ++static ssize_t fan_store(struct device *device, struct device_attribute *d, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ unsigned val; ++ ++ if (sscanf(buf, "%u\n", &val) != 1) ++ return -EINVAL; ++ ddbwritel(dev, 1, GPIO_DIRECTION); ++ ddbwritel(dev, val & 1, GPIO_OUTPUT); ++ return count; ++} + +-static void ddb_remove(struct pci_dev *pdev) ++static ssize_t temp_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- struct ddb *dev = pci_get_drvdata(pdev); ++ struct ddb *dev = dev_get_drvdata(device); ++ struct i2c_adapter *adap; ++ int temp, temp2, temp3, i; ++ u8 tmp[2]; + +- ddb_ports_detach(dev); +- ddb_i2c_release(dev); ++ if (dev->info->type == DDB_MOD) { ++ ddbwritel(dev, 1, TEMPMON_CONTROL); ++ for (i = 0; i < 10; i++) { ++ if (0 == (1 & ddbreadl(dev, TEMPMON_CONTROL))) ++ break; ++ usleep_range(1000, 2000); ++ } ++ temp = ddbreadl(dev, TEMPMON_SENSOR1); ++ temp2 = ddbreadl(dev, TEMPMON_SENSOR2); ++ temp = (temp * 1000) >> 8; ++ temp2 = (temp2 * 1000) >> 8; ++ if (ddbreadl(dev, TEMPMON_CONTROL) & 0x8000) { ++ temp3 = ddbreadl(dev, TEMPMON_CORE); ++ temp3 = (temp3 * 1000) >> 8; ++ return sprintf(buf, "%d %d %d\n", temp, temp2, temp3); ++ } ++ return sprintf(buf, "%d %d\n", temp, temp2); ++ } ++ if (!dev->info->temp_num) ++ return sprintf(buf, "no sensor\n"); ++ adap = &dev->i2c[dev->info->temp_bus].adap; ++ if (i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0) ++ return sprintf(buf, "read_error\n"); ++ temp = (tmp[0] << 3) | (tmp[1] >> 5); ++ temp *= 125; ++ if (dev->info->temp_num == 2) { ++ if (i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0) ++ return sprintf(buf, "read_error\n"); ++ temp2 = (tmp[0] << 3) | (tmp[1] >> 5); ++ temp2 *= 125; ++ return sprintf(buf, "%d %d\n", temp, temp2); ++ } ++ return sprintf(buf, "%d\n", temp); ++} + +- ddbwritel(0, INTERRUPT_ENABLE); +- free_irq(dev->pdev->irq, dev); +-#ifdef CONFIG_PCI_MSI +- if (dev->msi) +- pci_disable_msi(dev->pdev); +-#endif +- ddb_ports_release(dev); +- ddb_buffers_free(dev); +- ddb_device_destroy(dev); ++#if 0 ++static ssize_t qam_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ struct i2c_adapter *adap; ++ u8 tmp[4]; ++ s16 i, q; + +- ddb_unmap(dev); +- pci_set_drvdata(pdev, NULL); +- pci_disable_device(pdev); ++ adap = &dev->i2c[1].adap; ++ if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0) ++ return sprintf(buf, "read_error\n"); ++ i = (s16) (((u16) tmp[1]) << 14) | (((u16) tmp[0]) << 6); ++ q = (s16) (((u16) tmp[3]) << 14) | (((u16) tmp[2]) << 6); ++ ++ return sprintf(buf, "%d %d\n", i, q); + } ++#endif ++ ++static ssize_t mod_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; + ++ return sprintf(buf, "%s:%s\n", ++ class_name[dev->port[num].class], ++ type_name[dev->port[num].type]); ++} + +-static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++static ssize_t led_show(struct device *device, ++ struct device_attribute *attr, char *buf) + { +- struct ddb *dev; +- int stat = 0; +- int irq_flag = IRQF_SHARED; ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; + +- if (pci_enable_device(pdev) < 0) +- return -ENODEV; ++ return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); ++} + +- dev = vmalloc(sizeof(struct ddb)); +- if (dev == NULL) +- return -ENOMEM; +- memset(dev, 0, sizeof(struct ddb)); + +- dev->pdev = pdev; +- pci_set_drvdata(pdev, dev); +- dev->info = (struct ddb_info *) id->driver_data; +- printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name); ++static void ddb_set_led(struct ddb *dev, int num, int val) ++{ ++ if (!dev->info->led_num) ++ return; ++ switch (dev->port[num].class) { ++ case DDB_PORT_TUNER: ++ switch (dev->port[num].type) { ++ case DDB_TUNER_DVBS_ST: ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x69, 0xf14c, val ? 2 : 0); ++ break; ++ case DDB_TUNER_DVBCT_ST: ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x1f, 0xf00e, 0); ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x1f, 0xf00f, val ? 1 : 0); ++ break; ++ case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2_ST: ++ { ++ u8 v; + +- dev->regs = ioremap(pci_resource_start(dev->pdev, 0), +- pci_resource_len(dev->pdev, 0)); +- if (!dev->regs) { +- stat = -ENOMEM; +- goto fail; ++ i2c_read_reg(&dev->i2c[num].adap, 0x10, 0x08, &v); ++ v = (v & ~0x10) | (val ? 0x10 : 0); ++ i2c_write_reg(&dev->i2c[num].adap, 0x10, 0x08, v); ++ break; ++ } ++ default: ++ break; ++ } ++ break; + } +- printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); ++} ++ ++static ssize_t led_store(struct device *device, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ unsigned val; ++ ++ if (sscanf(buf, "%u\n", &val) != 1) ++ return -EINVAL; ++ if (val) ++ dev->leds |= (1 << num); ++ else ++ dev->leds &= ~(1 << num); ++ ddb_set_led(dev, num, val); ++ return count; ++} ++ ++static ssize_t snr_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ char snr[32]; ++ int num = attr->attr.name[3] - 0x30; + +-#ifdef CONFIG_PCI_MSI +- if (pci_msi_enabled()) +- stat = pci_enable_msi(dev->pdev); +- if (stat) { +- printk(KERN_INFO ": MSI not available.\n"); ++ if (dev->port[num].type >= DDB_TUNER_XO2) { ++ if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0) ++ return sprintf(buf, "NO SNR\n"); ++ snr[16] = 0; + } else { +- irq_flag = 0; +- dev->msi = 1; ++ /* serial number at 0x100-0x11f */ ++ if (i2c_read_regs16(&dev->i2c[num].adap, ++ 0x50, 0x100, snr, 32) < 0) ++ if (i2c_read_regs16(&dev->i2c[num].adap, ++ 0x57, 0x100, snr, 32) < 0) ++ return sprintf(buf, "NO SNR\n"); ++ snr[31] = 0; /* in case it is not terminated on EEPROM */ + } +-#endif +- stat = request_irq(dev->pdev->irq, irq_handler, +- irq_flag, "DDBridge", (void *) dev); +- if (stat < 0) +- goto fail1; +- ddbwritel(0, DMA_BASE_WRITE); +- ddbwritel(0, DMA_BASE_READ); +- ddbwritel(0xffffffff, INTERRUPT_ACK); +- ddbwritel(0xfff0f, INTERRUPT_ENABLE); +- ddbwritel(0, MSI1_ENABLE); +- +- if (ddb_i2c_init(dev) < 0) +- goto fail1; +- ddb_ports_init(dev); +- if (ddb_buffers_alloc(dev) < 0) { +- printk(KERN_INFO ": Could not allocate buffer memory\n"); +- goto fail2; +- } +- if (ddb_ports_attach(dev) < 0) +- goto fail3; +- ddb_device_create(dev); ++ return sprintf(buf, "%s\n", snr); ++} ++ ++ ++static ssize_t snr_store(struct device *device, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ u8 snr[34] = { 0x01, 0x00 }; ++ ++ if (count > 31) ++ return -EINVAL; ++ if (dev->port[num].type >= DDB_TUNER_XO2) ++ return -EINVAL; ++ memcpy(snr + 2, buf, count); ++ i2c_write(&dev->i2c[num].adap, 0x57, snr, 34); ++ i2c_write(&dev->i2c[num].adap, 0x50, snr, 34); ++ return count; ++} ++ ++static ssize_t bsnr_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ char snr[16]; ++ ++ ddbridge_flashread(dev, snr, 0x10, 15); ++ snr[15] = 0; /* in case it is not terminated on EEPROM */ ++ return sprintf(buf, "%s\n", snr); ++} ++ ++static ssize_t redirect_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ + return 0; ++} + +-fail3: +- ddb_ports_detach(dev); +- printk(KERN_ERR "fail3\n"); +- ddb_ports_release(dev); +-fail2: +- printk(KERN_ERR "fail2\n"); +- ddb_buffers_free(dev); +-fail1: +- printk(KERN_ERR "fail1\n"); +- if (dev->msi) +- pci_disable_msi(dev->pdev); +- free_irq(dev->pdev->irq, dev); +-fail: +- printk(KERN_ERR "fail\n"); +- ddb_unmap(dev); +- pci_set_drvdata(pdev, NULL); +- pci_disable_device(pdev); +- return -1; ++static ssize_t redirect_store(struct device *device, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned int i, p; ++ int res; ++ ++ if (sscanf(buf, "%x %x\n", &i, &p) != 2) ++ return -EINVAL; ++ res = ddb_redirect(i, p); ++ if (res < 0) ++ return res; ++ pr_info("redirect: %02x, %02x\n", i, p); ++ return count; + } + +-/******************************************************************************/ +-/******************************************************************************/ +-/******************************************************************************/ ++static ssize_t gap_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; + +-static struct ddb_info ddb_none = { +- .type = DDB_NONE, +- .name = "Digital Devices PCIe bridge", +-}; ++ return sprintf(buf, "%d\n", dev->port[num].gap); + +-static struct ddb_info ddb_octopus = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Octopus DVB adapter", +- .port_num = 4, +-}; ++} ++static ssize_t gap_store(struct device *device, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ unsigned int val; ++ ++ if (sscanf(buf, "%u\n", &val) != 1) ++ return -EINVAL; ++ if (val > 20) ++ return -EINVAL; ++ dev->port[num].gap = val; ++ return count; ++} + +-static struct ddb_info ddb_octopus_le = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Octopus LE DVB adapter", +- .port_num = 2, +-}; ++static ssize_t version_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); + +-static struct ddb_info ddb_octopus_mini = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Octopus Mini", +- .port_num = 4, +-}; ++ return sprintf(buf, "%08x %08x\n", ++ ddbreadl(dev, 0), ddbreadl(dev, 4)); ++} + +-static struct ddb_info ddb_v6 = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Cine S2 V6 DVB adapter", +- .port_num = 3, +-}; +-static struct ddb_info ddb_v6_5 = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Cine S2 V6.5 DVB adapter", +- .port_num = 4, ++static ssize_t hwid_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "0x%08X\n", dev->ids.hwid); ++} ++ ++static ssize_t regmap_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "0x%08X\n", dev->ids.regmapid); ++} ++ ++static struct device_attribute ddb_attrs[] = { ++ __ATTR_RO(version), ++ __ATTR_RO(ports), ++ __ATTR_RO(ts_irq), ++ __ATTR_RO(i2c_irq), ++ __ATTR(gap0, 0664, gap_show, gap_store), ++ __ATTR(gap1, 0664, gap_show, gap_store), ++ __ATTR(gap2, 0664, gap_show, gap_store), ++ __ATTR(gap3, 0664, gap_show, gap_store), ++ __ATTR_RO(hwid), ++ __ATTR_RO(regmap), ++#if 0 ++ __ATTR_RO(qam), ++#endif ++ __ATTR(redirect, 0664, redirect_show, redirect_store), ++ __ATTR_MRO(snr, bsnr_show), ++ __ATTR_NULL, + }; + +-static struct ddb_info ddb_dvbct = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices DVBCT V6.1 DVB adapter", +- .port_num = 3, ++static struct device_attribute ddb_attrs_temp[] = { ++ __ATTR_RO(temp), + }; + +-static struct ddb_info ddb_satixS2v3 = { +- .type = DDB_OCTOPUS, +- .name = "Mystique SaTiX-S2 V3 DVB adapter", +- .port_num = 3, ++static struct device_attribute ddb_attrs_mod[] = { ++ __ATTR_MRO(mod0, mod_show), ++ __ATTR_MRO(mod1, mod_show), ++ __ATTR_MRO(mod2, mod_show), ++ __ATTR_MRO(mod3, mod_show), ++ __ATTR_MRO(mod4, mod_show), ++ __ATTR_MRO(mod5, mod_show), ++ __ATTR_MRO(mod6, mod_show), ++ __ATTR_MRO(mod7, mod_show), ++ __ATTR_MRO(mod8, mod_show), ++ __ATTR_MRO(mod9, mod_show), + }; + +-static struct ddb_info ddb_octopusv3 = { +- .type = DDB_OCTOPUS, +- .name = "Digital Devices Octopus V3 DVB adapter", +- .port_num = 4, ++static struct device_attribute ddb_attrs_fan[] = { ++ __ATTR(fan, 0664, fan_show, fan_store), + }; + +-#define DDVID 0xdd01 /* Digital Devices Vendor ID */ +- +-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ +- .vendor = _vend, .device = _dev, \ +- .subvendor = _subvend, .subdevice = _subdev, \ +- .driver_data = (unsigned long)&_driverdata } +- +-static const struct pci_device_id ddb_id_tbl[] = { +- DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), +- DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), +- DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), +- /* in case sub-ids got deleted in flash */ +- DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), +- {0} ++static struct device_attribute ddb_attrs_snr[] = { ++ __ATTR(snr0, 0664, snr_show, snr_store), ++ __ATTR(snr1, 0664, snr_show, snr_store), ++ __ATTR(snr2, 0664, snr_show, snr_store), ++ __ATTR(snr3, 0664, snr_show, snr_store), + }; +-MODULE_DEVICE_TABLE(pci, ddb_id_tbl); + ++static struct device_attribute ddb_attrs_led[] = { ++ __ATTR(led0, 0664, led_show, led_store), ++ __ATTR(led1, 0664, led_show, led_store), ++ __ATTR(led2, 0664, led_show, led_store), ++ __ATTR(led3, 0664, led_show, led_store), ++}; + +-static struct pci_driver ddb_pci_driver = { +- .name = "DDBridge", +- .id_table = ddb_id_tbl, +- .probe = ddb_probe, +- .remove = ddb_remove, ++static struct class ddb_class = { ++ .name = "ddbridge", ++ .owner = THIS_MODULE, ++#if 0 ++ .dev_attrs = ddb_attrs, ++#endif ++ .devnode = ddb_devnode, + }; + +-static __init int module_init_ddbridge(void) ++static int ddb_class_create(void) + { +- int ret; ++ ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); ++ if (ddb_major < 0) ++ return ddb_major; ++ if (class_register(&ddb_class) < 0) ++ return -1; ++ return 0; ++} ++ ++static void ddb_class_destroy(void) ++{ ++ class_unregister(&ddb_class); ++ unregister_chrdev(ddb_major, DDB_NAME); ++} + +- printk(KERN_INFO "Digital Devices PCIE bridge driver, " +- "Copyright (C) 2010-11 Digital Devices GmbH\n"); ++static void ddb_device_attrs_del(struct ddb *dev) ++{ ++ int i; + +- ret = ddb_class_create(); +- if (ret < 0) +- return ret; +- ret = pci_register_driver(&ddb_pci_driver); +- if (ret < 0) +- ddb_class_destroy(); +- return ret; ++ for (i = 0; i < dev->info->temp_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]); ++ for (i = 0; i < dev->info->port_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]); ++ for (i = 0; i < dev->info->fan_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_attrs_fan[i]); ++ for (i = 0; i < dev->info->i2c_num; i++) { ++ if (dev->info->led_num) ++ device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]); ++ device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]); ++ } ++ for (i = 0; ddb_attrs[i].attr.name; i++) ++ device_remove_file(dev->ddb_dev, &ddb_attrs[i]); + } + +-static __exit void module_exit_ddbridge(void) ++static int ddb_device_attrs_add(struct ddb *dev) + { +- pci_unregister_driver(&ddb_pci_driver); +- ddb_class_destroy(); ++ int i; ++ ++ for (i = 0; ddb_attrs[i].attr.name; i++) ++ if (device_create_file(dev->ddb_dev, &ddb_attrs[i])) ++ goto fail; ++ for (i = 0; i < dev->info->temp_num; i++) ++ if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i])) ++ goto fail; ++ for (i = 0; i < dev->info->port_num; i++) ++ if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])) ++ goto fail; ++ for (i = 0; i < dev->info->fan_num; i++) ++ if (device_create_file(dev->ddb_dev, &ddb_attrs_fan[i])) ++ goto fail; ++ for (i = 0; i < dev->info->i2c_num; i++) { ++ if (device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])) ++ goto fail; ++ if (dev->info->led_num) ++ if (device_create_file(dev->ddb_dev, ++ &ddb_attrs_led[i])) ++ goto fail; ++ } ++ return 0; ++fail: ++ return -1; + } + +-module_init(module_init_ddbridge); +-module_exit(module_exit_ddbridge); ++static int ddb_device_create(struct ddb *dev) ++{ ++ int res = 0; ++ ++ if (ddb_num == DDB_MAX_ADAPTER) ++ return -ENOMEM; ++ mutex_lock(&ddb_mutex); ++ dev->nr = ddb_num; ++ ddbs[dev->nr] = dev; ++ dev->ddb_dev = device_create(&ddb_class, dev->dev, ++ MKDEV(ddb_major, dev->nr), ++ dev, "ddbridge%d", dev->nr); ++ if (IS_ERR(dev->ddb_dev)) { ++ res = PTR_ERR(dev->ddb_dev); ++ pr_info("Could not create ddbridge%d\n", dev->nr); ++ goto fail; ++ } ++ res = ddb_device_attrs_add(dev); ++ if (res) { ++ ddb_device_attrs_del(dev); ++ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); ++ ddbs[dev->nr] = 0; ++ dev->ddb_dev = ERR_PTR(-ENODEV); ++ } else ++ ddb_num++; ++fail: ++ mutex_unlock(&ddb_mutex); ++ return res; ++} + +-MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); +-MODULE_AUTHOR("Ralph Metzler"); +-MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.5"); ++static void ddb_device_destroy(struct ddb *dev) ++{ ++ if (IS_ERR(dev->ddb_dev)) ++ return; ++ ddb_device_attrs_del(dev); ++ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); ++} +diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c +new file mode 100644 +index 0000000..bd0d9b1 +--- /dev/null ++++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c +@@ -0,0 +1,257 @@ ++/* ++ * ddbridge-i2c.c: Digital Devices bridge i2c driver ++ * ++ * Copyright (C) 2010-2014 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) ++{ ++ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_read_regs(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 *val, u8 len) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_read_regs16(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 *val, u8 len) ++{ ++ u8 reg16[2] = { reg >> 8, reg }; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = reg16, .len = 2 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, ++ u16 reg, u8 val) ++{ ++ u8 msg[3] = {reg >> 8, reg & 0xff, val}; ++ ++ return i2c_write(adap, adr, msg, 3); ++} ++ ++static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, ++ u8 reg, u8 val) ++{ ++ u8 msg[2] = {reg, val}; ++ ++ return i2c_write(adap, adr, msg, 2); ++} ++ ++static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) ++{ ++ struct ddb *dev = i2c->dev; ++ int stat; ++ u32 val; ++ ++ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND); ++ stat = wait_for_completion_timeout(&i2c->completion, HZ); ++ if (stat <= 0) { ++ pr_err("DDBridge I2C timeout, card %d, port %d\n", ++ dev->nr, i2c->nr); ++#ifdef CONFIG_PCI_MSI ++ { /* MSI debugging*/ ++ u32 istat = ddbreadl(dev, INTERRUPT_STATUS); ++ dev_err(dev->dev, "DDBridge IRS %08x\n", istat); ++ ddbwritel(dev, istat, INTERRUPT_ACK); ++ } ++#endif ++ return -EIO; ++ } ++ val = ddbreadl(dev, i2c->regs + I2C_COMMAND); ++ if (val & 0x70000) ++ return -EIO; ++ return 0; ++} ++ ++static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg msg[], int num) ++{ ++ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); ++ struct ddb *dev = i2c->dev; ++ u8 addr = 0; ++ ++ if (num) ++ addr = msg[0].addr; ++ if (num == 2 && msg[1].flags & I2C_M_RD && ++ !(msg[0].flags & I2C_M_RD)) { ++ memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, ++ msg[0].buf, msg[0].len); ++ ddbwritel(dev, msg[0].len|(msg[1].len << 16), ++ i2c->regs + I2C_TASKLENGTH); ++ if (!ddb_i2c_cmd(i2c, addr, 1)) { ++ memcpy_fromio(msg[1].buf, ++ dev->regs + I2C_TASKMEM_BASE + ++ i2c->rbuf, ++ msg[1].len); ++ return num; ++ } ++ } ++ if (num == 1 && !(msg[0].flags & I2C_M_RD)) { ++ ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, ++ msg[0].buf, msg[0].len); ++ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH); ++ if (!ddb_i2c_cmd(i2c, addr, 2)) ++ return num; ++ } ++ if (num == 1 && (msg[0].flags & I2C_M_RD)) { ++ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); ++ if (!ddb_i2c_cmd(i2c, addr, 3)) { ++ ddbcpyfrom(dev, msg[0].buf, ++ I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); ++ return num; ++ } ++ } ++ return -EIO; ++} ++ ++#if 0 ++static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, ++ struct i2c_msg msg[], int num) ++{ ++ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); ++ struct ddb *dev = i2c->dev; ++ int ret; ++ ++ if (dev->info->type != DDB_OCTONET || i2c->nr == 0 || i2c->nr == 3) ++ return ddb_i2c_master_xfer_locked(adapter, msg, num); ++ ++ mutex_lock(&dev->octonet_i2c_lock); ++ ret = ddb_i2c_master_xfer_locked(adapter, msg, num); ++ mutex_unlock(&dev->octonet_i2c_lock); ++ return ret; ++} ++#endif ++ ++static u32 ddb_i2c_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_SMBUS_EMUL; ++} ++ ++struct i2c_algorithm ddb_i2c_algo = { ++ .master_xfer = ddb_i2c_master_xfer, ++ .functionality = ddb_i2c_functionality, ++}; ++ ++static void ddb_i2c_release(struct ddb *dev) ++{ ++ int i; ++ struct ddb_i2c *i2c; ++ struct i2c_adapter *adap; ++ ++ for (i = 0; i < dev->info->i2c_num; i++) { ++ i2c = &dev->i2c[i]; ++ adap = &i2c->adap; ++ i2c_del_adapter(adap); ++ } ++} ++ ++static void i2c_handler(unsigned long priv) ++{ ++ struct ddb_i2c *i2c = (struct ddb_i2c *) priv; ++ ++ complete(&i2c->completion); ++} ++ ++static int ddb_i2c_init(struct ddb *dev) ++{ ++ int i, j, stat = 0; ++ struct ddb_i2c *i2c; ++ struct i2c_adapter *adap; ++ ++ for (i = 0; i < dev->info->i2c_num; i++) { ++ i2c = &dev->i2c[i]; ++ dev->handler[i] = i2c_handler; ++ dev->handler_data[i] = (unsigned long) i2c; ++ i2c->dev = dev; ++ i2c->nr = i; ++ i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); ++ i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); ++ i2c->regs = 0x80 + i * 0x20; ++ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); ++ ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf, ++ i2c->regs + I2C_TASKADDRESS); ++ init_completion(&i2c->completion); ++ ++ adap = &i2c->adap; ++ i2c_set_adapdata(adap, i2c); ++#ifdef I2C_ADAP_CLASS_TV_DIGITAL ++ adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; ++#else ++#ifdef I2C_CLASS_TV_ANALOG ++ adap->class = I2C_CLASS_TV_ANALOG; ++#endif ++#endif ++ strcpy(adap->name, "ddbridge"); ++ adap->algo = &ddb_i2c_algo; ++ adap->algo_data = (void *)i2c; ++ adap->dev.parent = dev->dev; ++ stat = i2c_add_adapter(adap); ++ if (stat) ++ break; ++ } ++ if (stat) ++ for (j = 0; j < i; j++) { ++ i2c = &dev->i2c[j]; ++ adap = &i2c->adap; ++ i2c_del_adapter(adap); ++ } ++ return stat; ++} ++ +diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.h b/drivers/media/pci/ddbridge/ddbridge-i2c.h +new file mode 100644 +index 0000000..4a9bc26 +--- /dev/null ++++ b/drivers/media/pci/ddbridge/ddbridge-i2c.h +@@ -0,0 +1,105 @@ ++/* ++ * ddbridge-i2c.h: Digital Devices bridge i2c driver ++ * ++ * Copyright (C) 2010-2014 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef _DDBRIDGE_I2C_H_ ++#define _DDBRIDGE_I2C_H_ ++ ++#include ++#include ++ ++static inline int i2c_write(struct i2c_adapter *adap, u8 adr, ++ u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ ++static inline int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) ++{ ++ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; ++} ++ ++static inline int i2c_read_regs(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 *val, u8 len) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static inline int i2c_read_regs16(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 *val, u8 len) ++{ ++ u8 reg16[2] = { reg >> 8, reg }; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = reg16, .len = 2 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static inline int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, ++ u8 reg, u8 *val) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, ++ u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1 } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static inline int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, ++ u16 reg, u8 val) ++{ ++ u8 msg[3] = {reg >> 8, reg & 0xff, val}; ++ ++ return i2c_write(adap, adr, msg, 3); ++} ++ ++static inline int i2c_write_reg(struct i2c_adapter *adap, u8 adr, ++ u8 reg, u8 val) ++{ ++ u8 msg[2] = {reg, val}; ++ ++ return i2c_write(adap, adr, msg, 2); ++} ++ ++#endif +diff --git a/drivers/media/pci/ddbridge/ddbridge-mod.c b/drivers/media/pci/ddbridge/ddbridge-mod.c +new file mode 100644 +index 0000000..5a9c866 +--- /dev/null ++++ b/drivers/media/pci/ddbridge/ddbridge-mod.c +@@ -0,0 +1,1148 @@ ++/* ++ * ddbridge.c: Digital Devices PCIe bridge driver ++ * ++ * Copyright (C) 2010-2014 Digital Devices GmbH ++ * Ralph Metzler ++ * Marcus Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include "ddbridge.h" ++#include "ddbridge-regs.h" ++ ++#include ++ ++inline s64 ConvertPCR(s64 a) ++{ ++ s32 ext; ++ s64 b; ++ ++ b = div_s64_rem(a, 300 << 22, &ext); ++ ++ return (b << 31) | ext; ++ ++} ++ ++inline s64 NegConvertPCR(s64 a) ++{ ++ s32 ext; ++ s64 b; ++ ++ b = -div_s64_rem(a, 300 << 22, &ext); ++ ++ if (ext != 0) { ++ ext = (300 << 22) - ext; ++ b -= 1; ++ } ++ return (b << 31) | ext; ++} ++ ++inline s64 RoundPCR(s64 a) ++{ ++ s64 b = a + (HW_LSB_MASK>>1); ++ return b & ~(HW_LSB_MASK - 1); ++} ++ ++inline s64 RoundPCRUp(s64 a) ++{ ++ s64 b = a + (HW_LSB_MASK - 1); ++ return b & ~(HW_LSB_MASK - 1); ++} ++ ++inline s64 RoundPCRDown(s64 a) ++{ ++ return a & ~(HW_LSB_MASK - 1); ++} ++ ++static int mod_busy(struct ddb *dev, int chan) ++{ ++ u32 creg; ++ ++ while (1) { ++ creg = ddbreadl(dev, CHANNEL_CONTROL(chan)); ++ if (creg == 0xffffffff) ++ return -EFAULT; ++ if ((creg & CHANNEL_CONTROL_BUSY) == 0) ++ break; ++ } ++ return 0; ++} ++ ++void ddbridge_mod_output_stop(struct ddb_output *output) ++{ ++ struct ddb *dev = output->port->dev; ++ struct mod_state *mod = &dev->mod[output->nr]; ++ ++ mod->State = CM_IDLE; ++ mod->Control = 0; ++ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); ++#if 0 ++ udelay(10); ++ ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr)); ++ udelay(10); ++ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); ++#endif ++ mod_busy(dev, output->nr); ++ pr_info("mod_output_stop %d.%d\n", dev->nr, output->nr); ++} ++ ++static void mod_set_incs(struct ddb_output *output) ++{ ++ s64 pcr; ++ struct ddb *dev = output->port->dev; ++ struct mod_state *mod = &dev->mod[output->nr]; ++ ++ pcr = ConvertPCR(mod->PCRIncrement); ++ ddbwritel(dev, pcr & 0xffffffff, ++ CHANNEL_PCR_ADJUST_OUTL(output->nr)); ++ ddbwritel(dev, (pcr >> 32) & 0xffffffff, ++ CHANNEL_PCR_ADJUST_OUTH(output->nr)); ++ mod_busy(dev, output->nr); ++ ++ pcr = NegConvertPCR(mod->PCRDecrement); ++ ddbwritel(dev, pcr & 0xffffffff, ++ CHANNEL_PCR_ADJUST_INL(output->nr)); ++ ddbwritel(dev, (pcr >> 32) & 0xffffffff, ++ CHANNEL_PCR_ADJUST_INH(output->nr)); ++ mod_busy(dev, output->nr); ++ ++} ++ ++static void mod_set_rateinc(struct ddb *dev, u32 chan) ++{ ++ ddbwritel(dev, dev->mod[chan].rate_inc, CHANNEL_RATE_INCR(chan)); ++ mod_busy(dev, chan); ++} ++ ++static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 }; ++ ++void ddbridge_mod_output_start(struct ddb_output *output) ++{ ++ struct ddb *dev = output->port->dev; ++ struct mod_state *mod = &dev->mod[output->nr]; ++ ++ /*PCRIncrement = RoundPCR(PCRIncrement);*/ ++ /*PCRDecrement = RoundPCR(PCRDecrement);*/ ++ ++ mod->LastInPacketCount = 0; ++ mod->LastOutPacketCount = 0; ++ mod->InOverflowPacketCount = 0; ++ mod->OutOverflowPacketCount = 0; ++ mod->LastInPackets = 0; ++ mod->LastOutPackets = 0; ++ mod->LastPCRAdjust = 0; ++ mod->PCRRunningCorr = 0; ++ /* we interrupt every 0x80000=524288 packets */ ++ mod->MinInputPackets = 524288 / 2; ++ mod->PCRIncrement = 0; ++ mod->PCRDecrement = 0; ++ ++ mod->State = CM_STARTUP; ++ mod->StateCounter = CM_STARTUP_DELAY; ++ ++ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); ++ udelay(10); ++ ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr)); ++ udelay(10); ++ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); ++ ++ /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ ++ /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ ++ ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr)); ++ ++ mod_set_rateinc(dev, output->nr); ++ mod_set_incs(output); ++ ++ mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | ++ CHANNEL_CONTROL_ENABLE_DVB | ++ CHANNEL_CONTROL_ENABLE_SOURCE); ++ ++ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); ++ pr_info("mod_output_start %d.%d\n", dev->nr, output->nr); ++} ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value) ++{ ++ u32 RegValue = 0; ++ ++ ddbwritel(dev, Value, DAC_WRITE_DATA); ++ ddbwritel(dev, DAC_CONTROL_STARTIO | Index, DAC_CONTROL); ++ do { ++ RegValue = ddbreadl(dev, DAC_CONTROL); ++ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); ++} ++ ++static void mod_write_dac_register2(struct ddb *dev, u8 Index, u16 Value) ++{ ++ u32 RegValue = 0; ++ ++ ddbwritel(dev, Value, DAC_WRITE_DATA); ++ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x20 | Index, DAC_CONTROL); ++ do { ++ RegValue = ddbreadl(dev, DAC_CONTROL); ++ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); ++} ++ ++static int mod_read_dac_register(struct ddb *dev, u8 Index, u8 *pValue) ++{ ++ u32 RegValue = 0; ++ ++ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x80 | Index, DAC_CONTROL); ++ do { ++ RegValue = ddbreadl(dev, DAC_CONTROL); ++ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); ++ ++ RegValue = ddbreadl(dev, DAC_READ_DATA); ++ *pValue = (u8) RegValue; ++ return 0; ++} ++ ++static void mod_set_up_converter_vco1(struct ddb *dev, u32 Value) ++{ ++ u32 RegValue = 0; ++ ++ /* Extra delay before writing N divider */ ++ if ((Value & 0x03) == 0x02) ++ msleep(50); ++ do { ++ RegValue = ddbreadl(dev, VCO1_CONTROL); ++ } while ((RegValue & VCO1_CONTROL_WRITE) != 0); ++ ++ if ((RegValue & VCO1_CONTROL_CE) == 0) { ++ RegValue |= VCO1_CONTROL_CE; ++ ddbwritel(dev, RegValue, VCO1_CONTROL); ++ msleep(20); ++ } ++ ++ ddbwritel(dev, Value, VCO1_DATA); ++ ddbwritel(dev, RegValue | VCO1_CONTROL_WRITE, VCO1_CONTROL); ++} ++ ++static void mod_set_up_converter_vco2(struct ddb *dev, u32 Value) ++{ ++ u32 RegValue = 0; ++ ++ /* Extra delay before writing N divider */ ++ if ((Value & 0x03) == 0x02) ++ msleep(50); ++ do { ++ RegValue = ddbreadl(dev, VCO2_CONTROL); ++ } while ((RegValue & VCO2_CONTROL_WRITE) != 0); ++ ++ if ((RegValue & VCO2_CONTROL_CE) == 0) { ++ RegValue |= VCO2_CONTROL_CE; ++ ddbwritel(dev, RegValue, VCO2_CONTROL); ++ msleep(20); ++ } ++ ++ ddbwritel(dev, Value, VCO2_DATA); ++ ddbwritel(dev, RegValue | VCO2_CONTROL_WRITE, VCO2_CONTROL); ++} ++ ++static void mod_set_down_converter_vco(struct ddb *dev, u32 Value) ++{ ++ u32 RegValue = 0; ++ ++ do { ++ RegValue = ddbreadl(dev, VCO3_CONTROL); ++ } while ((RegValue & VCO3_CONTROL_WRITE) != 0); ++ ++ if ((RegValue & VCO3_CONTROL_CE) == 0) { ++ RegValue |= VCO3_CONTROL_CE; ++ ddbwritel(dev, RegValue, VCO3_CONTROL); ++ msleep(20); ++ } ++ ddbwritel(dev, Value, VCO3_DATA); ++ ddbwritel(dev, RegValue | VCO3_CONTROL_WRITE, VCO3_CONTROL); ++} ++ ++static int mod_set_attenuator(struct ddb *dev, u32 Value) ++{ ++ if (Value > 31) ++ return -EINVAL; ++ ddbwritel(dev, Value, RF_ATTENUATOR); ++ return 0; ++} ++ ++static void mod_si598_readreg(struct ddb *dev, u8 index, u8 *val) ++{ ++ ddbwritel(dev, index, CLOCKGEN_INDEX); ++ ddbwritel(dev, 1, CLOCKGEN_CONTROL); ++ usleep_range(5000, 6000); ++ *val = ddbreadl(dev, CLOCKGEN_READDATA); ++} ++ ++static void mod_si598_writereg(struct ddb *dev, u8 index, u8 val) ++{ ++ ddbwritel(dev, index, CLOCKGEN_INDEX); ++ ddbwritel(dev, val, CLOCKGEN_WRITEDATA); ++ ddbwritel(dev, 3, CLOCKGEN_CONTROL); ++ usleep_range(5000, 6000); ++} ++ ++static int mod_set_si598(struct ddb *dev, u32 freq) ++{ ++ u8 Data[6]; ++ u64 fDCO = 0; ++ u64 RFreq = 0; ++ u32 fOut = 10000000; ++ u64 m_fXtal = 0; ++ u32 N = 0; ++ u64 HSDiv = 0; ++ ++ u32 fxtal; ++ u64 MinDiv, MaxDiv, Div; ++ u64 RF; ++ ++ if (freq < 10000000 || freq > 525000000) ++ return -EINVAL; ++ mod_si598_writereg(dev, 137, 0x10); ++ ++ if (m_fXtal == 0) { ++ mod_si598_writereg(dev, 135, 0x01); ++ mod_si598_readreg(dev, 7, &Data[0]); ++ mod_si598_readreg(dev, 8, &Data[1]); ++ mod_si598_readreg(dev, 9, &Data[2]); ++ mod_si598_readreg(dev, 10, &Data[3]); ++ mod_si598_readreg(dev, 11, &Data[4]); ++ mod_si598_readreg(dev, 12, &Data[5]); ++ ++ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", ++ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); ++ RFreq = (((u64)Data[1] & 0x3F) << 32) | ((u64)Data[2] << 24) | ++ ((u64)Data[3] << 16) | ((u64)Data[4] << 8) | ++ ((u64)Data[5]); ++ if (RFreq == 0) ++ return -EINVAL; ++ HSDiv = ((Data[0] & 0xE0) >> 5) + 4; ++ if (HSDiv == 8 || HSDiv == 10) ++ return -EINVAL; ++ N = (((u32)(Data[0] & 0x1F) << 2) | ++ ((u32)(Data[1] & 0xE0) >> 6)) + 1; ++ fDCO = fOut * (u64)(HSDiv * N); ++ m_fXtal = fDCO << 28; ++ pr_info("fxtal %016llx rfreq %016llx\n", m_fXtal, RFreq); ++ ++ m_fXtal += RFreq >> 1; ++ m_fXtal = div64_u64(m_fXtal, RFreq); ++ ++ pr_info("fOut = %d fXtal = %d fDCO = %d HDIV = %2d, N = %3d\n", ++ (u32) fOut, (u32) m_fXtal, (u32) fDCO, (u32) HSDiv, N); ++ } ++ ++ fOut = freq; ++ MinDiv = 4850000000ULL; do_div(MinDiv, freq); MinDiv += 1; ++ MaxDiv = 5670000000ULL; do_div(MaxDiv, freq); ++ Div = 5260000000ULL; do_div(Div, freq); ++ ++ if (Div < MinDiv) ++ Div = Div + 1; ++ pr_info(" fOut = %u MinDiv = %llu MaxDiv = %llu StartDiv = %llu\n", ++ fOut, MinDiv, MaxDiv, Div); ++ ++ if (Div <= 11) { ++ N = 1; ++ HSDiv = Div; ++ } else { ++ int retry = 100; ++ while (retry > 0) { ++ N = 0; ++ HSDiv = Div; ++ while ((HSDiv > 11) /*|| ((HSDiv * N) != Div)*/) { ++ N = N + 2; ++ HSDiv = Div; ++ do_div(HSDiv, N); ++ if (N > 128) ++ break; ++ } ++ pr_info(" %3d: %llu %llu %llu %u\n", ++ retry, Div, HSDiv * N, HSDiv, N); ++ if (HSDiv * N < MinDiv) ++ Div = Div + 2; ++ else if (HSDiv * N > MaxDiv) ++ Div = Div - 2; ++ else ++ break; ++ retry = retry - 1; ++ } ++ if (retry == 0) { ++ pr_err(" FAIL\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (HSDiv == 8 || HSDiv == 10) { ++ HSDiv = HSDiv >> 1; ++ N = N * 2; ++ } ++ ++ if (HSDiv < 4) ++ return -EINVAL; ++ ++ ++ fDCO = (u64)fOut * (u64)N * (u64)HSDiv; ++ pr_info("fdco %16llx\n", fDCO); ++ RFreq = fDCO<<28; ++ pr_info("%16llx %16llx\n", fDCO, RFreq); ++ ++ fxtal = m_fXtal; ++ do_div(RFreq, fxtal); ++ pr_info("%16llx %d\n", RFreq, fxtal); ++ RF = RFreq; ++ ++ pr_info("fOut = %u fXtal = %llu fDCO = %llu HSDIV = %llu, N = %u, RFreq = %llu\n", ++ fOut, m_fXtal, fDCO, HSDiv, N, RFreq); ++ ++ Data[0] = (u8)(((HSDiv - 4) << 5) | ((N - 1) >> 2)); ++ Data[1] = (u8)((((N - 1) & 0x03) << 6) | ((RF >> 32) & 0x3F)); ++ Data[2] = (u8)((RF >> 24) & 0xFF); ++ Data[3] = (u8)((RF >> 16) & 0xFF); ++ Data[4] = (u8)((RF >> 8) & 0xFF); ++ Data[5] = (u8)((RF) & 0xFF); ++ ++ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", ++ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); ++ mod_si598_writereg(dev, 7, Data[0]); ++ mod_si598_writereg(dev, 8, Data[1]); ++ mod_si598_writereg(dev, 9, Data[2]); ++ mod_si598_writereg(dev, 10, Data[3]); ++ mod_si598_writereg(dev, 11, Data[4]); ++ mod_si598_writereg(dev, 12, Data[5]); ++ ++ mod_si598_writereg(dev, 137, 0x00); ++ mod_si598_writereg(dev, 135, 0x40); ++ return 0; ++} ++ ++ ++static void mod_bypass_equalizer(struct ddb *dev, int bypass) ++{ ++ u32 RegValue; ++ ++ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); ++ RegValue &= ~IQOUTPUT_CONTROL_BYPASS_EQUALIZER; ++ RegValue |= (bypass ? IQOUTPUT_CONTROL_BYPASS_EQUALIZER : 0x00); ++ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); ++} ++ ++static int mod_set_equalizer(struct ddb *dev, u32 Num, s16 *cTable) ++{ ++ u32 i, adr = IQOUTPUT_EQUALIZER_0; ++ ++ if (Num > 11) ++ return -EINVAL; ++ ++ for (i = 0; i < 11 - Num; i += 1) { ++ ddbwritel(dev, 0, adr); ++ adr += 4; ++ } ++ for (i = 0; i < Num; i += 1) { ++ ddbwritel(dev, (u32) cTable[i], adr); ++ adr += 4; ++ } ++ return 0; ++} ++ ++#if 0 ++static void mod_peak(struct ddb *dev, u32 Time, s16 *pIPeak, s16 *pQPeak) ++{ ++ u32 val; ++ ++ val = ddbreadl(dev, IQOUTPUT_CONTROL); ++ val &= ~(IQOUTPUT_CONTROL_ENABLE_PEAK | IQOUTPUT_CONTROL_RESET_PEAK); ++ ddbwritel(dev, val, IQOUTPUT_CONTROL); ++ ddbwritel(dev, val | IQOUTPUT_CONTROL_RESET_PEAK, IQOUTPUT_CONTROL); ++ msleep(20); ++ ddbwritel(dev, val, IQOUTPUT_CONTROL); ++ ddbwritel(dev, val | IQOUTPUT_CONTROL_ENABLE_PEAK, IQOUTPUT_CONTROL); ++ msleep(Time); ++ ddbwritel(dev, val, IQOUTPUT_CONTROL); ++ val = ddbreadl(dev, IQOUTPUT_PEAK_DETECTOR); ++ ++ *pIPeak = val & 0xffff; ++ *pQPeak = (val >> 16) & 0xffff; ++} ++#endif ++ ++static int mod_init_dac_input(struct ddb *dev) ++{ ++ u8 Set = 0; ++ u8 Hld = 0; ++ u8 Sample = 0; ++ ++ u8 Seek = 0; ++ u8 ReadSeek = 0; ++ ++ u8 SetTable[32]; ++ u8 HldTable[32]; ++ u8 SeekTable[32]; ++ ++ u8 Sample1 = 0xFF; ++ u8 Sample2 = 0xFF; ++ ++ u8 SelectSample = 0xFF; ++ u8 DiffMin = 0xFF; ++ ++ for (Sample = 0; Sample < 32; Sample++) { ++ Set = 0; ++ Hld = 0; ++ ++ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); ++ mod_write_dac_register(dev, 0x05, Sample); ++ mod_read_dac_register(dev, 0x06, &ReadSeek); ++ Seek = ReadSeek & 0x01; ++ SeekTable[Sample] = Seek; ++ ++ HldTable[Sample] = 15; ++ ++ for (Hld = 1; Hld < 16; Hld += 1) { ++ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); ++ mod_read_dac_register(dev, 0x06, &ReadSeek); ++ ++ if ((ReadSeek & 0x01) != Seek) { ++ HldTable[Sample] = Hld; ++ break; ++ } ++ } ++ ++ Hld = 0; ++ SetTable[Sample] = 15; ++ for (Set = 1; Set < 16; Set += 1) { ++ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); ++ mod_read_dac_register(dev, 0x06, &ReadSeek); ++ ++ if ((ReadSeek & 0x01) != Seek) { ++ SetTable[Sample] = Set; ++ break; ++ } ++ } ++ } ++ ++ Seek = 1; ++ for (Sample = 0; Sample < 32; Sample += 1) { ++ /* printk(" %2d: %d %2d %2d\n", ++ Sample, SeekTable[Sample], SetTable[Sample], ++ HldTable[Sample]); ++ */ ++ ++ if (Sample1 == 0xFF && SeekTable[Sample] == 1 && Seek == 0) ++ Sample1 = Sample; ++ if (Sample1 != 0xFF && Sample2 == 0xFF && ++ SeekTable[Sample] == 0 && Seek == 1) ++ Sample2 = Sample; ++ Seek = SeekTable[Sample]; ++ } ++ ++ if (Sample1 == 0xFF || Sample2 == 0xFF) { ++ pr_err(" No valid window found\n"); ++ return -EINVAL; ++ } ++ ++ pr_err(" Window = %d - %d\n", Sample1, Sample2); ++ ++ for (Sample = Sample1; Sample < Sample2; Sample += 1) { ++ if (SetTable[Sample] < HldTable[Sample]) { ++ if (HldTable[Sample] - SetTable[Sample] < DiffMin) { ++ DiffMin = HldTable[Sample] - SetTable[Sample]; ++ SelectSample = Sample; ++ } ++ } ++ } ++ ++ pr_info("Select Sample %d\n", SelectSample); ++ ++ if (SelectSample == 0xFF) { ++ pr_err("No valid sample found\n"); ++ return -EINVAL; ++ } ++ ++ if (HldTable[SelectSample] + SetTable[SelectSample] < 8) { ++ pr_err("Too high jitter\n"); ++ return -EINVAL; ++ } ++ ++ mod_write_dac_register(dev, 0x04, 0x00); ++ mod_write_dac_register(dev, 0x05, (SelectSample - 1) & 0x1F); ++ mod_read_dac_register(dev, 0x06, &Seek); ++ mod_write_dac_register(dev, 0x05, (SelectSample + 1) & 0x1F); ++ mod_read_dac_register(dev, 0x06, &ReadSeek); ++ Seek &= ReadSeek; ++ ++ mod_write_dac_register(dev, 0x05, SelectSample); ++ mod_read_dac_register(dev, 0x06, &ReadSeek); ++ Seek &= ReadSeek; ++ if ((Seek & 0x01) == 0) { ++ pr_err("Insufficient timing margin\n"); ++ return -EINVAL; ++ } ++ pr_info("Done\n"); ++ return 0; ++} ++ ++static void mod_set_up1(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) ++{ ++ u32 RDiv = Ext / Ref; ++ ++ Frequency = Frequency / Ref; ++ mod_set_up_converter_vco1(dev, 0x360001 | (RDiv << 2)); ++ mod_set_up_converter_vco1(dev, 0x0ff128); ++ mod_set_up_converter_vco1(dev, 0x02 | (Frequency << 8)); ++} ++ ++static void mod_set_up2(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) ++{ ++ u32 Rdiv = Ext / Ref; ++ u32 PreScale = 8; ++ ++ Frequency = Frequency / Ref; ++ mod_set_up_converter_vco2(dev, 0x360001 | (Rdiv << 2)); ++ mod_set_up_converter_vco2(dev, 0x0fc128 | ++ (((PreScale - 8) / 8) << 22)); ++ mod_set_up_converter_vco2(dev, 0x02 | ((Frequency / PreScale) << 8) ++ | (Frequency & (PreScale - 1)) << 2); ++} ++ ++static int mod_set_down(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) ++{ ++ u32 BandSelect = Ref * 8; ++ u32 RefMul = 1; ++ u32 RefDiv2 = 1; ++ u32 RefDiv = Ext * RefMul / (Ref * RefDiv2); ++ ++ if (Frequency < 2200 || Frequency > 4000) ++ return -EINVAL; ++ ++ Frequency = Frequency / Ref; ++ ++ mod_set_down_converter_vco(dev, 0x0080003C | ++ ((BandSelect & 0xFF) << 12)); ++ mod_set_down_converter_vco(dev, 0x00000003); ++ mod_set_down_converter_vco(dev, 0x18001E42 | ((RefMul-1) << 25) | ++ ((RefDiv2-1) << 24) | (RefDiv << 14)); ++ mod_set_down_converter_vco(dev, 0x08008021); ++ mod_set_down_converter_vco(dev, Frequency << 15); ++ return 0; ++} ++ ++static int mod_set_dac_clock(struct ddb *dev, u32 Frequency) ++{ ++ int hr, i; ++ ++ if (Frequency) { ++ ddbwritel(dev, DAC_CONTROL_RESET, DAC_CONTROL); ++ msleep(20); ++ if (mod_set_si598(dev, Frequency)) { ++ pr_err("mod_set_si598 failed\n"); ++ return -1; ++ } ++ msleep(50); ++ ddbwritel(dev, 0x000, DAC_CONTROL); ++ msleep(20); ++ mod_write_dac_register(dev, 0, 0x02); ++ } ++ ++ for (i = 0; i < 10; i++) { ++ hr = mod_init_dac_input(dev); ++ if (hr == 0) ++ break; ++ msleep(100); ++ } ++ pr_info("mod_set_dac_clock OK\n"); ++ return hr; ++} ++ ++static void mod_set_dac_current(struct ddb *dev, u32 Current1, u32 Current2) ++{ ++ mod_write_dac_register2(dev, 0x0b, Current1 & 0x3ff); ++ mod_write_dac_register2(dev, 0x0f, Current2 & 0x3ff); ++} ++ ++static void mod_output_enable(struct ddb *dev, int enable) ++{ ++ ++ u32 RegValue; ++ ++ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); ++ RegValue &= ~(IQOUTPUT_CONTROL_ENABLE | IQOUTPUT_CONTROL_RESET); ++ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); ++ ++ if (enable) { ++ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_RESET, ++ IQOUTPUT_CONTROL); ++ msleep(20); ++ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); ++ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_ENABLE, ++ IQOUTPUT_CONTROL); ++ } ++} ++ ++static int mod_set_iq(struct ddb *dev, u32 steps, u32 chan, u32 freq) ++{ ++ u32 i, j, k, fac = 8; ++ u32 s1 = 22, s2 = 33; ++ u64 amp = (1ULL << 17) - 1ULL; ++ u64 s = 0, c = (amp << s1), ss; ++ u64 frq = 0xC90FDAA22168C234ULL; ++ u32 *iqtab; ++ u32 iqtabadr; ++ u32 regval; ++ ++ iqtab = kmalloc((steps + 1) * 4, GFP_KERNEL); ++ if (!iqtab) ++ return -ENOMEM; ++ frq = div64_u64(frq, steps * fac) >> (61 - s2); ++ ++ /* create sine table */ ++ for (i = 0; i <= steps * fac / 4; i++) { ++ if (!(i & (fac - 1))) { ++ j = i / fac; ++ ss = s >> s1; ++ /*round? ss = ((s >> (s1 - 1)) + 1) >> 1; */ ++ ++ iqtab[j] = iqtab[steps / 2 - j] = ss; ++ iqtab[steps / 2 + j] = iqtab[steps - j] = -ss; ++ } ++ c -= ((s * frq) >> s2); ++ s += ((c * frq) >> s2); ++ } ++ iqtabadr = chan << 16; ++ ddbwritel(dev, chan & 0x0f, MODULATOR_IQTABLE_INDEX); ++ for (i = j = 0, k = steps / 4; i < steps; i++) { ++ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_I, ++ MODULATOR_IQTABLE_INDEX); ++ ddbwritel(dev, iqtab[j], MODULATOR_IQTABLE_DATA); ++ regval = ddbreadl(dev, MODULATOR_CONTROL); ++ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_Q, ++ MODULATOR_IQTABLE_INDEX); ++ ddbwritel(dev, iqtab[k], MODULATOR_IQTABLE_DATA); ++ regval = ddbreadl(dev, MODULATOR_CONTROL); ++ j += freq; ++ j %= steps; ++ k += freq; ++ k %= steps; ++ } ++ ddbwritel(dev, steps - 1, MODULATOR_IQTABLE_END); ++ kfree(iqtab); ++ return 0; ++} ++ ++u32 eqtab[] = { ++ 0x0000FFDB, 0x00000121, 0x0000FF0A, 0x000003D7, ++ 0x000001C4, 0x000005A5, 0x000009CC, 0x0000F50D, ++ 0x00001B23, 0x0000EEB7, 0x00006A28 ++}; ++ ++static int mod_set_modulation(struct ddb *dev, int chan, enum fe_modulation mod) ++{ ++ if (mod > QAM_256 || mod < QAM_16) ++ return -EINVAL; ++ dev->mod[chan].modulation = mod; ++ dev->mod[chan].obitrate = 0x0061072787900000 * (mod + 3); ++ dev->mod[chan].ibitrate = dev->mod[chan].obitrate; ++ ddbwritel(dev, qamtab[mod], CHANNEL_SETTINGS(chan)); ++ return 0; ++} ++ ++static void mod_set_channelsumshift(struct ddb *dev, u32 shift) ++{ ++ ddbwritel(dev, (shift & 3) << 2, MODULATOR_CONTROL); ++} ++ ++static void mod_pre_eq_gain(struct ddb *dev, u16 gain) ++{ ++ ddbwritel(dev, gain, IQOUTPUT_PRESCALER); ++} ++ ++static void mod_post_eq_gain(struct ddb *dev, u16 igain, u16 qgain) ++{ ++ ddbwritel(dev, ((u32)qgain << 16) | igain, IQOUTPUT_POSTSCALER); ++} ++ ++static int set_base_frequency(struct ddb *dev, u32 freq) ++{ ++ u32 Ext = 40; ++ u32 UP1Frequency = 290; ++ u32 UP2Frequency = 1896; ++ u32 down, freq10; ++ ++ pr_info("set base to %u\n", freq); ++ dev->mod_base.frequency = freq; ++ freq /= 1000000; ++ freq10 = dev->mod_base.flat_start + 4; ++ down = freq + 9 * 8 + freq10 + UP1Frequency + UP2Frequency; ++ ++ if ((freq10 + 9 * 8) > (dev->mod_base.flat_end - 4)) { ++ pr_err("Frequency out of range %d\n", freq10); ++ return -EINVAL; ++ } ++ if (down % 8) { ++ pr_err(" Invalid Frequency %d\n", down); ++ return -EINVAL; ++ } ++ return mod_set_down(dev, down, 8, Ext); ++} ++ ++static int mod_init(struct ddb *dev, u32 Frequency) ++{ ++ int stat = 0; ++ u8 *buffer; ++ struct DDMOD_FLASH *flash; ++ u32 Ext = 40; ++ u32 UP1Frequency = 290; ++ u32 UP2Frequency = 1896; ++ u32 DownFrequency; ++ u32 FrequencyCH10; ++ u32 iqfreq, iqsteps, i; ++ ++ buffer = kmalloc(4096, GFP_KERNEL); ++ if (!buffer) ++ return -ENOMEM; ++ flash = (struct DDMOD_FLASH *) buffer; ++ ++ ddbridge_flashread(dev, buffer, DDMOD_FLASH_START, 4096); ++ ++ if (flash->Magic != DDMOD_FLASH_MAGIC && flash->Magic != 1) { ++ stat = -EINVAL; ++ goto fail; ++ } ++ pr_info("srate = %d\n", flash->DataSet[0].Symbolrate * 1000); ++ ++ mod_output_enable(dev, 0); ++ stat = mod_set_dac_clock(dev, flash->DataSet[0].DACFrequency * 1000); ++ if (stat < 0) { ++ pr_err("setting DAC clock failed\n"); ++ goto fail; ++ } ++ mod_set_dac_current(dev, 512, 512); ++ ++ ddbwritel(dev, flash->DataSet[0].Control2, IQOUTPUT_CONTROL2); ++ ++ mod_set_up1(dev, UP1Frequency, 5, Ext); ++ mod_set_up2(dev, UP2Frequency, 8, Ext); ++ ++ dev->mod_base.flat_start = flash->DataSet[0].FlatStart; ++ dev->mod_base.flat_end = flash->DataSet[0].FlatEnd; ++ ++ Frequency /= 1000000; ++ FrequencyCH10 = flash->DataSet[0].FlatStart + 4; ++ DownFrequency = Frequency + 9 * 8 + FrequencyCH10 + ++ UP1Frequency + UP2Frequency; ++ pr_info("CH10 = %d, Down = %d\n", FrequencyCH10, DownFrequency); ++ ++ if ((FrequencyCH10 + 9 * 8) > (flash->DataSet[0].FlatEnd - 4)) { ++ pr_err("Frequency out of range %d\n", FrequencyCH10); ++ stat = -EINVAL; ++ goto fail; ++ } ++ ++ if (DownFrequency % 8 != 0) { ++ pr_err(" Invalid Frequency %d\n", DownFrequency); ++ stat = -EINVAL; ++ goto fail; ++ } ++ ++ mod_set_down(dev, DownFrequency, 8, Ext); ++ ++ for (i = 0; i < 10; i++) { ++ ddbwritel(dev, 0, CHANNEL_CONTROL(i)); ++ ++ iqfreq = flash->DataSet[0].FrequencyFactor * ++ (FrequencyCH10 + (9 - i) * 8); ++ iqsteps = flash->DataSet[0].IQTableLength; ++ mod_set_iq(dev, iqsteps, i, iqfreq); ++ mod_set_modulation(dev, i, QAM_256); ++ } ++ ++ mod_bypass_equalizer(dev, 1); ++ mod_set_equalizer(dev, 11, flash->DataSet[0].EQTap); ++ mod_bypass_equalizer(dev, 0); ++ mod_post_eq_gain(dev, flash->DataSet[0].PostScaleI, ++ flash->DataSet[0].PostScaleQ); ++ mod_pre_eq_gain(dev, flash->DataSet[0].PreScale); ++ /*mod_pre_eq_gain(dev, 0x0680);*/ ++ pr_info("prescaler %04x\n", flash->DataSet[0].PreScale); ++ mod_set_channelsumshift(dev, 2); ++ mod_output_enable(dev, 1); ++ ++ /*mod_set_attenuator(dev, 10);*/ ++fail: ++ kfree(buffer); ++ return stat; ++} ++ ++#define PACKET_CLOCKS (27000000ULL*1504) ++#define FACTOR (1ULL << 22) ++ ++/* ++ double Increment = FACTOR*PACKET_CLOCKS/double(m_OutputBitrate); ++ double Decrement = FACTOR*PACKET_CLOCKS/double(m_InputBitrate); ++ ++ 27000000 * 1504 * 2^22 / (6900000 * 188 / 204) = 26785190066.1 ++*/ ++ ++void ddbridge_mod_rate_handler(unsigned long data) ++{ ++ struct ddb_output *output = (struct ddb_output *) data; ++ struct ddb_dma *dma = output->dma; ++ struct ddb *dev = output->port->dev; ++ struct mod_state *mod = &dev->mod[output->nr]; ++ ++ u32 chan = output->nr; ++ u32 OutPacketCount; ++ u32 InPacketCount; ++ u64 OutPackets, InPackets; ++ s64 PCRAdjust; ++ u32 PCRAdjustExt, PCRAdjustExtFrac, InPacketDiff, OutPacketDiff; ++ s32 PCRCorr; ++ ++ s64 pcr; ++ s64 PCRIncrementDiff; ++ s64 PCRIncrement; ++ u64 mul; ++ ++ if (!mod->pcr_correction) ++ return; ++ spin_lock(&dma->lock); ++ ddbwritel(dev, mod->Control | CHANNEL_CONTROL_FREEZE_STATUS, ++ CHANNEL_CONTROL(output->nr)); ++ ++ OutPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_OUT(chan)); ++ if (OutPacketCount < mod->LastOutPacketCount) ++ mod->OutOverflowPacketCount += 1; ++ mod->LastOutPacketCount = OutPacketCount; ++ ++ InPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_IN(chan)); ++ if (InPacketCount < mod->LastInPacketCount) ++ mod->InOverflowPacketCount += 1; ++ mod->LastInPacketCount = InPacketCount; ++ ++ OutPackets = ((u64) (mod->OutOverflowPacketCount) << 20) | ++ OutPacketCount; ++ InPackets = ((u64) (mod->InOverflowPacketCount) << 20) | ++ InPacketCount; ++ ++ PCRAdjust = (s64) ((u64) ddbreadl(dev, ++ CHANNEL_PCR_ADJUST_ACCUL(chan)) | ++ (((u64) ddbreadl(dev, ++ CHANNEL_PCR_ADJUST_ACCUH(chan)) ++ << 32))); ++ PCRAdjustExt = (u32)((PCRAdjust & 0x7FFFFFFF) >> 22); ++ PCRAdjustExtFrac = (u32)((PCRAdjust & 0x003FFFFF) >> 12); ++ PCRAdjust >>= 31; ++ InPacketDiff = (u32) (InPackets - mod->LastInPackets); ++ OutPacketDiff = (u32) (OutPackets - mod->LastOutPackets); ++ PCRCorr = 0; ++ ++ switch (mod->State) { ++ case CM_STARTUP: ++ if (mod->StateCounter) { ++ if (mod->StateCounter == 1) { ++ if (mod->ibitrate == 0) { ++ mul = (0x1000000 * (u64) (OutPacketDiff - ++ InPacketDiff - ++ InPacketDiff/1000)); ++ if (OutPacketDiff) ++ mod->rate_inc = ++ div_u64(mul, OutPacketDiff); ++ else ++ mod->rate_inc = 0; ++ mod_set_rateinc(dev, output->nr); ++ mod->PCRIncrement = ++ div_u64(26785190066ULL, ++ mod->modulation + 3); ++ if (InPacketDiff) ++ mod->PCRDecrement = ++ div_u64(mod->PCRIncrement * ++ (u64) OutPacketDiff, ++ InPacketDiff); ++ else ++ mod->PCRDecrement = 0; ++ mod_set_incs(output); ++ } else { ++ mod->PCRIncrement = ++ div_u64(26785190066ULL, ++ mod->modulation + 3); ++ mod->PCRDecrement = ++ div_u64(FACTOR*PACKET_CLOCKS, ++ mod->ibitrate >> 32); ++ mod_set_incs(output); ++ } ++ } ++ mod->StateCounter--; ++ break; ++ } else if (InPacketDiff >= mod->MinInputPackets) { ++ mod->State = CM_ADJUST; ++ mod->Control |= CHANNEL_CONTROL_ENABLE_PCRADJUST; ++ mod->InPacketsSum = 0; ++ mod->OutPacketsSum = 0; ++ mod->PCRAdjustSum = 0; ++ mod->StateCounter = CM_AVERAGE; ++ } ++ break; ++ ++ case CM_ADJUST: ++ if (InPacketDiff < mod->MinInputPackets) { ++ pr_info("PCR Adjust reset IN: %u Min: %u\n", ++ InPacketDiff, mod->MinInputPackets); ++ mod->InPacketsSum = 0; ++ mod->OutPacketsSum = 0; ++ mod->PCRAdjustSum = 0; ++ mod->StateCounter = CM_AVERAGE; ++ ddbwritel(dev, ++ (mod->Control | ++ CHANNEL_CONTROL_FREEZE_STATUS) & ++ ~CHANNEL_CONTROL_ENABLE_PCRADJUST, ++ CHANNEL_CONTROL(chan)); ++ break; ++ } ++ ++ mod->PCRAdjustSum += (s32) PCRAdjust; ++ mod->InPacketsSum += InPacketDiff; ++ mod->OutPacketsSum += OutPacketDiff; ++ if (mod->StateCounter--) ++ break; ++ ++ if (mod->OutPacketsSum) ++ PCRIncrement = div_s64((s64)mod->InPacketsSum * ++ (s64)mod->PCRDecrement + ++ (s64)(mod->OutPacketsSum >> 1), ++ mod->OutPacketsSum); ++ else ++ PCRIncrement = 0; ++ ++ if (mod->PCRAdjustSum > 0) ++ PCRIncrement = RoundPCRDown(PCRIncrement); ++ else ++ PCRIncrement = RoundPCRUp(PCRIncrement); ++ ++ PCRIncrementDiff = PCRIncrement - mod->PCRIncrement; ++ if (PCRIncrementDiff > HW_LSB_MASK) ++ PCRIncrementDiff = HW_LSB_MASK; ++ if (PCRIncrementDiff < -HW_LSB_MASK) ++ PCRIncrementDiff = -HW_LSB_MASK; ++ ++ mod->PCRIncrement += PCRIncrementDiff; ++ pcr = ConvertPCR(mod->PCRIncrement); ++ pr_info("outl %016llx\n", pcr); ++ ddbwritel(dev, pcr & 0xffffffff, ++ CHANNEL_PCR_ADJUST_OUTL(output->nr)); ++ ddbwritel(dev, (pcr >> 32) & 0xffffffff, ++ CHANNEL_PCR_ADJUST_OUTH(output->nr)); ++ mod_busy(dev, chan); ++ ++ PCRCorr = (s32) (PCRIncrementDiff >> HW_LSB_SHIFT); ++ mod->PCRRunningCorr += PCRCorr; ++ ++ mod->InPacketsSum = 0; ++ mod->OutPacketsSum = 0; ++ mod->PCRAdjustSum = 0; ++ mod->StateCounter = CM_AVERAGE; ++ break; ++ ++ default: ++ break; ++ } ++ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(chan)); ++ ++ mod->LastInPackets = InPackets; ++ mod->LastOutPackets = OutPackets; ++ mod->LastPCRAdjust = (s32) PCRAdjust; ++ ++ spin_unlock(&dma->lock); ++ ++ pr_info("chan %d out %016llx in %016llx indiff %08x\n", ++ chan, OutPackets, InPackets, InPacketDiff); ++ pr_info("cnt %d pcra %016llx pcraext %08x pcraextfrac %08x pcrcorr %08x pcri %016llx\n", ++ mod->StateCounter, PCRAdjust, PCRAdjustExt, ++ PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement); ++} ++ ++int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb *dev = output->port->dev; ++ ++ /* unsigned long arg = (unsigned long) parg; */ ++ int ret = 0; ++ ++ switch (cmd) { ++ case DVB_MOD_SET: ++ { ++ struct dvb_mod_params *mp = parg; ++ ++ pr_info("set base freq\n"); ++ if (mp->base_frequency != dev->mod_base.frequency) ++ if (set_base_frequency(dev, mp->base_frequency)) ++ return -EINVAL; ++ pr_info("set attenuator\n"); ++ mod_set_attenuator(dev, mp->attenuator); ++ break; ++ } ++ case DVB_MOD_CHANNEL_SET: ++ { ++ struct dvb_mod_channel_params *cp = parg; ++ int res; ++ u32 ri; ++ ++ pr_info("set modulation\n"); ++ res = mod_set_modulation(dev, output->nr, cp->modulation); ++ if (res) ++ return res; ++ ++ if (cp->input_bitrate > dev->mod[output->nr].obitrate) ++ return -EINVAL; ++ dev->mod[output->nr].ibitrate = cp->input_bitrate; ++ dev->mod[output->nr].pcr_correction = cp->pcr_correction; ++ ++ pr_info("ibitrate %llu\n", dev->mod[output->nr].ibitrate); ++ pr_info("obitrate %llu\n", dev->mod[output->nr].obitrate); ++ if (cp->input_bitrate != 0) { ++ u64 d = dev->mod[output->nr].obitrate - ++ dev->mod[output->nr].ibitrate; ++ ++ d = div64_u64(d, dev->mod[output->nr].obitrate >> 24); ++ if (d > 0xfffffe) ++ ri = 0xfffffe; ++ else ++ ri = d; ++ } else ++ ri = 0; ++ dev->mod[output->nr].rate_inc = ri; ++ pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n", ++ dev->mod[output->nr].ibitrate >> 32, ++ dev->mod[output->nr].obitrate >> 32, ++ ri); ++ break; ++ } ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++int ddbridge_mod_init(struct ddb *dev) ++{ ++ return mod_init(dev, 722000000); ++} +diff --git a/drivers/media/pci/ddbridge/ddbridge-ns.c b/drivers/media/pci/ddbridge/ddbridge-ns.c +new file mode 100644 +index 0000000..9d86cba +--- /dev/null ++++ b/drivers/media/pci/ddbridge/ddbridge-ns.c +@@ -0,0 +1,489 @@ ++/* ++ * ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming ++ * ++ * Copyright (C) 2010-2014 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++static int ddb_dvb_input_start(struct ddb_input *input); ++static int ddb_dvb_input_stop(struct ddb_input *input); ++ ++static u16 calc_pcs(struct dvb_ns_params *p) ++{ ++ u32 sum = 0; ++ u16 pcs; ++ ++ sum += (p->sip[0] << 8) | p->sip[1]; ++ sum += (p->sip[2] << 8) | p->sip[3]; ++ sum += (p->dip[0] << 8) | p->dip[1]; ++ sum += (p->dip[2] << 8) | p->dip[3]; ++ sum += 0x11; /* UDP proto */ ++ sum = (sum >> 16) + (sum & 0xffff); ++ pcs = sum; ++ return pcs; ++} ++ ++static u16 calc_pcs16(struct dvb_ns_params *p, int ipv) ++{ ++ u32 sum = 0, i; ++ u16 pcs; ++ ++ for (i = 0; i < ipv ? 16 : 4; i += 2) { ++ sum += (p->sip[i] << 8) | p->sip[i + 1]; ++ sum += (p->dip[i] << 8) | p->dip[i + 1]; ++ } ++ sum += 0x11; /* UDP proto */ ++ sum = (sum >> 16) + (sum & 0xffff); ++ pcs = sum; ++ return pcs; ++} ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static void ns_free(struct dvbnss *nss) ++{ ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ ++ mutex_lock(&dev->mutex); ++ dns->input = 0; ++ mutex_unlock(&dev->mutex); ++} ++ ++static int ns_alloc(struct dvbnss *nss) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ int i, ret = -EBUSY; ++ ++ mutex_lock(&dev->mutex); ++ for (i = 0; i < dev->ns_num; i++) { ++ if (dev->ns[i].input) ++ continue; ++ dev->ns[i].input = input; ++ dev->ns[i].fe = input->nr; ++ nss->priv = &dev->ns[i]; ++ ret = 0; ++ /*pr_info("%s i=%d fe=%d\n", __func__, i, input->nr); */ ++ break; ++ } ++ ddbwritel(dev, 0x03, RTP_MASTER_CONTROL); ++ mutex_unlock(&dev->mutex); ++ return ret; ++} ++ ++static int ns_set_pids(struct dvbnss *nss) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ ++ if (dev->ids.devid == 0x0301dd01) { ++ u32 sys = 0; ++ int pid, j = 1; ++ ++ sys |= nss->pids[0] & 3; ++ sys |= (nss->pids[2] & 0x1f) << 4; ++ ddbwritel(dev, sys, PID_FILTER_SYSTEM_PIDS(dns->nr)); ++ for (pid = 20; j < 5 && pid < 8192; pid++) ++ if (nss->pids[pid >> 3] & (1 << (pid & 7))) { ++ ddbwritel(dev, 0x8000 | pid, ++ PID_FILTER_PID(dns->nr, j)); ++ j++; ++ } ++ /* disable unused pids */ ++ for (; j < 5; j++) ++ ddbwritel(dev, 0, PID_FILTER_PID(dns->nr, j)); ++ } else ++ ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400); ++ return 0; ++} ++ ++static int ns_set_pid(struct dvbnss *nss, u16 pid) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ u16 byte = (pid & 0x1fff) >> 3; ++ u8 bit = 1 << (pid & 7); ++ u32 off = STREAM_PIDS(dns->nr); ++ ++#if 1 ++ if (dev->ids.devid == 0x0301dd01) { ++ if (pid & 0x2000) { ++ if (pid & 0x8000) ++ memset(nss->pids, 0xff, 0x400); ++ else ++ memset(nss->pids, 0x00, 0x400); ++ } else { ++ if (pid & 0x8000) ++ nss->pids[byte] |= bit; ++ else ++ nss->pids[byte] &= ~bit; ++ } ++ ns_set_pids(nss); ++ } else { ++ if (pid & 0x2000) { ++ if (pid & 0x8000) ++ ddbmemset(dev, off, 0xff, 0x400); ++ else ++ ddbmemset(dev, off, 0x00, 0x400); ++ } else { ++ u8 val = ddbreadb(dev, off + byte); ++ if (pid & 0x8000) ++ ddbwriteb(dev, val | bit, off + byte); ++ else ++ ddbwriteb(dev, val & ~bit, off + byte); ++ } ++ } ++#else ++ ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400); ++#endif ++ return 0; ++} ++ ++static int citoport(struct ddb *dev, u8 ci) ++{ ++ int i, j; ++ ++ for (i = j = 0; i < dev->info->port_num; i++) { ++ if (dev->port[i].class == DDB_PORT_CI) { ++ if (j == ci) ++ return i; ++ j++; ++ } ++ } ++ return -1; ++} ++ ++static int ns_set_ci(struct dvbnss *nss, u8 ci) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ int ciport; ++ ++ if (ci == 255) { ++ dns->fe = input->nr; ++ return 0; ++ } ++ ciport = citoport(dev, ci); ++ if (ciport < 0) ++ return -EINVAL; ++ pr_info("input %d to ci %d at port %d\n", input->nr, ci, ciport); ++ ddbwritel(dev, (input->nr << 16) | 0x1c, TS_OUTPUT_CONTROL(ciport)); ++ usleep_range(1, 5); ++ ddbwritel(dev, (input->nr << 16) | 0x1d, TS_OUTPUT_CONTROL(ciport)); ++ dns->fe = ciport * 2; ++ return 0; ++} ++ ++static u8 rtp_head[] = { ++ 0x80, 0x21, ++ 0x00, 0x00, /* seq number */ ++ 0x00, 0x00, 0x00, 0x00, /* time stamp*/ ++ 0x91, 0x82, 0x73, 0x64, /* SSRC */ ++}; ++ ++static u8 rtcp_head[] = { ++ /* SR off 42:8 len 28*/ ++ 0x80, 0xc8, /* SR type */ ++ 0x00, 0x06, /* len */ ++ 0x91, 0x82, 0x73, 0x64, /* SSRC */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* NTP */ ++ 0x73, 0x64, 0x00, 0x00, /* RTP TS */ ++ 0x00, 0x00, 0x00, 0x00, /* packet count */ ++ 0x00, 0x00, 0x00, 0x00, /* octet count */ ++ /* SDES off 70:36 len 20 */ ++ 0x81, 0xca, /* SDES */ ++ 0x00, 0x03, /* len */ ++ 0x91, 0x82, 0x73, 0x64, /* SSRC */ ++ 0x01, 0x05, /* CNAME item */ ++ 0x53, 0x41, 0x54, 0x49, 0x50, /* "SATIP" */ ++ 0x00, /* item type 0 */ ++ /* APP off 86:52 len 16+string length */ ++ 0x80, 0xcc, /* APP */ ++ 0x00, 0x04, /* len */ ++ 0x91, 0x82, 0x73, 0x64, /* SSRC */ ++ 0x53, 0x45, 0x53, 0x31, /* "SES1" */ ++ 0x00, 0x00, /* identifier */ ++ 0x00, 0x00, /* string length */ ++ /* string off 102:68 */ ++}; ++ ++static int ns_set_rtcp_msg(struct dvbnss *nss, u8 *msg, u32 len) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ u32 off = STREAM_PACKET_ADR(dns->nr); ++ u32 coff = 96; ++ u16 wlen; ++ ++ if (!len) { ++ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) & ++ ~0x10, ++ STREAM_CONTROL(dns->nr)); ++ return 0; ++ } ++ if (copy_from_user(dns->p + coff + dns->rtcp_len, msg, len)) ++ return -EFAULT; ++ dns->p[coff + dns->rtcp_len - 2] = (len >> 8); ++ dns->p[coff + dns->rtcp_len - 1] = (len & 0xff); ++ if (len & 3) { ++ u32 pad = 4 - (len & 3); ++ memset(dns->p + coff + dns->rtcp_len + len, 0, pad); ++ len += pad; ++ } ++ wlen = len / 4; ++ wlen += 3; ++ dns->p[coff + dns->rtcp_len - 14] = (wlen >> 8); ++ dns->p[coff + dns->rtcp_len - 13] = (wlen & 0xff); ++ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); ++ ddbwritel(dev, (dns->rtcp_udplen + len) | ++ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), ++ STREAM_RTCP_PACKET(dns->nr)); ++ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) | 0x10, ++ STREAM_CONTROL(dns->nr)); ++ return 0; ++} ++ ++static u32 set_nsbuf(struct dvb_ns_params *p, u8 *buf, u32 *udplen, int rtcp) ++{ ++ u32 c = 0; ++ u16 pcs; ++ u16 sport, dport; ++ ++ sport = rtcp ? p->sport2 : p->sport; ++ dport = rtcp ? p->dport2 : p->dport; ++ ++ /* MAC header */ ++ memcpy(buf + c, p->dmac, 6); ++ memcpy(buf + c + 6, p->smac, 6); ++ c += 12; ++ if (vlan) { ++ buf[c + 0] = 0x81; ++ buf[c + 1] = 0x00; ++ buf[c + 2] = ((p->qos & 7) << 5) | ((p->vlan & 0xf00) >> 8); ++ buf[c + 3] = p->vlan & 0xff; ++ c += 4; ++ } ++ buf[c + 0] = 0x08; ++ buf[c + 1] = 0x00; ++ c += 2; ++ ++ /* IP header */ ++ if (p->flags & DVB_NS_IPV6) { ++ u8 ip6head[8] = { 0x65, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x11, 0x00, }; ++ memcpy(buf + c, ip6head, sizeof(ip6head)); ++ buf[c + 7] = p->ttl; ++ memcpy(buf + c + 8, p->sip, 16); ++ memcpy(buf + c + 24, p->dip, 16); ++ c += 40; ++ ++ /* UDP */ ++ buf[c + 0] = sport >> 8; ++ buf[c + 1] = sport & 0xff; ++ buf[c + 2] = dport >> 8; ++ buf[c + 3] = dport & 0xff; ++ buf[c + 4] = 0; /* length */ ++ buf[c + 5] = 0; ++ pcs = calc_pcs16(p, p->flags & DVB_NS_IPV6); ++ buf[c + 6] = pcs >> 8; ++ buf[c + 7] = pcs & 0xff; ++ c += 8; ++ *udplen = 8; ++ ++ } else { ++ u8 ip4head[12] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x40, 0x11, 0x00, 0x00 }; ++ ++ memcpy(buf + c, ip4head, sizeof(ip4head)); ++ buf[c + 8] = p->ttl; ++ memcpy(buf + c + 12, p->sip, 4); ++ memcpy(buf + c + 16, p->dip, 4); ++ c += 20; ++ ++ /* UDP */ ++ buf[c + 0] = sport >> 8; ++ buf[c + 1] = sport & 0xff; ++ buf[c + 2] = dport >> 8; ++ buf[c + 3] = dport & 0xff; ++ buf[c + 4] = 0; /* length */ ++ buf[c + 5] = 0; ++ pcs = calc_pcs(p); ++ buf[c + 6] = pcs >> 8; ++ buf[c + 7] = pcs & 0xff; ++ c += 8; ++ *udplen = 8; ++ } ++ ++ if (rtcp) { ++ memcpy(buf + c, rtcp_head, sizeof(rtcp_head)); ++ memcpy(buf + c + 4, p->ssrc, 4); ++ memcpy(buf + c + 32, p->ssrc, 4); ++ memcpy(buf + c + 48, p->ssrc, 4); ++ c += sizeof(rtcp_head); ++ *udplen += sizeof(rtcp_head); ++ } else if (p->flags & DVB_NS_RTP) { ++ memcpy(buf + c, rtp_head, sizeof(rtp_head)); ++ memcpy(buf + c + 8, p->ssrc, 4); ++ c += sizeof(rtp_head); ++ *udplen += sizeof(rtp_head); ++ } ++ return c; ++} ++ ++static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len) ++{ ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ u32 off = STREAM_PACKET_ADR(dns->nr); ++ ++ if (nss->params.flags & DVB_NS_RTCP) ++ return -EINVAL; ++ ++ if (copy_from_user(dns->p + dns->ts_offset, buf, len)) ++ return -EFAULT; ++ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); ++ return 0; ++} ++ ++static int ns_insert_ts_packets(struct dvbnss *nss, u8 count) ++{ ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ u32 value = count; ++ ++ if (nss->params.flags & DVB_NS_RTCP) ++ return -EINVAL; ++ ++ if (count < 1 || count > 2) ++ return -EINVAL; ++ ++ ddbwritel(dev, value, STREAM_INSERT_PACKET(dns->nr)); ++ return 0; ++} ++ ++static int ns_set_net(struct dvbnss *nss) ++{ ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ struct dvb_ns_params *p = &nss->params; ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ u32 off = STREAM_PACKET_ADR(dns->nr); ++ u32 coff = 96; ++ ++ dns->ts_offset = set_nsbuf(p, dns->p, &dns->udplen, 0); ++ if (nss->params.flags & DVB_NS_RTCP) ++ dns->rtcp_len = set_nsbuf(p, dns->p + coff, ++ &dns->rtcp_udplen, 1); ++ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); ++ ddbwritel(dev, dns->udplen | (STREAM_PACKET_OFF(dns->nr) << 16), ++ STREAM_RTP_PACKET(dns->nr)); ++ ddbwritel(dev, dns->rtcp_udplen | ++ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), ++ STREAM_RTCP_PACKET(dns->nr)); ++ return 0; ++} ++ ++static int ns_start(struct dvbnss *nss) ++{ ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ u32 reg = 0x8003; ++ ++ ++ if (nss->params.flags & DVB_NS_RTCP) ++ reg |= 0x10; ++ if (nss->params.flags & DVB_NS_RTP_TO) ++ reg |= 0x20; ++ if (nss->params.flags & DVB_NS_RTP) ++ reg |= 0x40; ++ if (nss->params.flags & DVB_NS_IPV6) ++ reg |= 0x80; ++ if (dns->fe != input->nr) ++ ddb_dvb_input_start(&dev->input[dns->fe]); ++ ddb_dvb_input_start(input); ++ ddbwritel(dev, reg | (dns->fe << 8), STREAM_CONTROL(dns->nr)); ++ return 0; ++} ++ ++static int ns_stop(struct dvbnss *nss) ++{ ++ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; ++ struct dvb_netstream *ns = nss->ns; ++ struct ddb_input *input = ns->priv; ++ struct ddb *dev = input->port->dev; ++ ++ ddbwritel(dev, 0x00, STREAM_CONTROL(dns->nr)); ++ ddb_dvb_input_stop(input); ++ if (dns->fe != input->nr) ++ ddb_dvb_input_stop(&dev->input[dns->fe]); ++ return 0; ++} ++ ++static int netstream_init(struct ddb_input *input) ++{ ++ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; ++ struct dvb_adapter *adap = dvb->adap; ++ struct dvb_netstream *ns = &dvb->dvbns; ++ struct ddb *dev = input->port->dev; ++ int i, res; ++ ++ ddbmemset(dev, STREAM_PIDS(input->nr), 0x00, 0x400); ++ if (dev->ids.devid == 0x0301dd01) ++ dev->ns_num = 15; ++ else ++ dev->ns_num = 12; ++ for (i = 0; i < dev->ns_num; i++) ++ dev->ns[i].nr = i; ++ ns->priv = input; ++ ns->set_net = ns_set_net; ++ ns->set_rtcp_msg = ns_set_rtcp_msg; ++ ns->set_ts_packets = ns_set_ts_packets; ++ ns->insert_ts_packets = ns_insert_ts_packets; ++ ns->set_pid = ns_set_pid; ++ ns->set_pids = ns_set_pids; ++ ns->set_ci = ns_set_ci; ++ ns->start = ns_start; ++ ns->stop = ns_stop; ++ ns->alloc = ns_alloc; ++ ns->free = ns_free; ++ res = dvb_netstream_init(adap, ns); ++ return res; ++} +diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h +index a3ccb31..eca8574 100644 +--- a/drivers/media/pci/ddbridge/ddbridge-regs.h ++++ b/drivers/media/pci/ddbridge/ddbridge-regs.h +@@ -1,7 +1,7 @@ + /* + * ddbridge-regs.h: Digital Devices PCIe bridge driver + * +- * Copyright (C) 2010-2011 Digital Devices GmbH ++ * Copyright (C) 2010-2014 Digital Devices GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +@@ -21,11 +21,11 @@ + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */ +- + /* Register Definitions */ + +-#define CUR_REGISTERMAP_VERSION 0x10000 ++#define CUR_REGISTERMAP_VERSION 0x10003 ++#define CUR_REGISTERMAP_VERSION_CI 0x10000 ++#define CUR_REGISTERMAP_VERSION_MOD 0x10000 + + #define HARDWARE_VERSION 0x00 + #define REGISTERMAP_VERSION 0x04 +@@ -37,10 +37,30 @@ + #define SPI_DATA 0x14 + + /* ------------------------------------------------------------------------- */ ++/* GPIO */ ++ ++#define GPIO_OUTPUT 0x20 ++#define GPIO_INPUT 0x24 ++#define GPIO_DIRECTION 0x28 ++ ++/* ------------------------------------------------------------------------- */ ++/* MDIO */ ++ ++#define MDIO_CTRL 0x20 ++#define MDIO_ADR 0x24 ++#define MDIO_REG 0x28 ++#define MDIO_VAL 0x2C ++ ++/* ------------------------------------------------------------------------- */ + +-/* Interrupt controller */ +-/* How many MSI's are available depends on HW (Min 2 max 8) */ +-/* How many are usable also depends on Host platform */ ++#define BOARD_CONTROL 0x30 ++ ++/* ------------------------------------------------------------------------- */ ++ ++/* Interrupt controller ++ How many MSI's are available depends on HW (Min 2 max 8) ++ How many are usable also depends on Host platform ++*/ + + #define INTERRUPT_BASE (0x40) + +@@ -57,6 +77,9 @@ + #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20) + #define INTERRUPT_ACK (INTERRUPT_BASE + 0x20) + ++#define INTMASK_CLOCKGEN (0x00000001) ++#define INTMASK_TEMPMON (0x00000002) ++ + #define INTMASK_I2C1 (0x00000001) + #define INTMASK_I2C2 (0x00000002) + #define INTMASK_I2C3 (0x00000004) +@@ -81,6 +104,32 @@ + #define INTMASK_TSOUTPUT3 (0x00040000) + #define INTMASK_TSOUTPUT4 (0x00080000) + ++ ++/* Clock Generator ( Sil598 @ 0xAA I2c ) */ ++#define CLOCKGEN_BASE (0x80) ++#define CLOCKGEN_CONTROL (CLOCKGEN_BASE + 0x00) ++#define CLOCKGEN_INDEX (CLOCKGEN_BASE + 0x04) ++#define CLOCKGEN_WRITEDATA (CLOCKGEN_BASE + 0x08) ++#define CLOCKGEN_READDATA (CLOCKGEN_BASE + 0x0C) ++ ++/* DAC ( AD9781/AD9783 SPI ) */ ++#define DAC_BASE (0x090) ++#define DAC_CONTROL (DAC_BASE) ++#define DAC_WRITE_DATA (DAC_BASE+4) ++#define DAC_READ_DATA (DAC_BASE+8) ++ ++#define DAC_CONTROL_INSTRUCTION_REG (0xFF) ++#define DAC_CONTROL_STARTIO (0x100) ++#define DAC_CONTROL_RESET (0x200) ++ ++/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */ ++#define TEMPMON_BASE (0xA0) ++#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00) ++/* SHORT Temperature in °C x 256 */ ++#define TEMPMON_CORE (TEMPMON_BASE + 0x04) ++#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08) ++#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C) ++ + /* ------------------------------------------------------------------------- */ + /* I2C Master Controller */ + +@@ -90,19 +139,14 @@ + #define I2C_TIMING (0x04) + #define I2C_TASKLENGTH (0x08) /* High read, low write */ + #define I2C_TASKADDRESS (0x0C) /* High read, low write */ +- + #define I2C_MONITOR (0x1C) + +-#define I2C_BASE_1 (I2C_BASE + 0x00) +-#define I2C_BASE_2 (I2C_BASE + 0x20) +-#define I2C_BASE_3 (I2C_BASE + 0x40) +-#define I2C_BASE_4 (I2C_BASE + 0x60) +- + #define I2C_BASE_N(i) (I2C_BASE + (i) * 0x20) + + #define I2C_TASKMEM_BASE (0x1000) /* Byte offset */ +-#define I2C_TASKMEM_SIZE (0x1000) ++#define I2C_TASKMEM_SIZE (0x0800) + ++#define I2C_SPEED_666 (0x02010202) + #define I2C_SPEED_400 (0x04030404) + #define I2C_SPEED_200 (0x09080909) + #define I2C_SPEED_154 (0x0C0B0C0C) +@@ -117,35 +161,276 @@ + #define DMA_BASE_WRITE (0x100) + #define DMA_BASE_READ (0x140) + +-#define DMA_CONTROL (0x00) /* 64 */ +-#define DMA_ERROR (0x04) /* 65 ( only read instance ) */ ++#define DMA_CONTROL (0x00) ++#define DMA_ERROR (0x04) + +-#define DMA_DIAG_CONTROL (0x1C) /* 71 */ +-#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) /* 72 */ +-#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) /* 73 */ +-#define DMA_DIAG_TIMECOUNTER_LOW (0x28) /* 74 */ +-#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) /* 75 */ +-#define DMA_DIAG_RECHECKCOUNTER (0x30) /* 76 ( Split completions on read ) */ +-#define DMA_DIAG_WAITTIMEOUTINIT (0x34) /* 77 */ +-#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) /* 78 */ +-#define DMA_DIAG_WAITCOUNTER (0x3C) /* 79 */ ++#define DMA_DIAG_CONTROL (0x1C) ++#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) ++#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) ++#define DMA_DIAG_TIMECOUNTER_LOW (0x28) ++#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) ++#define DMA_DIAG_RECHECKCOUNTER (0x30) ++#define DMA_DIAG_WAITTIMEOUTINIT (0x34) ++#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) ++#define DMA_DIAG_WAITCOUNTER (0x3C) + + /* ------------------------------------------------------------------------- */ + /* DMA Buffer */ + + #define TS_INPUT_BASE (0x200) +-#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 16 + 0x00) ++#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00) ++#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04) + + #define TS_OUTPUT_BASE (0x280) +-#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 16 + 0x00) ++#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00) ++#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04) + + #define DMA_BUFFER_BASE (0x300) + +-#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 16 + 0x00) +-#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 16 + 0x04) +-#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 16 + 0x08) +-#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 16 + 0x0c) ++#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) ++#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04) ++#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08) ++#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c) + + #define DMA_BASE_ADDRESS_TABLE (0x2000) + #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512) + ++ ++/* ------------------------------------------------------------------------- */ ++ ++#define LNB_BASE (0x400) ++#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00) ++#define LNB_CMD (7ULL << 0) ++#define LNB_CMD_NOP 0 ++#define LNB_CMD_INIT 1 ++#define LNB_CMD_STATUS 2 ++#define LNB_CMD_LOW 3 ++#define LNB_CMD_HIGH 4 ++#define LNB_CMD_OFF 5 ++#define LNB_CMD_DISEQC 6 ++#define LNB_CMD_UNI 7 ++ ++#define LNB_BUSY (1ULL << 4) ++#define LNB_TONE (1ULL << 15) ++ ++#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04) ++#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08) ++#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c) ++#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) ++#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14) ++ ++/* ------------------------------------------------------------------------- */ ++/* CI Interface (only CI-Bridge) */ ++ ++#define CI_BASE (0x400) ++#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) ++ ++#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) ++#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) ++#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) ++#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) ++ ++#define CI_RESET_CAM (0x00000001) ++#define CI_POWER_ON (0x00000002) ++#define CI_ENABLE (0x00000004) ++#define CI_BLOCKIO_ENABLE (0x00000008) ++#define CI_BYPASS_DISABLE (0x00000010) ++#define CI_DISABLE_AUTO_OFF (0x00000020) ++ ++#define CI_CAM_READY (0x00010000) ++#define CI_CAM_DETECT (0x00020000) ++#define CI_READY (0x80000000) ++#define CI_BLOCKIO_ACTIVE (0x40000000) ++#define CI_BLOCKIO_RCVDATA (0x20000000) ++#define CI_BLOCKIO_SEND_PENDING (0x10000000) ++#define CI_BLOCKIO_SEND_COMPLETE (0x08000000) ++ ++#define CI_READ_CMD (0x40000000) ++#define CI_WRITE_CMD (0x80000000) ++ ++#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) ++#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) ++ ++#define CI_BLOCKIO_SEND_COMMAND (0x80000000) ++#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) ++#define CI_BLOCKIO_RCVDATA_ACK (0x40000000) ++ ++#define CI_BUFFER_BASE (0x3000) ++#define CI_BUFFER_SIZE (0x0800) ++#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2) ++ ++#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) ++#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) ++#define CI_BLOCKIO_SEND_BUFFER(i) \ ++ (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) ++ ++#define VCO1_BASE (0xC0) ++#define VCO1_CONTROL (VCO1_BASE + 0x00) ++#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */ ++/* 1 = Trigger write, resets when done */ ++#define VCO1_CONTROL_WRITE (0x00000001) ++/* 0 = Put VCO into power down */ ++#define VCO1_CONTROL_CE (0x00000002) ++/* Muxout from VCO (usually = Lock) */ ++#define VCO1_CONTROL_MUXOUT (0x00000004) ++ ++#define VCO2_BASE (0xC8) ++#define VCO2_CONTROL (VCO2_BASE + 0x00) ++#define VCO2_DATA (VCO2_BASE + 0x04) /* 24 Bit */ ++/* 1 = Trigger write, resets when done */ ++#define VCO2_CONTROL_WRITE (0x00000001) ++/* 0 = Put VCO into power down */ ++#define VCO2_CONTROL_CE (0x00000002) ++/* Muxout from VCO (usually = Lock) */ ++#define VCO2_CONTROL_MUXOUT (0x00000004) ++ ++#define VCO3_BASE (0xD0) ++#define VCO3_CONTROL (VCO3_BASE + 0x00) ++#define VCO3_DATA (VCO3_BASE + 0x04) /* 32 Bit */ ++/* 1 = Trigger write, resets when done */ ++#define VCO3_CONTROL_WRITE (0x00000001) ++/* 0 = Put VCO into power down */ ++#define VCO3_CONTROL_CE (0x00000002) ++/* Muxout from VCO (usually = Lock) */ ++#define VCO3_CONTROL_MUXOUT (0x00000004) ++ ++#define RF_ATTENUATOR (0xD8) ++/* 0x00 = 0 dB ++ 0x01 = 1 dB ++ ... ++ 0x1F = 31 dB ++*/ ++ ++#define RF_POWER (0xE0) ++#define RF_POWER_BASE (0xE0) ++#define RF_POWER_CONTROL (RF_POWER_BASE + 0x00) ++#define RF_POWER_DATA (RF_POWER_BASE + 0x04) ++ ++#define RF_POWER_CONTROL_START (0x00000001) ++#define RF_POWER_CONTROL_DONE (0x00000002) ++#define RF_POWER_CONTROL_VALIDMASK (0x00000700) ++#define RF_POWER_CONTROL_VALID (0x00000500) ++ ++ ++/* -------------------------------------------------------------------------- ++ Output control ++*/ ++ ++#define IQOUTPUT_BASE (0x240) ++#define IQOUTPUT_CONTROL (IQOUTPUT_BASE + 0x00) ++#define IQOUTPUT_CONTROL2 (IQOUTPUT_BASE + 0x04) ++#define IQOUTPUT_PEAK_DETECTOR (IQOUTPUT_BASE + 0x08) ++#define IQOUTPUT_POSTSCALER (IQOUTPUT_BASE + 0x0C) ++#define IQOUTPUT_PRESCALER (IQOUTPUT_BASE + 0x10) ++ ++#define IQOUTPUT_EQUALIZER_0 (IQOUTPUT_BASE + 0x14) ++#define IQOUTPUT_EQUALIZER_1 (IQOUTPUT_BASE + 0x18) ++#define IQOUTPUT_EQUALIZER_2 (IQOUTPUT_BASE + 0x1C) ++#define IQOUTPUT_EQUALIZER_3 (IQOUTPUT_BASE + 0x20) ++#define IQOUTPUT_EQUALIZER_4 (IQOUTPUT_BASE + 0x24) ++#define IQOUTPUT_EQUALIZER_5 (IQOUTPUT_BASE + 0x28) ++#define IQOUTPUT_EQUALIZER_6 (IQOUTPUT_BASE + 0x2C) ++#define IQOUTPUT_EQUALIZER_7 (IQOUTPUT_BASE + 0x30) ++#define IQOUTPUT_EQUALIZER_8 (IQOUTPUT_BASE + 0x34) ++#define IQOUTPUT_EQUALIZER_9 (IQOUTPUT_BASE + 0x38) ++#define IQOUTPUT_EQUALIZER_10 (IQOUTPUT_BASE + 0x3C) ++ ++#define IQOUTPUT_EQUALIZER(i) (IQOUTPUT_EQUALIZER_0 + (i) * 4) ++ ++#define IQOUTPUT_CONTROL_RESET (0x00000001) ++#define IQOUTPUT_CONTROL_ENABLE (0x00000002) ++#define IQOUTPUT_CONTROL_RESET_PEAK (0x00000004) ++#define IQOUTPUT_CONTROL_ENABLE_PEAK (0x00000008) ++#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010) ++ ++ ++/* Modulator Base */ ++ ++#define MODULATOR_BASE (0x200) ++#define MODULATOR_CONTROL (MODULATOR_BASE) ++#define MODULATOR_IQTABLE_END (MODULATOR_BASE+4) ++#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE+8) ++#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE+12) ++ ++#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK (0x000F0000) ++#define MODULATOR_IQTABLE_INDEX_IQ_MASK (0x00008000) ++#define MODULATOR_IQTABLE_INDEX_ADDRESS_MASK (0x000007FF) ++#define MODULATOR_IQTABLE_INDEX_SEL_I (0x00000000) ++#define MODULATOR_IQTABLE_INDEX_SEL_Q (MODULATOR_IQTABLE_INDEX_IQ_MASK) ++#define MODULATOR_IQTABLE_SIZE (2048) ++ ++ ++/* Modulator Channels */ ++ ++#define CHANNEL_BASE (0x400) ++#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00) ++#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04) ++#define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C) ++#define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10) ++#define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14) ++#define CHANNEL_PCR_ADJUST_INL(i) (CHANNEL_BASE + (i) * 64 + 0x18) ++#define CHANNEL_PCR_ADJUST_INH(i) (CHANNEL_BASE + (i) * 64 + 0x1C) ++#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20) ++#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24) ++#define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28) ++#define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C) ++ ++#define CHANNEL_CONTROL_RESET (0x00000001) ++#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002) ++#define CHANNEL_CONTROL_ENABLE_IQ (0x00000004) ++#define CHANNEL_CONTROL_ENABLE_SOURCE (0x00000008) ++#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010) ++#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100) ++ ++#define CHANNEL_CONTROL_RESET_ERROR (0x00010000) ++#define CHANNEL_CONTROL_BUSY (0x01000000) ++#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000) ++#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000) ++#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000) ++ ++#define CHANNEL_SETTINGS_QAM_MASK (0x00000007) ++#define CHANNEL_SETTINGS_QAM16 (0x00000000) ++#define CHANNEL_SETTINGS_QAM32 (0x00000001) ++#define CHANNEL_SETTINGS_QAM64 (0x00000002) ++#define CHANNEL_SETTINGS_QAM128 (0x00000003) ++#define CHANNEL_SETTINGS_QAM256 (0x00000004) ++ ++ ++/* OCTONET */ ++ ++#define ETHER_BASE (0x100) ++#define ETHER_CONTROL (ETHER_BASE + 0x00) ++#define ETHER_LENGTH (ETHER_BASE + 0x04) ++ ++#define RTP_MASTER_BASE (0x120) ++#define RTP_MASTER_CONTROL (RTP_MASTER_BASE + 0x00) ++#define RTP_RTCP_INTERRUPT (RTP_MASTER_BASE + 0x04) ++#define RTP_MASTER_RTCP_SETTINGS (RTP_MASTER_BASE + 0x0c) ++ ++#define STREAM_BASE (0x400) ++#define STREAM_CONTROL(i) (STREAM_BASE + (i) * 0x20 + 0x00) ++#define STREAM_RTP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x04) ++#define STREAM_RTCP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x08) ++#define STREAM_RTP_SETTINGS(i) (STREAM_BASE + (i) * 0x20 + 0x0c) ++#define STREAM_INSERT_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x10) ++ ++#define STREAM_PACKET_OFF(i) ((i) * 0x200) ++#define STREAM_PACKET_ADR(i) (0x2000 + (STREAM_PACKET_OFF(i))) ++ ++#define STREAM_PIDS(i) (0x4000 + (i) * 0x400) ++ ++#define TS_CAPTURE_BASE (0x0140) ++#define TS_CAPTURE_CONTROL (TS_CAPTURE_BASE + 0x00) ++#define TS_CAPTURE_PID (TS_CAPTURE_BASE + 0x04) ++#define TS_CAPTURE_RECEIVED (TS_CAPTURE_BASE + 0x08) ++#define TS_CAPTURE_TIMEOUT (TS_CAPTURE_BASE + 0x0c) ++#define TS_CAPTURE_TABLESECTION (TS_CAPTURE_BASE + 0x10) ++ ++#define TS_CAPTURE_MEMORY (0x7000) ++ ++#define PID_FILTER_BASE (0x800) ++#define PID_FILTER_SYSTEM_PIDS(i) (PID_FILTER_BASE + (i) * 0x20) ++#define PID_FILTER_PID(i, j) (PID_FILTER_BASE + (i) * 0x20 + (j) * 4) ++ ++ ++ +diff --git a/drivers/media/pci/ddbridge/ddbridge.c b/drivers/media/pci/ddbridge/ddbridge.c +new file mode 100644 +index 0000000..9784f10 +--- /dev/null ++++ b/drivers/media/pci/ddbridge/ddbridge.c +@@ -0,0 +1,470 @@ ++/* ++ * ddbridge.c: Digital Devices PCIe bridge driver ++ * ++ * Copyright (C) 2010-2013 Digital Devices GmbH ++ * Ralph Metzler ++ * Marcus Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*#define DDB_ALT_DMA*/ ++#define DDB_USE_WORK ++/*#define DDB_TEST_THREADED*/ ++ ++#include "ddbridge.h" ++#include "ddbridge-regs.h" ++ ++static struct workqueue_struct *ddb_wq; ++ ++static int adapter_alloc; ++module_param(adapter_alloc, int, 0444); ++MODULE_PARM_DESC(adapter_alloc, ++ "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); ++ ++#ifdef CONFIG_PCI_MSI ++static int msi = 1; ++module_param(msi, int, 0444); ++MODULE_PARM_DESC(msi, ++ " Control MSI interrupts: 0-disable, 1-enable (default)"); ++#endif ++ ++#include "ddbridge-core.c" ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static void ddb_unmap(struct ddb *dev) ++{ ++ if (dev->regs) ++ iounmap(dev->regs); ++ vfree(dev); ++} ++ ++ ++static void __devexit ddb_remove(struct pci_dev *pdev) ++{ ++ struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev); ++ ++ ddb_ports_detach(dev); ++ ddb_i2c_release(dev); ++ ++ ddbwritel(dev, 0, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0, MSI1_ENABLE); ++ if (dev->msi == 2) ++ free_irq(dev->pdev->irq + 1, dev); ++ free_irq(dev->pdev->irq, dev); ++#ifdef CONFIG_PCI_MSI ++ if (dev->msi) ++ pci_disable_msi(dev->pdev); ++#endif ++ ddb_ports_release(dev); ++ ddb_buffers_free(dev); ++ ddb_device_destroy(dev); ++ ++ ddb_unmap(dev); ++ pci_set_drvdata(pdev, 0); ++ pci_disable_device(pdev); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) ++#define __devinit ++#define __devinitdata ++#endif ++ ++static int __devinit ddb_probe(struct pci_dev *pdev, ++ const struct pci_device_id *id) ++{ ++ struct ddb *dev; ++ int stat = 0; ++ int irq_flag = IRQF_SHARED; ++ ++ if (pci_enable_device(pdev) < 0) ++ return -ENODEV; ++ ++ dev = vzalloc(sizeof(struct ddb)); ++ if (dev == NULL) ++ return -ENOMEM; ++ ++ dev->has_dma = 1; ++ dev->pdev = pdev; ++ dev->dev = &pdev->dev; ++ pci_set_drvdata(pdev, dev); ++ ++ dev->ids.vendor = id->vendor; ++ dev->ids.device = id->device; ++ dev->ids.subvendor = id->subvendor; ++ dev->ids.subdevice = id->subdevice; ++ ++ dev->info = (struct ddb_info *) id->driver_data; ++ pr_info("DDBridge driver detected: %s\n", dev->info->name); ++ ++ dev->regs_len = pci_resource_len(dev->pdev, 0); ++ dev->regs = ioremap(pci_resource_start(dev->pdev, 0), ++ pci_resource_len(dev->pdev, 0)); ++ if (!dev->regs) { ++ pr_err("DDBridge: not enough memory for register map\n"); ++ stat = -ENOMEM; ++ goto fail; ++ } ++ if (ddbreadl(dev, 0) == 0xffffffff) { ++ pr_err("DDBridge: cannot read registers\n"); ++ stat = -ENODEV; ++ goto fail; ++ } ++ ++ dev->ids.hwid = ddbreadl(dev, 0); ++ dev->ids.regmapid = ddbreadl(dev, 4); ++ ++ pr_info("HW %08x REGMAP %08x\n", ++ dev->ids.hwid, dev->ids.regmapid); ++ ++ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI1_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI2_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI3_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI4_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI5_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI6_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI7_ENABLE); ++ ++#ifdef CONFIG_PCI_MSI ++ if (msi && pci_msi_enabled()) { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) // OE ++ stat = pci_enable_msi_range(dev->pdev, 1, 2); ++ if (stat >= 1) { ++ dev->msi = stat; ++ pr_info(": Using %d MSI interrupts\n", dev->msi); ++ irq_flag = 0; ++ } else ++ pr_info(": MSI not available.\n"); ++#else ++ stat = pci_enable_msi_block(dev->pdev, 2); ++ if (stat == 0) { ++ dev->msi = 1; ++ pr_info("DDBrige using 2 MSI interrupts\n"); ++ } ++ if (stat == 1) ++ stat = pci_enable_msi(dev->pdev); ++ if (stat < 0) { ++ pr_info(": MSI not available.\n"); ++ } else { ++ irq_flag = 0; ++ dev->msi++; ++ } ++#endif ++ } ++ if (dev->msi == 2) { ++ stat = request_irq(dev->pdev->irq, irq_handler0, ++ irq_flag, "ddbridge", (void *) dev); ++ if (stat < 0) ++ goto fail0; ++ stat = request_irq(dev->pdev->irq + 1, irq_handler1, ++ irq_flag, "ddbridge", (void *) dev); ++ if (stat < 0) { ++ free_irq(dev->pdev->irq, dev); ++ goto fail0; ++ } ++ } else ++#endif ++ { ++#ifdef DDB_TEST_THREADED ++ stat = request_threaded_irq(dev->pdev->irq, irq_handler, ++ irq_thread, ++ irq_flag, ++ "ddbridge", (void *) dev); ++#else ++ stat = request_irq(dev->pdev->irq, irq_handler, ++ irq_flag, "ddbridge", (void *) dev); ++#endif ++ if (stat < 0) ++ goto fail0; ++ } ++ ddbwritel(dev, 0, DMA_BASE_READ); ++ if (dev->info->type != DDB_MOD) ++ ddbwritel(dev, 0, DMA_BASE_WRITE); ++ ++ /*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/ ++ if (dev->msi == 2) { ++ ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0x0000000f, MSI1_ENABLE); ++ } else { ++ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0x00000000, MSI1_ENABLE); ++ } ++ mutex_init(&dev->lnb_lock); ++ if (ddb_i2c_init(dev) < 0) ++ goto fail1; ++ ddb_ports_init(dev); ++ if (ddb_buffers_alloc(dev) < 0) { ++ pr_info(": Could not allocate buffer memory\n"); ++ goto fail2; ++ } ++ if (ddb_ports_attach(dev) < 0) ++ goto fail3; ++ ++ /* ignore if this fails */ ++ ddb_device_create(dev); ++ ++ if (dev->info->fan_num) { ++ ddbwritel(dev, 1, GPIO_DIRECTION); ++ ddbwritel(dev, 1, GPIO_OUTPUT); ++ } ++ if (dev->info->type == DDB_MOD) ++ ddbridge_mod_init(dev); ++ ++ return 0; ++ ++fail3: ++ ddb_ports_detach(dev); ++ pr_err("fail3\n"); ++ ddb_ports_release(dev); ++fail2: ++ pr_err("fail2\n"); ++ ddb_buffers_free(dev); ++ ddb_i2c_release(dev); ++fail1: ++ pr_err("fail1\n"); ++ ddbwritel(dev, 0, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0, MSI1_ENABLE); ++ free_irq(dev->pdev->irq, dev); ++ if (dev->msi == 2) ++ free_irq(dev->pdev->irq + 1, dev); ++fail0: ++ pr_err("fail0\n"); ++ if (dev->msi) ++ pci_disable_msi(dev->pdev); ++fail: ++ pr_err("fail\n"); ++ ddb_unmap(dev); ++ pci_set_drvdata(pdev, 0); ++ pci_disable_device(pdev); ++ return -1; ++} ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static struct ddb_regset octopus_i2c = { ++ .base = 0x80, ++ .num = 0x04, ++ .size = 0x20, ++}; ++ ++static struct ddb_regmap octopus_map = { ++ .i2c = &octopus_i2c, ++}; ++ ++static struct ddb_info ddb_none = { ++ .type = DDB_NONE, ++ .name = "unknown Digital Devices PCIe card, install newer driver", ++ .regmap = &octopus_map, ++}; ++ ++static struct ddb_info ddb_octopus = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++}; ++ ++static struct ddb_info ddb_octopusv3 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus V3 DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++}; ++ ++static struct ddb_info ddb_octopus_le = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus LE DVB adapter", ++ .port_num = 2, ++ .i2c_num = 2, ++}; ++ ++static struct ddb_info ddb_octopus_oem = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus OEM", ++ .port_num = 4, ++ .i2c_num = 4, ++ .led_num = 1, ++ .fan_num = 1, ++ .temp_num = 1, ++ .temp_bus = 0, ++}; ++ ++static struct ddb_info ddb_octopus_mini = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus Mini", ++ .port_num = 4, ++ .i2c_num = 4, ++}; ++ ++static struct ddb_info ddb_v6 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Cine S2 V6 DVB adapter", ++ .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_v6_5 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Cine S2 V6.5 DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++}; ++ ++static struct ddb_info ddb_v7 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Cine S2 V7 DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++ .board_control = 2, ++}; ++ ++static struct ddb_info ddb_s2_48 = { ++ .type = DDB_OCTOPUS_MAX, ++ .name = "Digital Devices Cine S2 4/8", ++ .port_num = 4, ++ .i2c_num = 1, ++ .board_control = 1, ++}; ++ ++static struct ddb_info ddb_ctv7 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Cine CT V7 DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++ .board_control = 3, ++}; ++ ++static struct ddb_info ddb_satixS2v3 = { ++ .type = DDB_OCTOPUS, ++ .name = "Mystique SaTiX-S2 V3 DVB adapter", ++ .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_ci = { ++ .type = DDB_OCTOPUS_CI, ++ .name = "Digital Devices Octopus CI", ++ .port_num = 4, ++ .i2c_num = 2, ++}; ++ ++static struct ddb_info ddb_cis = { ++ .type = DDB_OCTOPUS_CI, ++ .name = "Digital Devices Octopus CI single", ++ .port_num = 3, ++ .i2c_num = 2, ++}; ++ ++static struct ddb_info ddb_dvbct = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices DVBCT V6.1 DVB adapter", ++ .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_mod = { ++ .type = DDB_MOD, ++ .name = "Digital Devices DVB-C modulator", ++ .port_num = 10, ++ .temp_num = 1, ++}; ++ ++#define DDVID 0xdd01 /* Digital Devices Vendor ID */ ++ ++#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ ++ .vendor = _vend, .device = _dev, \ ++ .subvendor = _subvend, .subdevice = _subdev, \ ++ .driver_data = (unsigned long)&_driverdata } ++ ++static const struct pci_device_id ddb_id_tbl[] __devinitconst = { ++ DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), ++ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), ++ DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), ++ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), ++ DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7), ++ DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7), ++ DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7), ++ DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48), ++ DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), ++ DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), ++ DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod), ++ /* in case sub-ids got deleted in flash */ ++ DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), ++ DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none), ++ DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none), ++ {0} ++}; ++MODULE_DEVICE_TABLE(pci, ddb_id_tbl); ++ ++static struct pci_driver ddb_pci_driver = { ++ .name = "ddbridge", ++ .id_table = ddb_id_tbl, ++ .probe = ddb_probe, ++ .remove = ddb_remove, ++}; ++ ++static __init int module_init_ddbridge(void) ++{ ++ int stat = -1; ++ ++ pr_info("Digital Devices PCIE bridge driver " ++ DDBRIDGE_VERSION ++ ", Copyright (C) 2010-14 Digital Devices GmbH\n"); ++ if (ddb_class_create() < 0) ++ return -1; ++ ddb_wq = create_workqueue("ddbridge"); ++ if (ddb_wq == NULL) ++ goto exit1; ++ stat = pci_register_driver(&ddb_pci_driver); ++ if (stat < 0) ++ goto exit2; ++ return stat; ++exit2: ++ destroy_workqueue(ddb_wq); ++exit1: ++ ddb_class_destroy(); ++ return stat; ++} ++ ++static __exit void module_exit_ddbridge(void) ++{ ++ pci_unregister_driver(&ddb_pci_driver); ++ destroy_workqueue(ddb_wq); ++ ddb_class_destroy(); ++} ++ ++module_init(module_init_ddbridge); ++module_exit(module_exit_ddbridge); ++ ++MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); ++MODULE_AUTHOR("Ralph Metzler, Metzler Brothers Systementwicklung"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(DDBRIDGE_VERSION); +diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h +index be87fbd..a02e91a 100644 +--- a/drivers/media/pci/ddbridge/ddbridge.h ++++ b/drivers/media/pci/ddbridge/ddbridge.h +@@ -1,7 +1,8 @@ + /* + * ddbridge.h: Digital Devices PCIe bridge driver + * +- * Copyright (C) 2010-2011 Digital Devices GmbH ++ * Copyright (C) 2010-2014 Digital Devices GmbH ++ * Ralph Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +@@ -24,16 +25,51 @@ + #ifndef _DDBRIDGE_H_ + #define _DDBRIDGE_H_ + ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) ++#define __devexit ++#define __devinit ++#define __devinitconst ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ + #include + #include + #include + #include + #include + #include +-#include ++#include ++#include ++#include ++ + #include + #include ++#include ++#include + ++#include "dvb_netstream.h" + #include "dmxdev.h" + #include "dvbdev.h" + #include "dvb_demux.h" +@@ -41,95 +77,167 @@ + #include "dvb_ringbuffer.h" + #include "dvb_ca_en50221.h" + #include "dvb_net.h" ++ ++#include "tda18271c2dd.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "lnbh24.h" ++#include "drxk.h" ++#include "stv0367.h" ++#include "stv0367dd.h" ++#include "tda18212.h" ++#include "tda18212dd.h" ++#include "cxd2843.h" + #include "cxd2099.h" ++#include "stv0910.h" ++#include "stv6111.h" ++#include "lnbh25.h" + + #define DDB_MAX_I2C 4 +-#define DDB_MAX_PORT 4 ++#define DDB_MAX_PORT 10 + #define DDB_MAX_INPUT 8 +-#define DDB_MAX_OUTPUT 4 ++#define DDB_MAX_OUTPUT 10 ++ ++struct ddb_regset { ++ u32 base; ++ u32 num; ++ u32 size; ++}; ++ ++struct ddb_regmap { ++ struct ddb_regset *i2c; ++ struct ddb_regset *i2c_buf; ++ struct ddb_regset *dma; ++ struct ddb_regset *dma_buf; ++ struct ddb_regset *input; ++ struct ddb_regset *output; ++ struct ddb_regset *channel; ++ struct ddb_regset *ci; ++ struct ddb_regset *pid_filter; ++ struct ddb_regset *ns; ++}; ++ ++struct ddb_ids { ++ u16 vendor; ++ u16 device; ++ u16 subvendor; ++ u16 subdevice; ++ ++ u32 hwid; ++ u32 regmapid; ++ u32 devid; ++ u32 mac; ++}; + + struct ddb_info { + int type; + #define DDB_NONE 0 + #define DDB_OCTOPUS 1 ++#define DDB_OCTOPUS_CI 2 ++#define DDB_MOD 3 ++#define DDB_OCTONET 4 ++#define DDB_OCTOPUS_MAX 5 + char *name; +- int port_num; +- u32 port_type[DDB_MAX_PORT]; ++ u8 port_num; ++ u8 i2c_num; ++ u8 led_num; ++ u8 fan_num; ++ u8 temp_num; ++ u8 temp_bus; ++ u8 board_control; ++ u8 ns_num; ++ u8 mdio_num; ++ struct ddb_regmap *regmap; + }; + +-/* DMA_SIZE MUST be divisible by 188 and 128 !!! */ + +-#define INPUT_DMA_MAX_BUFS 32 /* hardware table limit */ ++/* DMA_SIZE MUST be smaller than 256k and ++ MUST be divisible by 188 and 128 !!! */ ++ ++#define DMA_MAX_BUFS 32 /* hardware table limit */ ++ + #define INPUT_DMA_BUFS 8 + #define INPUT_DMA_SIZE (128*47*21) ++#define INPUT_DMA_IRQ_DIV 1 + +-#define OUTPUT_DMA_MAX_BUFS 32 + #define OUTPUT_DMA_BUFS 8 + #define OUTPUT_DMA_SIZE (128*47*21) ++#define OUTPUT_DMA_IRQ_DIV 1 + + struct ddb; + struct ddb_port; + +-struct ddb_input { +- struct ddb_port *port; ++struct ddb_dma { ++ void *io; + u32 nr; +- int attached; +- +- dma_addr_t pbuf[INPUT_DMA_MAX_BUFS]; +- u8 *vbuf[INPUT_DMA_MAX_BUFS]; +- u32 dma_buf_num; +- u32 dma_buf_size; ++ dma_addr_t pbuf[DMA_MAX_BUFS]; ++ u8 *vbuf[DMA_MAX_BUFS]; ++ u32 num; ++ u32 size; ++ u32 div; ++ u32 bufreg; + ++#ifdef DDB_USE_WORK ++ struct work_struct work; ++#else + struct tasklet_struct tasklet; ++#endif + spinlock_t lock; + wait_queue_head_t wq; + int running; + u32 stat; ++ u32 ctrl; + u32 cbuf; + u32 coff; ++}; + +- struct dvb_adapter adap; ++struct ddb_dvb { ++ struct dvb_adapter *adap; ++ int adap_registered; + struct dvb_device *dev; + struct dvb_frontend *fe; + struct dvb_frontend *fe2; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dvb_net dvbnet; ++ struct dvb_netstream dvbns; + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; + int users; +- int (*gate_ctrl)(struct dvb_frontend *, int); ++ u32 attached; ++ u8 input; ++ ++ int (*i2c_gate_ctrl)(struct dvb_frontend *, int); ++ int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); ++ int (*set_input)(struct dvb_frontend *fe); + }; + +-struct ddb_output { ++struct ddb_ci { ++ struct dvb_ca_en50221 en; + struct ddb_port *port; + u32 nr; +- dma_addr_t pbuf[OUTPUT_DMA_MAX_BUFS]; +- u8 *vbuf[OUTPUT_DMA_MAX_BUFS]; +- u32 dma_buf_num; +- u32 dma_buf_size; +- struct tasklet_struct tasklet; +- spinlock_t lock; +- wait_queue_head_t wq; +- int running; +- u32 stat; +- u32 cbuf; +- u32 coff; ++ struct mutex lock; ++}; + +- struct dvb_adapter adap; +- struct dvb_device *dev; ++struct ddb_io { ++ struct ddb_port *port; ++ u32 nr; ++ struct ddb_dma *dma; ++ struct ddb_io *redo; ++ struct ddb_io *redi; + }; + ++#define ddb_output ddb_io ++#define ddb_input ddb_io ++ + struct ddb_i2c { + struct ddb *dev; + u32 nr; + struct i2c_adapter adap; +- struct i2c_adapter adap2; + u32 regs; + u32 rbuf; + u32 wbuf; +- int done; +- wait_queue_head_t wq; ++ struct completion completion; + }; + + struct ddb_port { +@@ -141,43 +249,250 @@ struct ddb_port { + #define DDB_PORT_NONE 0 + #define DDB_PORT_CI 1 + #define DDB_PORT_TUNER 2 +- u32 type; +-#define DDB_TUNER_NONE 0 +-#define DDB_TUNER_DVBS_ST 1 +-#define DDB_TUNER_DVBS_ST_AA 2 +-#define DDB_TUNER_DVBCT_TR 16 +-#define DDB_TUNER_DVBCT_ST 17 +- u32 adr; ++#define DDB_PORT_LOOP 3 ++#define DDB_PORT_MOD 4 ++ char *name; ++ u32 type; ++#define DDB_TUNER_NONE 0 ++#define DDB_TUNER_DVBS_ST 1 ++#define DDB_TUNER_DVBS_ST_AA 2 ++#define DDB_TUNER_DVBCT_TR 3 ++#define DDB_TUNER_DVBCT_ST 4 ++#define DDB_CI_INTERNAL 5 ++#define DDB_CI_EXTERNAL_SONY 6 ++#define DDB_TUNER_DVBCT2_SONY_P 7 ++#define DDB_TUNER_DVBC2T2_SONY_P 8 ++#define DDB_TUNER_ISDBT_SONY_P 9 ++#define DDB_TUNER_DVBS_STV0910_P 10 ++#define DDB_TUNER_MXL5XX 11 + ++#define DDB_TUNER_XO2 16 ++#define DDB_TUNER_DVBS_STV0910 16 ++#define DDB_TUNER_DVBCT2_SONY 17 ++#define DDB_TUNER_ISDBT_SONY 18 ++#define DDB_TUNER_DVBC2T2_SONY 19 ++#define DDB_TUNER_ATSC_ST 20 ++#define DDB_TUNER_DVBC2T2_ST 21 ++ ++ u32 adr; + struct ddb_input *input[2]; + struct ddb_output *output; + struct dvb_ca_en50221 *en; ++ struct ddb_dvb dvb[2]; ++ u32 gap; ++ u32 obr; ++}; ++ ++ ++struct mod_base { ++ u32 frequency; ++ ++ u32 flat_start; ++ u32 flat_end; ++}; ++ ++struct mod_state { ++ u32 modulation; ++ u64 obitrate; ++ u64 ibitrate; ++ u32 pcr_correction; ++ ++ u32 rate_inc; ++ u32 Control; ++ u32 State; ++ u32 StateCounter; ++ s32 LastPCRAdjust; ++ s32 PCRAdjustSum; ++ s32 InPacketsSum; ++ s32 OutPacketsSum; ++ s64 PCRIncrement; ++ s64 PCRDecrement; ++ s32 PCRRunningCorr; ++ u32 OutOverflowPacketCount; ++ u32 InOverflowPacketCount; ++ u32 LastOutPacketCount; ++ u32 LastInPacketCount; ++ u64 LastOutPackets; ++ u64 LastInPackets; ++ u32 MinInputPackets; ++}; ++ ++#define CM_STARTUP_DELAY 2 ++#define CM_AVERAGE 20 ++#define CM_GAIN 10 ++ ++#define HW_LSB_SHIFT 12 ++#define HW_LSB_MASK 0x1000 ++ ++#define CM_IDLE 0 ++#define CM_STARTUP 1 ++#define CM_ADJUST 2 ++ ++#define TS_CAPTURE_LEN (4096) ++ ++/* net streaming hardware block */ ++ ++#define DDB_NS_MAX 15 ++ ++struct ddb_ns { ++ struct ddb_input *input; ++ int nr; ++ int fe; ++ u32 rtcp_udplen; ++ u32 rtcp_len; ++ u32 ts_offset; ++ u32 udplen; ++ u8 p[512]; + }; + + struct ddb { + struct pci_dev *pdev; +- unsigned char __iomem *regs; ++ struct platform_device *pfdev; ++ struct device *dev; ++ struct ddb_ids ids; ++ struct ddb_info *info; ++ int msi; ++ struct workqueue_struct *wq; ++ u32 has_dma; ++ u32 has_ns; ++ ++ struct ddb_regmap regmap; ++ unsigned char *regs; ++ u32 regs_len; + struct ddb_port port[DDB_MAX_PORT]; + struct ddb_i2c i2c[DDB_MAX_I2C]; + struct ddb_input input[DDB_MAX_INPUT]; + struct ddb_output output[DDB_MAX_OUTPUT]; ++ struct dvb_adapter adap[DDB_MAX_INPUT]; ++ struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; ++ ++ void (*handler[32])(unsigned long); ++ unsigned long handler_data[32]; + + struct device *ddb_dev; +- int nr; ++ u32 ddb_dev_users; ++ u32 nr; + u8 iobuf[1028]; + +- struct ddb_info *info; +- int msi; ++ u8 leds; ++ u32 ts_irq; ++ u32 i2c_irq; ++ ++ int ns_num; ++ struct ddb_ns ns[DDB_NS_MAX]; ++ struct mutex mutex; ++ ++ struct dvb_device *nsd_dev; ++ u8 tsbuf[TS_CAPTURE_LEN]; ++ ++ struct mod_base mod_base; ++ struct mod_state mod[10]; ++ ++ struct mutex octonet_i2c_lock; ++ struct mutex lnb_lock; ++ u32 lnb_tone; + }; + ++ + /****************************************************************************/ + +-#define ddbwritel(_val, _adr) writel((_val), \ +- dev->regs+(_adr)) +-#define ddbreadl(_adr) readl(dev->regs+(_adr)) +-#define ddbcpyto(_adr, _src, _count) memcpy_toio(dev->regs+(_adr), (_src), (_count)) +-#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), dev->regs+(_adr), (_count)) ++static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr) ++{ ++ writeb(val, (char *) (dev->regs+(adr))); ++} ++ ++static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr) ++{ ++ writel(val, (char *) (dev->regs+(adr))); ++} ++ ++static inline void ddbwritew(struct ddb *dev, u16 val, u32 adr) ++{ ++ writew(val, (char *) (dev->regs+(adr))); ++} ++ ++static inline u32 ddbreadl(struct ddb *dev, u32 adr) ++{ ++ return readl((char *) (dev->regs+(adr))); ++} ++ ++static inline u32 ddbreadb(struct ddb *dev, u32 adr) ++{ ++ return readb((char *) (dev->regs+(adr))); ++} + ++#define ddbcpyto(_dev, _adr, _src, _count) \ ++ memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count)) ++ ++#define ddbcpyfrom(_dev, _dst, _adr, _count) \ ++ memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count)) ++ ++#define ddbmemset(_dev, _adr, _val, _count) \ ++ memset_io((char *) (_dev->regs + (_adr)), (_val), (_count)) ++ ++ ++/****************************************************************************/ ++/****************************************************************************/ + /****************************************************************************/ + ++#define dd_uint8 u8 ++#define dd_uint16 u16 ++#define dd_int16 s16 ++#define dd_uint32 u32 ++#define dd_int32 s32 ++#define dd_uint64 u64 ++#define dd_int64 s64 ++ ++#define DDMOD_FLASH_START 0x1000 ++ ++struct DDMOD_FLASH_DS { ++ dd_uint32 Symbolrate; /* kSymbols/s */ ++ dd_uint32 DACFrequency; /* kHz */ ++ dd_uint16 FrequencyResolution; /* kHz */ ++ dd_uint16 IQTableLength; ++ dd_uint16 FrequencyFactor; ++ dd_int16 PhaseCorr; /* TBD */ ++ dd_uint32 Control2; ++ dd_uint16 PostScaleI; ++ dd_uint16 PostScaleQ; ++ dd_uint16 PreScale; ++ dd_int16 EQTap[11]; ++ dd_uint16 FlatStart; ++ dd_uint16 FlatEnd; ++ dd_uint32 FlashOffsetPrecalculatedIQTables; /* 0 = none */ ++ dd_uint8 Reserved[28]; ++ ++}; ++ ++struct DDMOD_FLASH { ++ dd_uint32 Magic; ++ dd_uint16 Version; ++ dd_uint16 DataSets; ++ ++ dd_uint16 VCORefFrequency; /* MHz */ ++ dd_uint16 VCO1Frequency; /* MHz */ ++ dd_uint16 VCO2Frequency; /* MHz */ ++ ++ dd_uint16 DACAux1; /* TBD */ ++ dd_uint16 DACAux2; /* TBD */ ++ ++ dd_uint8 Reserved1[238]; ++ ++ struct DDMOD_FLASH_DS DataSet[1]; ++}; ++ ++#define DDMOD_FLASH_MAGIC 0x5F564d5F ++ ++ ++int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg); ++int ddbridge_mod_init(struct ddb *dev); ++void ddbridge_mod_output_stop(struct ddb_output *output); ++void ddbridge_mod_output_start(struct ddb_output *output); ++void ddbridge_mod_rate_handler(unsigned long data); ++ ++ ++int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len); ++ ++#define DDBRIDGE_VERSION "0.9.15" ++ + #endif +diff --git a/drivers/media/pci/ddbridge/octonet.c b/drivers/media/pci/ddbridge/octonet.c +new file mode 100644 +index 0000000..e803e73 +--- /dev/null ++++ b/drivers/media/pci/ddbridge/octonet.c +@@ -0,0 +1,199 @@ ++/* ++ * octonet.c: Digital Devices network tuner driver ++ * ++ * Copyright (C) 2012-14 Digital Devices GmbH ++ * Ralph Metzler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include "ddbridge.h" ++#include "ddbridge-regs.h" ++ ++#include ++ ++static int adapter_alloc = 3; ++module_param(adapter_alloc, int, 0444); ++MODULE_PARM_DESC(adapter_alloc, ++"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); ++ ++#define DVB_NSD ++ ++#include "ddbridge-core.c" ++ ++static struct ddb_info ddb_octonet = { ++ .type = DDB_OCTONET, ++ .name = "Digital Devices OctopusNet network DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++ .ns_num = 12, ++ .mdio_num = 1, ++}; ++ ++static void octonet_unmap(struct ddb *dev) ++{ ++ if (dev->regs) ++ iounmap(dev->regs); ++ vfree(dev); ++} ++ ++static int __exit octonet_remove(struct platform_device *pdev) ++{ ++ struct ddb *dev; ++ ++ dev = platform_get_drvdata(pdev); ++ ++ ddb_nsd_detach(dev); ++ ddb_ports_detach(dev); ++ ddb_i2c_release(dev); ++ ++ ddbwritel(dev, 0, ETHER_CONTROL); ++ ddbwritel(dev, 0, INTERRUPT_ENABLE); ++ free_irq(platform_get_irq(dev->pfdev, 0), dev); ++ ++ ddb_ports_release(dev); ++ ddb_device_destroy(dev); ++ octonet_unmap(dev); ++ platform_set_drvdata(pdev, 0); ++ return 0; ++} ++ ++static int __init octonet_probe(struct platform_device *pdev) ++{ ++ struct ddb *dev; ++ struct resource *regs; ++ int i; ++ ++ dev = vzalloc(sizeof(struct ddb)); ++ if (!dev) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, dev); ++ dev->dev = &pdev->dev; ++ dev->pfdev = pdev; ++ dev->info = &ddb_octonet; ++ ++ mutex_init(&dev->mutex); ++ regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0); ++ if (!regs) ++ return -ENXIO; ++ dev->regs_len = (regs->end - regs->start) + 1; ++ dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n", ++ (u32) regs->start, (u32) dev->regs_len); ++ dev->regs = ioremap(regs->start, dev->regs_len); ++ if (!dev->regs) { ++ dev_err(dev->dev, "ioremap failed\n"); ++ return -ENOMEM; ++ } ++ ++ dev->ids.hwid = ddbreadl(dev, 0); ++ dev->ids.regmapid = ddbreadl(dev, 4); ++ dev->ids.devid = ddbreadl(dev, 8); ++ dev->ids.mac = ddbreadl(dev, 12); ++ ++ dev->ids.vendor = dev->ids.devid & 0xffff; ++ dev->ids.device = dev->ids.devid >> 16; ++ dev->ids.subvendor = dev->ids.devid & 0xffff; ++ dev->ids.subdevice = dev->ids.devid >> 16; ++ ++ pr_info("HW %08x REGMAP %08x\n", dev->ids.hwid, dev->ids.regmapid); ++ pr_info("MAC %08x DEVID %08x\n", dev->ids.mac, dev->ids.devid); ++ ++ ddbwritel(dev, 0, ETHER_CONTROL); ++ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS); ++ for (i = 0; i < 16; i++) ++ ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i)); ++ usleep_range(5000, 6000); ++ ++ if (request_irq(platform_get_irq(dev->pfdev, 0), irq_handler, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, ++ "octonet-dvb", (void *) dev) < 0) ++ goto fail; ++ ++ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0x1, ETHER_CONTROL); ++ ddbwritel(dev, 14 + (vlan ? 4 : 0), ETHER_LENGTH); ++ ++ ++ mutex_init(&dev->octonet_i2c_lock); ++ if (ddb_i2c_init(dev) < 0) ++ goto fail1; ++ ++ ddb_ports_init(dev); ++ if (ddb_ports_attach(dev) < 0) ++ goto fail3; ++ ++ ddb_nsd_attach(dev); ++ ++ ddb_device_create(dev); ++ ++ return 0; ++ ++fail3: ++ ddb_ports_detach(dev); ++ dev_err(dev->dev, "fail3\n"); ++fail1: ++ dev_err(dev->dev, "fail1\n"); ++fail: ++ dev_err(dev->dev, "fail\n"); ++ ddbwritel(dev, 0, ETHER_CONTROL); ++ ddbwritel(dev, 0, INTERRUPT_ENABLE); ++ octonet_unmap(dev); ++ platform_set_drvdata(pdev, 0); ++ return 0; ++} ++ ++static struct platform_driver octonet_driver = { ++ .remove = __exit_p(octonet_remove), ++ .probe = octonet_probe, ++ .driver = { ++ .name = "octonet-dvb", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static __init int init_octonet(void) ++{ ++ int res; ++ ++ pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION ++ ", Copyright (C) 2010-14 Digital Devices GmbH\n"); ++ res = ddb_class_create(); ++ if (res) ++ return res; ++ res = platform_driver_probe(&octonet_driver, octonet_probe); ++ if (res) { ++ ddb_class_destroy(); ++ return res; ++ } ++ return 0; ++} ++ ++static __exit void exit_octonet(void) ++{ ++ platform_driver_unregister(&octonet_driver); ++ ddb_class_destroy(); ++} ++ ++module_init(init_octonet); ++module_exit(exit_octonet); ++ ++MODULE_DESCRIPTION("GPL"); ++MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("0.5"); +diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig +index 637d506..3896c12 100644 +--- a/drivers/media/pci/ngene/Kconfig ++++ b/drivers/media/pci/ngene/Kconfig +@@ -1,12 +1,16 @@ + config DVB_NGENE + tristate "Micronas nGene support" + depends on DVB_CORE && PCI && I2C ++ select DVB_CXD2099 + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + Support for Micronas PCI express cards with nGene bridge. +diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile +index 5c0b5d6..42c036a 100644 +--- a/drivers/media/pci/ngene/Makefile ++++ b/drivers/media/pci/ngene/Makefile +@@ -2,7 +2,8 @@ + # Makefile for the nGene device driver + # + +-ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o ++ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-av.o \ ++ ngene-eeprom.o ngene-dvb.o + + obj-$(CONFIG_DVB_NGENE) += ngene.o + +diff --git a/drivers/media/pci/ngene/ngene-av.c b/drivers/media/pci/ngene/ngene-av.c +new file mode 100644 +index 0000000..a86459e +--- /dev/null ++++ b/drivers/media/pci/ngene/ngene-av.c +@@ -0,0 +1,348 @@ ++/* ++ * ngene-av.c: nGene PCIe bridge driver - DVB video/audio support ++ * ++ * Copyright (C) 2005-2007 Micronas ++ * ++ * Copyright (C) 2008-2009 Ralph Metzler ++ * Modifications for new nGene firmware, ++ * support for EEPROM-copying, ++ * support for new dual DVB-S2 card prototype ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/* This file provides the support functions for DVB audio/video devices ++ (/dev/dvb/adapter0/[video|audio]), not to be confused with V4L2 support */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ngene.h" ++ ++#if 0 ++ ++static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) ++{ ++ struct ngene_channel *chan = priv; ++ struct ngene *dev = chan->dev; ++ ++ if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { ++ dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); ++ wake_up_interruptible(&dev->ain_rbuf.queue); ++ } else ++ printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); ++ ++ return 0; ++} ++ ++static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) ++{ ++ ++ struct ngene_channel *chan = priv; ++ struct ngene *dev = chan->dev; ++ ++ if (len >= 1920 * 1080) ++ len = 1920 * 1080; ++ if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { ++ dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); ++ wake_up_interruptible(&dev->vin_rbuf.queue); ++ } else { ++ ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ ++ } ++ return 0; ++} ++ ++static ssize_t audio_write(struct file *file, ++ const char *buf, size_t count, loff_t *ppos) ++{ ++ return -EINVAL; ++} ++ ++ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left; ++ int avail; ++ ++ left = count; ++ while (left) { ++ if (wait_event_interruptible( ++ dev->ain_rbuf.queue, ++ dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) ++ return -EAGAIN; ++ avail = dvb_ringbuffer_avail(&dev->ain_rbuf); ++ if (avail > left) ++ avail = left; ++ dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++static int audio_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan2 = &chan->dev->channel[2]; ++ int ret; ++ ++ ret = dvb_generic_open(inode, file); ++ if (ret < 0) ++ return ret; ++ dvb_ringbuffer_flush(&dev->ain_rbuf); ++ ++ chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; ++ chan2->pBufferExchange = ain_exchange; ++ ngene_command_stream_control(chan2->dev, chan2->number, 0x80, ++ SMODE_AUDIO_CAPTURE, 0); ++ return ret; ++} ++ ++static int audio_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan2 = &chan->dev->channel[2]; ++ ++ ngene_command_stream_control(dev, 2, 0, 0, 0); ++ chan2->pBufferExchange = 0; ++ ++ return dvb_generic_release(inode, file); ++} ++ ++static const struct file_operations audio_fops = { ++ .owner = THIS_MODULE, ++ .read = audio_read, ++ .write = audio_write, ++ .open = audio_open, ++ .release = audio_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = 0, ++ .readers = -1, ++ .writers = 1, ++ .users = 1, ++ .fops = &audio_fops, ++}; ++ ++static int video_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan0 = &chan->dev->channel[0]; ++ int ret; ++ ++ ret = dvb_generic_open(inode, file); ++ if (ret < 0) ++ return ret; ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) ++ return ret; ++ dvb_ringbuffer_flush(&dev->vin_rbuf); ++ ++ chan0->nBytesPerLine = 1920 * 2; ++ chan0->nLines = 540; ++ chan0->Capture1Length = 1920 * 2 * 540; ++ chan0->pBufferExchange = vcap_exchange; ++ chan0->itumode = 2; ++ ngene_command_stream_control(chan0->dev, chan0->number, ++ 0x80, SMODE_VIDEO_CAPTURE, 0); ++ return ret; ++} ++ ++static int video_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan0 = &chan->dev->channel[0]; ++ ++ ngene_command_stream_control(dev, 0, 0, 0, 0); ++ chan0->pBufferExchange = 0; ++ ++ return dvb_generic_release(inode, file); ++} ++ ++static ssize_t video_write(struct file *file, ++ const char *buf, size_t count, loff_t *ppos) ++{ ++ return -EINVAL; ++} ++ ++ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left, avail; ++ ++ left = count; ++ while (left) { ++ if (wait_event_interruptible( ++ dev->vin_rbuf.queue, ++ dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) ++ return -EAGAIN; ++ avail = dvb_ringbuffer_avail(&dev->vin_rbuf); ++ if (avail > left) ++ avail = left; ++ dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++/* Why is this not exported from dvb_core ?!?! */ ++ ++static int dvb_usercopy2(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct inode *inode, struct file *file, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *)arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ err = func(inode, file, cmd, parg); ++ if (err == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++static int video_do_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int ret = 0; ++ unsigned long arg = (unsigned long)parg; ++ ++ switch (cmd) { ++ case VIDEO_SET_STREAMTYPE: ++ switch (arg) { ++ case VIDEO_CAP_MPEG2: ++ /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ ++ send_cli(dev, "vdec mpeg2\n"); ++ break; ++ case VIDEO_CAP_AVC: ++ /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ ++ send_cli(dev, "vdec h264\n"); ++ break; ++ case VIDEO_CAP_VC1: ++ /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ ++ send_cli(dev, "vdec vc1\n"); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ break; ++ default: ++ ret = -ENOIOCTLCMD; ++ return -EINVAL; ++ } ++ return ret; ++} ++ ++static int video_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); ++} ++ ++static const struct file_operations video_fops = { ++ .owner = THIS_MODULE, ++ .read = video_read, ++ .write = video_write, ++ .open = video_open, ++ .release = video_release, ++ .ioctl = video_ioctl, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = 0, ++ .readers = -1, ++ .writers = 1, ++ .users = -1, ++ .fops = &video_fops, ++}; ++#endif +diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c +index 039bed3..a8a1a03 100644 +--- a/drivers/media/pci/ngene/ngene-cards.c ++++ b/drivers/media/pci/ngene/ngene-cards.c +@@ -42,8 +42,18 @@ + #include "mt2131.h" + #include "tda18271c2dd.h" + #include "drxk.h" +-#include "drxd.h" +-#include "dvb-pll.h" ++#include "tda18212dd.h" ++#include "stv0367dd.h" ++#include "cxd2843.h" ++ ++ ++enum DEMOD_TYPE { ++ DMD_NONE = 0, ++ DMD_STV0900, ++ DMD_DRXK, ++ DMD_STV0367, ++ DMD_CXD28xx, ++}; + + + /****************************************************************************/ +@@ -86,8 +96,98 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) + return 0; + } + ++#if 0 ++static int tuner_attach_mt2060(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ void *tconf = dev->card_info->tuner_config[chan->number]; ++ u8 drxa = dev->card_info->demoda[chan->number]; ++ struct dvb_frontend *fe = chan->fe, *fe2; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ fe->misc_priv = chan; ++#else ++ fe->sec_priv = chan; ++#endif ++ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; ++ ++ dev->card_info->gate_ctrl(fe, 1); ++ fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); ++ dev->card_info->gate_ctrl(fe, 0); ++ ++ i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); ++ write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); ++ write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); ++ write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); ++ ++ return fe2 ? 0 : -ENODEV; ++} ++ ++static int tuner_attach_xc3028(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ void *tconf = dev->card_info->tuner_config[chan->number]; ++ struct dvb_frontend *fe = chan->fe, *fe2; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ fe->misc_priv = chan; ++#else ++ fe->sec_priv = chan; ++#endif ++ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; ++ ++ dev->card_info->gate_ctrl(fe, 1); ++ fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); ++ dev->card_info->gate_ctrl(fe, 0); ++ ++ /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ ++ ++ return fe2 ? 0 : -ENODEV; ++} ++ ++static int demod_attach_drxd(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = drxd_attach(feconf, ++ chan, &chan->i2c_adapter, ++ &chan->dev->pci_dev->dev); ++ return (chan->fe) ? 0 : -ENODEV; ++} ++ ++static int demod_attach_drxh(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = drxh_attach(feconf, chan, ++ &chan->i2c_adapter, &chan->dev->pci_dev->dev); ++ return (chan->fe) ? 0 : -ENODEV; ++} ++ ++static int demod_attach_stb0899(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = stb0899_attach(feconf, ++ chan, &chan->i2c_adapter, ++ &chan->dev->pci_dev->dev); ++ if (chan->fe) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++ chan->set_tone = chan->fe->ops->set_tone; ++ chan->fe->ops->set_tone = lnbh21_set_tone; ++ chan->fe->ops->set_voltage = lnbh21_set_voltage; ++#else ++ chan->set_tone = chan->fe->ops.set_tone; ++ chan->fe->ops.set_tone = lnbh21_set_tone; ++ chan->fe->ops.set_voltage = lnbh21_set_voltage; ++#endif ++ } ++ ++ return (chan->fe) ? 0 : -ENODEV; ++} ++#endif + +-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct ngene_channel *chan = fe->sec_priv; + int status; +@@ -121,12 +221,41 @@ static int tuner_attach_tda18271(struct ngene_channel *chan) + return 0; + } + ++static int tuner_attach_tda18212dd(struct ngene_channel *chan) ++{ ++ struct i2c_adapter *i2c; ++ struct dvb_frontend *fe; ++ u8 addr = (chan->number & 1) ? 0x63 : 0x60; ++ ++ if (chan->demod_type == DMD_CXD28xx && chan->number < 2) ++ addr ^= 0x04; ++ i2c = &chan->dev->channel[0].i2c_adapter; ++ fe = dvb_attach(tda18212dd_attach, chan->fe, i2c, addr); ++ if (!fe) { ++ printk(KERN_ERR "No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++ + static int tuner_attach_probe(struct ngene_channel *chan) + { +- if (chan->demod_type == 0) ++ switch(chan->demod_type) ++ { ++ case DMD_STV0900: + return tuner_attach_stv6110(chan); +- if (chan->demod_type == 1) ++ ++ case DMD_DRXK: + return tuner_attach_tda18271(chan); ++ ++ case DMD_STV0367: ++ case DMD_CXD28xx: ++ return tuner_attach_tda18212dd(chan); ++ ++ default: ++ pr_err("Unknown demod %x\n", chan->demod_type); ++ break; ++ } + return -EINVAL; + } + +@@ -184,6 +313,26 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) + return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; + } + ++static int i2c_read_regs(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 *val, u8 len) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, ++ u8 reg, u8 *val) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1} }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ + static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, + u16 reg, u8 *val) + { +@@ -195,6 +344,15 @@ static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, + return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; + } + ++static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, ++ u8 reg, u8 val) ++{ ++ u8 msg[2] = {reg, val}; ++ struct i2c_msg msgs[1] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2 } }; ++ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; ++} ++ + static int port_has_stv0900(struct i2c_adapter *i2c, int port) + { + u8 val; +@@ -218,18 +376,154 @@ static int demod_attach_drxk(struct ngene_channel *chan, + struct drxk_config config; + + memset(&config, 0, sizeof(config)); +- config.microcode_name = "drxk_a3.mc"; +- config.qam_demod_parameter_count = 4; + config.adr = 0x29 + (chan->number ^ 2); ++ config.microcode_name = "drxk_a3.mc"; + ++#ifdef USE_API3 ++ chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2); ++#else + chan->fe = dvb_attach(drxk_attach, &config, i2c); ++#endif + if (!chan->fe) { + printk(KERN_ERR "No DRXK found!\n"); + return -ENODEV; + } + chan->fe->sec_priv = chan; + chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; +- chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; ++ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++static int port_has_stv0367(struct i2c_adapter *i2c, int port) ++{ ++ u8 val; ++ ++ if (i2c_read_reg16(i2c, 0x1c + (port ^ 1), 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ return 1; ++} ++ ++static int demod_attach_stv0367dd(struct ngene_channel *chan, ++ struct i2c_adapter *i2c) ++{ ++ struct stv0367_cfg cfg; ++ ++ memset(&cfg, 0, sizeof cfg); ++ cfg.adr = 0x1c + (chan->number ^ 1); ++ ++ chan->fe = dvb_attach(stv0367_attach, i2c, &cfg, &chan->fe2); ++ if (!chan->fe) { ++ printk(KERN_ERR "No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ chan->fe->sec_priv = chan; ++ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; ++ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++static int port_has_xo2(struct i2c_adapter *i2c, int port, u8 *id) ++{ ++ u8 addr = (port < 2) ? 0x14 : 0x10; ++ u8 val; ++ u8 probe[1] = { 0x00 }, data[4]; ++ struct i2c_msg msgs[2] = {{ .addr = addr, .flags = 0, ++ .buf = probe, .len = 1 }, ++ { .addr = addr, .flags = I2C_M_RD, ++ .buf = data, .len = 4 } }; ++#if 0 ++ u8 cfg[] = { 0x79, 0x00, 0x00 }; ++ struct i2c_msg cmsg = { .addr = 0x44, .flags = 0, ++ .buf = cfg, .len = 3 }; ++ if (port == 0) ++ i2c_transfer(i2c, &cmsg, 1); ++ pr_info("chan %d addr %x\n", port, addr); ++ msleep(1000); ++#endif ++ val = i2c_transfer(i2c, msgs, 2); ++ if (val != 2) ++ return 0; ++ ++ if (data[0] != 'D' || data[1] != 'F') ++ return 0; ++ ++ *id = data[2]; ++ return 1; ++} ++ ++static int init_xo2(struct i2c_adapter *i2c, int port) ++{ ++ u8 addr = (port < 2) ? 0x14 : 0x10; ++ u8 val, data[2]; ++ int res; ++ ++ if (port & 1) ++ return 0; ++ ++ res = i2c_read_regs(i2c, addr, 0x04, data, 2); ++ if (res < 0) ++ return res; ++ ++ if (data[0] != 0x01) { ++ pr_info("Invalid XO2\n"); ++ return -1; ++ } ++ ++ i2c_read_reg(i2c, addr, 0x08, &val); ++ if (val != 0) { ++ i2c_write_reg(i2c, addr, 0x08, 0x00); ++ msleep(100); ++ } ++ /* Enable tuner power, disable pll, reset demods */ ++ i2c_write_reg(i2c, addr, 0x08, 0x04); ++ usleep_range(2000, 3000); ++ /* Release demod resets */ ++ i2c_write_reg(i2c, addr, 0x08, 0x07); ++ usleep_range(2000, 3000); ++ /* Start XO2 PLL */ ++ i2c_write_reg(i2c, addr, 0x08, 0x87); ++ ++ return 0; ++} ++ ++#define DDB_TUNER_XO2 16 ++#define DDB_TUNER_DVBS_STV0910 16 ++#define DDB_TUNER_DVBCT2_SONY 17 ++#define DDB_TUNER_ISDBT_SONY 18 ++#define DDB_TUNER_DVBC2T2_SONY 19 ++#define DDB_TUNER_ATSC_ST 20 ++#define DDB_TUNER_DVBC2T2_ST 21 ++ ++static char *xo2names[] = { ++ "DUAL DVB-S2", ++ "DUAL DVB-C/T/T2", ++ "DUAL DVB-ISDBT", ++ "DUAL DVB-C/C2/T/T2", ++ "DUAL ATSC", ++ "DUAL DVB-C/C2/T/T2", ++ "", "" ++}; ++ ++struct cxd2843_cfg cxd2843[] = { ++ { .adr = 0x68, }, ++ { .adr = 0x69, }, ++ { .adr = 0x6c, }, ++ { .adr = 0x6d, }, ++}; ++ ++static int demod_attach_cxd2843(struct ngene_channel *chan, ++ struct i2c_adapter *i2c) ++{ ++ chan->fe = dvb_attach(cxd2843_attach, i2c, cxd2843+chan->number); ++ if (!chan->fe) { ++ pr_err("No cxd2837/38/43 found!\n"); ++ return -ENODEV; ++ } ++ chan->fe->sec_priv = chan; ++ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; ++ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + return 0; + } + +@@ -240,6 +534,7 @@ static int cineS2_probe(struct ngene_channel *chan) + u8 buf[3]; + struct i2c_msg i2c_msg = { .flags = 0, .buf = buf }; + int rc; ++ u8 id; + + /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ + if (chan->number < 2) +@@ -247,8 +542,33 @@ static int cineS2_probe(struct ngene_channel *chan) + else + i2c = &chan->dev->channel[1].i2c_adapter; + +- if (port_has_stv0900(i2c, chan->number)) { +- chan->demod_type = 0; ++ if (port_has_xo2(i2c, chan->number, &id)) { ++ id >>= 2; ++ if (id > 5) { ++ pr_info("Channel %d: Unknown XO2 DuoFlex %u\n", ++ chan->number, id); ++ return -ENODEV; ++ } ++ init_xo2(i2c, chan->number); ++ switch(DDB_TUNER_XO2 + id) ++ { ++ case DDB_TUNER_DVBCT2_SONY: ++ case DDB_TUNER_ISDBT_SONY: ++ case DDB_TUNER_DVBC2T2_SONY: ++ chan->demod_type = DMD_CXD28xx; ++ pr_info("Channel %d: %s\n", chan->number, xo2names[id]); ++ demod_attach_cxd2843(chan, i2c); ++ break; ++ default: ++ pr_info("Channel %d: %s not supported yet\n", ++ chan->number, xo2names[id]); ++ return -ENODEV; ++ } ++ ++ } else if (chan->dev->channel[0].demod_type != DMD_CXD28xx && ++ port_has_stv0900(i2c, chan->number)) { ++ chan->demod_type = DMD_STV0900; ++ pr_info("Channel %d: STV0900\n", chan->number); + fe_conf = chan->dev->card_info->fe_config[chan->number]; + /* demod found, attach it */ + rc = demod_attach_stv0900(chan); +@@ -276,9 +596,17 @@ static int cineS2_probe(struct ngene_channel *chan) + printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n"); + return -EIO; + } ++ + } else if (port_has_drxk(i2c, chan->number^2)) { +- chan->demod_type = 1; ++ chan->demod_type = DMD_DRXK; ++ pr_info("Channel %d: DRXK\n", chan->number); + demod_attach_drxk(chan, i2c); ++ ++ } else if (port_has_stv0367(i2c, chan->number)) { ++ chan->demod_type = DMD_STV0367; ++ pr_info("Channel %d: STV0367\n", chan->number); ++ demod_attach_stv0367dd(chan, i2c); ++ + } else { + printk(KERN_ERR "No demod found on chan %d\n", chan->number); + return -ENODEV; +@@ -315,249 +643,140 @@ static int demod_attach_lg330x(struct ngene_channel *chan) + return (chan->fe) ? 0 : -ENODEV; + } + +-static int demod_attach_drxd(struct ngene_channel *chan) +-{ +- struct drxd_config *feconf; +- +- feconf = chan->dev->card_info->fe_config[chan->number]; +- +- chan->fe = dvb_attach(drxd_attach, feconf, chan, +- &chan->i2c_adapter, &chan->dev->pci_dev->dev); +- if (!chan->fe) { +- pr_err("No DRXD found!\n"); +- return -ENODEV; +- } +- return 0; +-} ++/****************************************************************************/ ++/* Switch control (I2C gates, etc.) *****************************************/ ++/****************************************************************************/ + +-static int tuner_attach_dtt7520x(struct ngene_channel *chan) ++#if 0 ++static int avf_output(struct ngene_channel *chan, int state) + { +- struct drxd_config *feconf; +- +- feconf = chan->dev->card_info->fe_config[chan->number]; +- +- if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, +- &chan->i2c_adapter, +- feconf->pll_type)) { +- pr_err("No pll(%d) found!\n", feconf->pll_type); +- return -ENODEV; +- } ++ if (chan->dev->card_info->avf[chan->number]) ++ i2c_write_register(&chan->i2c_adapter, ++ chan->dev->card_info->avf[chan->number], ++ 0xf2, state ? 0x89 : 0x80); + return 0; + } + +-/****************************************************************************/ +-/* EEPROM TAGS **************************************************************/ +-/****************************************************************************/ +- +-#define MICNG_EE_START 0x0100 +-#define MICNG_EE_END 0x0FF0 +- +-#define MICNG_EETAG_END0 0x0000 +-#define MICNG_EETAG_END1 0xFFFF +- +-/* 0x0001 - 0x000F reserved for housekeeping */ +-/* 0xFFFF - 0xFFFE reserved for housekeeping */ +- +-/* Micronas assigned tags +- EEProm tags for hardware support */ +- +-#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ +-#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ +- +-#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ +-#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ ++/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ + +-/* Tag range for OEMs */ ++static int exp_set(struct ngene *dev) ++{ ++ return i2c_write(&dev->channel[0].i2c_adapter, ++ dev->card_info->exp, dev->exp_val); ++} + +-#define MICNG_EETAG_OEM_FIRST 0xC000 +-#define MICNG_EETAG_OEM_LAST 0xFFEF ++static int exp_init(struct ngene *dev) ++{ ++ if (!dev->card_info->exp) ++ return 0; ++ dev->exp_val = dev->card_info->exp_init; ++ return exp_set(dev); ++} + +-static int i2c_write_eeprom(struct i2c_adapter *adapter, +- u8 adr, u16 reg, u8 data) ++static int exp_set_bit(struct ngene *dev, int bit, int val) + { +- u8 m[3] = {(reg >> 8), (reg & 0xff), data}; +- struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, +- .len = sizeof(m)}; ++ if (val) ++ set_bit(bit, &dev->exp_val); ++ else ++ clear_bit(bit, &dev->exp_val); ++ return exp_set(dev); ++} + +- if (i2c_transfer(adapter, &msg, 1) != 1) { +- pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); +- return -EIO; ++static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) ++{ ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ return exp_set_bit(chan->dev, 4 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return exp_set_bit(chan->dev, 6 + chan->number, val); ++ case 2: /* Input: 0=digital 1=analog antenna input */ ++ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); ++ exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); ++ break; + } + return 0; + } + +-static int i2c_read_eeprom(struct i2c_adapter *adapter, +- u8 adr, u16 reg, u8 *data, int len) ++static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) + { +- u8 msg[2] = {(reg >> 8), (reg & 0xff)}; +- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, +- .buf = msg, .len = 2 }, +- {.addr = adr, .flags = I2C_M_RD, +- .buf = data, .len = len} }; +- +- if (i2c_transfer(adapter, msgs, 2) != 2) { +- pr_err(DEVICE_NAME ": Error reading EEPROM\n"); +- return -EIO; ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ return exp_set_bit(chan->dev, 4 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return exp_set_bit(chan->dev, 6 + chan->number, val); ++ case 2: /* Input: 0=digital 1=analog antenna input */ ++ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); ++ exp_set_bit(chan->dev, 1 + chan->number * 2, 0); ++ break; + } + return 0; + } + +-static int ReadEEProm(struct i2c_adapter *adapter, +- u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) ++static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) + { +- int status = 0; +- u16 Addr = MICNG_EE_START, Length, tag = 0; +- u8 EETag[3]; +- +- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { +- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) +- return -1; +- tag = (EETag[0] << 8) | EETag[1]; +- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) +- return -1; +- if (tag == Tag) +- break; +- Addr += sizeof(u16) + 1 + EETag[2]; +- } +- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { +- pr_err(DEVICE_NAME +- ": Reached EOEE @ Tag = %04x Length = %3d\n", +- tag, EETag[2]); +- return -1; +- } +- Length = EETag[2]; +- if (Length > MaxLen) +- Length = (u16) MaxLen; +- if (Length > 0) { +- Addr += sizeof(u16) + 1; +- status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); +- if (!status) { +- *pLength = EETag[2]; +-#if 0 +- if (Length < EETag[2]) +- status = STATUS_BUFFER_OVERFLOW; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else /* Why is there no misc_priv available anymore !?!?! */ ++ /* Well, just abuse sec :-) */ ++ struct ngene_channel *chan = fe->sec_priv; + #endif +- } +- } +- return status; ++ struct ngene *dev = chan->dev; ++ ++ return dev->card_info->switch_ctrl(chan, 0, enable); + } + +-static int WriteEEProm(struct i2c_adapter *adapter, +- u16 Tag, u32 Length, u8 *data) ++static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) + { +- int status = 0; +- u16 Addr = MICNG_EE_START; +- u8 EETag[3]; +- u16 tag = 0; +- int retry, i; +- +- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { +- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) +- return -1; +- tag = (EETag[0] << 8) | EETag[1]; +- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) +- return -1; +- if (tag == Tag) +- break; +- Addr += sizeof(u16) + 1 + EETag[2]; +- } +- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { +- pr_err(DEVICE_NAME +- ": Reached EOEE @ Tag = %04x Length = %3d\n", +- tag, EETag[2]); +- return -1; +- } +- +- if (Length > EETag[2]) +- return -EINVAL; +- /* Note: We write the data one byte at a time to avoid +- issues with page sizes. (which are different for +- each manufacture and eeprom size) +- */ +- Addr += sizeof(u16) + 1; +- for (i = 0; i < Length; i++, Addr++) { +- status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); +- +- if (status) +- break; +- +- /* Poll for finishing write cycle */ +- retry = 10; +- while (retry) { +- u8 Tmp; +- +- msleep(50); +- status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); +- if (status) +- break; +- if (Tmp != data[i]) +- pr_err(DEVICE_NAME +- "eeprom write error\n"); +- retry -= 1; +- } +- if (status) { +- pr_err(DEVICE_NAME +- ": Timeout polling eeprom\n"); +- break; +- } ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ if (chan->number > 1) ++ return -EINVAL; ++ return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return 0; + } +- return status; ++ return 0; + } + +-static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) ++static int viper_reset_xc(struct dvb_frontend *fe) + { +- int stat; +- u8 buf[2]; +- u32 len = 0; +- +- stat = ReadEEProm(adapter, tag, 2, buf, &len); +- if (stat) +- return stat; +- if (len != 2) +- return -EINVAL; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else ++ struct ngene_channel *chan = fe->sec_priv; ++#endif ++ struct ngene *dev = chan->dev; + +- *data = (buf[0] << 8) | buf[1]; +- return 0; +-} ++ printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); + +-static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) +-{ +- int stat; +- u8 buf[2]; ++ if (chan->number > 1) ++ return -EINVAL; + +- buf[0] = data >> 8; +- buf[1] = data & 0xff; +- stat = WriteEEProm(adapter, tag, 2, buf); +- if (stat) +- return stat; ++ ngene_command_gpio_set(dev, 3 + chan->number, 0); ++ msleep(150); ++ ngene_command_gpio_set(dev, 3 + chan->number, 1); + return 0; + } + +-static s16 osc_deviation(void *priv, s16 deviation, int flag) ++static int python_gate_ctrl(struct dvb_frontend *fe, int enable) + { +- struct ngene_channel *chan = priv; +- struct i2c_adapter *adap = &chan->i2c_adapter; +- u16 data = 0; +- +- if (flag) { +- data = (u16) deviation; +- pr_info(DEVICE_NAME ": write deviation %d\n", +- deviation); +- eeprom_write_ushort(adap, 0x1000 + chan->number, data); +- } else { +- if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) +- data = 0; +- pr_info(DEVICE_NAME ": read deviation %d\n", +- (s16) data); +- } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else /* Why is there no misc_priv available anymore !?!?! */ ++ struct ngene_channel *chan = fe->sec_priv; ++#endif ++ struct ngene *dev = chan->dev; + +- return (s16) data; ++ if (chan->number == 0) ++ return ngene_command_gpio_set(dev, 3, enable); ++ if (chan->number == 1) ++ return ngene_command_gpio_set(dev, 4, enable); ++ return -EINVAL; + } +- +-/****************************************************************************/ +-/* Switch control (I2C gates, etc.) *****************************************/ +-/****************************************************************************/ +- ++#endif + + static struct stv090x_config fe_cineS2 = { + .device = STV0900, +@@ -696,7 +915,7 @@ static struct ngene_info ngene_info_m780 = { + .demod_attach = { NULL, demod_attach_lg330x }, + + /* Ensure these are NULL else the frame will call them (as funcs) */ +- .tuner_attach = { NULL, NULL, NULL, NULL }, ++ .tuner_attach = { 0, 0, 0, 0 }, + .fe_config = { NULL, &aver_m780 }, + .avf = { 0 }, + +@@ -705,14 +924,18 @@ static struct ngene_info ngene_info_m780 = { + .fw_version = 15, + }; + ++/****************************************************************************/ ++ ++#if 0 + static struct drxd_config fe_terratec_dvbt_0 = { + .index = 0, + .demod_address = 0x70, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, +- .pll_type = DVB_PLL_THOMSON_DTT7520X, ++ .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, ++ .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, + }; + +@@ -722,8 +945,9 @@ static struct drxd_config fe_terratec_dvbt_1 = { + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, +- .pll_type = DVB_PLL_THOMSON_DTT7520X, ++ .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, ++ .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, + }; + +@@ -732,13 +956,293 @@ static struct ngene_info ngene_info_terratec = { + .name = "Terratec Integra/Cinergy2400i Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, +- .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, + .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, + .i2c_access = 1, + }; + + /****************************************************************************/ + ++static struct mt2060_config tuner_python_0 = { ++ .i2c_address = 0x60, ++ .clock_out = 3, ++ .input = 0 ++}; ++ ++static struct mt2060_config tuner_python_1 = { ++ .i2c_address = 0x61, ++ .clock_out = 3, ++ .input = 1 ++}; ++ ++static struct drxd_config fe_python_0 = { ++ .index = 0, ++ .demod_address = 0x71, ++ .demod_revision = 0xb1, ++ .demoda_address = 0x41, ++ .clock = 16000, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct drxd_config fe_python_1 = { ++ .index = 1, ++ .demod_address = 0x70, ++ .demod_revision = 0xb1, ++ .demoda_address = 0x45, ++ .clock = 16000, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct ngene_info ngene_info_python = { ++ .type = NGENE_PYTHON, ++ .name = "Micronas MicPython/Hedgehog Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, ++ .fe_config = {&fe_python_0, &fe_python_1}, ++ .tuner_config = {&tuner_python_0, &tuner_python_1}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .demoda = {0x41, 0x45}, ++ .gate_ctrl = python_gate_ctrl, ++ .switch_ctrl = python_switch_ctrl, ++}; ++ ++/****************************************************************************/ ++ ++static struct drxd_config fe_appb_dvbt_0 = { ++ .index = 0, ++ .demod_address = 0x71, ++ .demod_revision = 0xa2, ++ .demoda_address = 0x41, ++ .pll_address = 0x63, ++ .pll_type = DRXD_PLL_MT3X0823, ++ .clock = 20000, ++ .pll_set = ngene_pll_set_mt_3x0823, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct drxd_config fe_appb_dvbt_1 = { ++ .index = 1, ++ .demod_address = 0x70, ++ .demod_revision = 0xa2, ++ .demoda_address = 0x45, ++ .pll_address = 0x60, ++ .pll_type = DRXD_PLL_MT3X0823, ++ .clock = 20000, ++ .pll_set = ngene_pll_set_mt_3x0823, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct ngene_info ngene_info_appboard = { ++ .type = NGENE_APP, ++ .name = "Micronas Application Board Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, ++ .avf = {0x43, 0x47}, ++}; ++ ++static struct ngene_info ngene_info_appboard_ntsc = { ++ .type = NGENE_APP, ++ .name = "Micronas Application Board Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, ++ .avf = {0x43, 0x47}, ++ .ntsc = 1, ++}; ++ ++/****************************************************************************/ ++ ++static struct stb0899_config fe_sidewinder_0 = { ++ .demod_address = 0x68, ++ .pll_address = 0x63, ++}; ++ ++static struct stb0899_config fe_sidewinder_1 = { ++ .demod_address = 0x6b, ++ .pll_address = 0x60, ++}; ++ ++static struct ngene_info ngene_info_sidewinder = { ++ .type = NGENE_SIDEWINDER, ++ .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, ++ .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, ++ .lnb = {0x0b, 0x08}, ++}; ++ ++/****************************************************************************/ ++/* Yet unnamed S2 card with dual DVB-S2 demod */ ++/****************************************************************************/ ++ ++static struct stv0900_config fe_s2_0 = { ++ .addr = 0x68, ++ .pll = 0x63, ++ .pll_type = 0, ++ .nr = 0, ++}; ++ ++static struct stv0900_config fe_s2_1 = { ++ .addr = 0x68, ++ .pll = 0x60, ++ .pll_type = 0, ++ .nr = 1, ++}; ++ ++static struct ngene_info ngene_info_s2 = { ++ .type = NGENE_SIDEWINDER, ++ .name = "S2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, ++ NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, ++ .fe_config = {&fe_s2_0, &fe_s2_1}, ++ .lnb = {0x0b, 0x08}, ++ .tsf = {3, 3}, ++ .fw_version = 15, ++}; ++ ++static struct stv0900_config fe_s2b_0 = { ++ .addr = 0x68, ++ .pll = 0x60, ++ .pll_type = 0x10, ++ .nr = 0, ++}; ++ ++static struct stv0900_config fe_s2b_1 = { ++ .addr = 0x68, ++ .pll = 0x63, ++ .pll_type = 0x10, ++ .nr = 1, ++}; ++ ++static struct ngene_info ngene_info_s2_b = { ++ .type = NGENE_SIDEWINDER, ++ .name = "S2 V2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, ++ NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, ++ .fe_config = {&fe_s2b_0, &fe_s2b_1}, ++ .lnb = {0x0b, 0x08}, ++ .tsf = {3, 3}, ++ .fw_version = 17, ++}; ++ ++/****************************************************************************/ ++ ++static struct xc3028_config tuner_viper_0 = { ++ .adr = 0x61, ++ .reset = viper_reset_xc ++}; ++ ++static struct xc3028_config tuner_viper_1 = { ++ .adr = 0x64, ++ .reset = viper_reset_xc ++}; ++ ++static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; ++ ++static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; ++ ++static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; ++ ++static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; ++ ++static struct ngene_info ngene_info_viper_v1 = { ++ .type = NGENE_VIPER, ++ .name = "Micronas MicViper Dual ATSC DRXH", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++static struct ngene_info ngene_info_viper_v2 = { ++ .type = NGENE_VIPER, ++ .name = "Micronas MicViper Dual ATSC DRXL", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x38, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_vbox_v1 = { ++ .type = NGENE_VBOX_V1, ++ .name = "VBox Cat's Eye 164E", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_vbox_v2 = { ++ .type = NGENE_VBOX_V2, ++ .name = "VBox Cat's Eye 164E", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl2, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_racer = { ++ .type = NGENE_RACER, ++ .name = "Micronas MicRacer HDTV Decoder Card", ++ .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, ++ NGENE_IO_AIN, NGENE_IO_NONE, ++ NGENE_IO_TSOUT}, ++ .i2s = {0, 0, 1, 0}, ++ .fw_version = 17, ++}; ++#endif + + + /****************************************************************************/ +@@ -753,6 +1257,8 @@ static struct ngene_info ngene_info_terratec = { + /****************************************************************************/ + + static const struct pci_device_id ngene_id_tbl[] = { ++ NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2), ++ NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5), + NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), + NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), + NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), +@@ -761,7 +1267,32 @@ static const struct pci_device_id ngene_id_tbl[] = { + NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), + NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), + NGENE_ID(0x1461, 0x062e, ngene_info_m780), ++#if 0 /* not (yet?) supported */ ++ NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), + NGENE_ID(0x153b, 0x1167, ngene_info_terratec), ++ NGENE_ID(0x18c3, 0x0030, ngene_info_python), ++ NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), ++ NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), ++ NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), ++ NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), ++ NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), ++ NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), ++ NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), ++ NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), ++ NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), ++ NGENE_ID(0x18c3, 0x0001, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0005, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0009, ngene_info_appboard_atsc), ++ NGENE_ID(0x18c3, 0x000b, ngene_info_appboard_atsc), ++ NGENE_ID(0x18c3, 0x0010, ngene_info_shrek_50_fp), ++ NGENE_ID(0x18c3, 0x0011, ngene_info_shrek_60_fp), ++ NGENE_ID(0x18c3, 0x0012, ngene_info_shrek_50), ++ NGENE_ID(0x18c3, 0x0013, ngene_info_shrek_60), ++ NGENE_ID(0x18c3, 0x0000, ngene_info_hognose), ++#endif + {0} + }; + MODULE_DEVICE_TABLE(pci, ngene_id_tbl); +@@ -798,7 +1329,7 @@ static void ngene_resume(struct pci_dev *dev) + printk(KERN_INFO DEVICE_NAME ": resume\n"); + } + +-static const struct pci_error_handlers ngene_errors = { ++static struct pci_error_handlers ngene_errors = { + .error_detected = ngene_error_detected, + .link_reset = ngene_link_reset, + .slot_reset = ngene_slot_reset, +diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c +index e29bc3af..84510db 100644 +--- a/drivers/media/pci/ngene/ngene-core.c ++++ b/drivers/media/pci/ngene/ngene-core.c +@@ -57,13 +57,15 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + #define dprintk if (debug) printk + +-#define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) +-#define ngwritel(dat, adr) writel((dat), dev->iomem + (adr)) +-#define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) ++#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) ++#define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) ++#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) + #define ngreadl(adr) readl(dev->iomem + (adr)) + #define ngreadb(adr) readb(dev->iomem + (adr)) +-#define ngcpyto(adr, src, count) memcpy_toio(dev->iomem + (adr), (src), (count)) +-#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), dev->iomem + (adr), (count)) ++#define ngcpyto(adr, src, count) memcpy_toio((char *) \ ++ (dev->iomem + (adr)), (src), (count)) ++#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ ++ (dev->iomem + (adr)), (count)) + + /****************************************************************************/ + /* nGene interrupt handler **************************************************/ +@@ -84,6 +86,14 @@ static void event_tasklet(unsigned long data) + if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) + dev->RxEventNotify(dev, Event.TimeStamp, + Event.RXCharacter); ++#if 0 ++ if ((Event.GPIOStatus & 0x80) && (dev->Gpio2EventNotify)) ++ dev->Gpio2EventNotify(dev, Event.TimeStamp, ++ Event.GPIOStatus & 0x1f); ++ if ((Event.GPIOStatus & 0x40) && (dev->Gpio3EventNotify)) ++ dev->Gpio3EventNotify(dev, Event.TimeStamp, ++ Event.GPIOStatus & 0x1f); ++#endif + } + } + +@@ -212,6 +222,13 @@ static irqreturn_t irq_handler(int irq, void *dev_id) + u8 nextWriteIndex = + (dev->EventQueueWriteIndex + 1) & + (EVENT_QUEUE_SIZE - 1); ++#if 0 ++ printk(KERN_ERR DEVICE_NAME ++ ": Event interrupt %02x Uart = %02x Gpio = %02x\n", ++ dev->EventBuffer->EventStatus, ++ dev->EventBuffer->UARTStatus, ++ dev->EventBuffer->GPIOStatus); ++#endif + if (nextWriteIndex != dev->EventQueueReadIndex) { + dev->EventQueue[dev->EventQueueWriteIndex] = + *(dev->EventBuffer); +@@ -256,16 +273,22 @@ static void dump_command_io(struct ngene *dev) + u8 buf[8], *b; + + ngcpyfrom(buf, HOST_TO_NGENE, 8); +- printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf); ++ printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); + + ngcpyfrom(buf, NGENE_TO_HOST, 8); +- printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf); ++ printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); + + b = dev->hosttongene; +- printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b); ++ printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + + b = dev->ngenetohost; +- printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b); ++ printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + + static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) +@@ -314,12 +337,24 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) + ngwritel(1, FORCE_INT); + + ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); ++#if 0 ++ if (ret < 0) ++ return ret; ++ if (!dev->cmd_done) ++ ; ++#endif + if (!ret) { + /*ngwritel(0, FORCE_NMI);*/ + + printk(KERN_ERR DEVICE_NAME + ": Command timeout cmd=%02x prev=%02x\n", + com->cmd.hdr.Opcode, dev->prev_cmd); ++#if 0 ++ printk(KERN_ERR DEVICE_NAME ": Icounts=%08x\n", ++ ngreadl(NGENE_INT_COUNTS)); ++ if (ngreadl(NGENE_INT_COUNTS) == 0xffffffff) ++ ngwritel(0, NGENE_INT_ENABLE); ++#endif + dump_command_io(dev); + return -1; + } +@@ -346,6 +381,19 @@ int ngene_command(struct ngene *dev, struct ngene_command *com) + return result; + } + ++#if 0 ++int ngene_command_nop(struct ngene *dev) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_NOP; ++ com.cmd.hdr.Length = 0; ++ com.in_len = 0; ++ com.out_len = 0; ++ ++ return ngene_command(dev, &com); ++} ++#endif + + static int ngene_command_load_firmware(struct ngene *dev, + u8 *ngene_fw, u32 size) +@@ -380,6 +428,83 @@ static int ngene_command_load_firmware(struct ngene *dev, + return ngene_command(dev, &com); + } + ++#if 0 ++int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; ++ com.cmd.hdr.Length = 1; ++ com.cmd.SfrIramRead.address = adr; ++ com.in_len = 1; ++ com.out_len = 2; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ *data = com.cmd.raw8[1]; ++ return 0; ++} ++ ++int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; ++ com.cmd.hdr.Length = 2; ++ com.cmd.SfrIramWrite.address = adr; ++ com.cmd.SfrIramWrite.data = data; ++ com.in_len = 2; ++ com.out_len = 1; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int ngene_command_config_uart(struct ngene *dev, u8 config, ++ tx_cb_t *tx_cb, rx_cb_t *rx_cb) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; ++ com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; ++ com.cmd.ConfigureUart.UartControl = config; ++ com.in_len = sizeof(struct FW_CONFIGURE_UART); ++ com.out_len = 0; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ dev->TxEventNotify = tx_cb; ++ dev->RxEventNotify = rx_cb; ++ ++ dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); ++ ++ return 0; ++} ++ ++static void tx_cb(struct ngene *dev, u32 ts) ++{ ++ dev->tx_busy = 0; ++ wake_up_interruptible(&dev->tx_wq); ++} ++ ++static void rx_cb(struct ngene *dev, u32 ts, u8 c) ++{ ++ int rp = dev->uart_rp; ++ int nwp, wp = dev->uart_wp; ++ ++ /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ ++ nwp = (wp + 1) % (UART_RBUF_LEN); ++ if (nwp == rp) ++ return; ++ dev->uart_rbuf[wp] = c; ++ dev->uart_wp = nwp; ++ wake_up_interruptible(&dev->rx_wq); ++} ++#endif + + static int ngene_command_config_buf(struct ngene *dev, u8 config) + { +@@ -425,6 +550,18 @@ int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) + return ngene_command(dev, &com); + } + ++#if 0 ++/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! ++ Also better set bootdelay to 1 in nvram or less. */ ++static void ngene_reset_decypher(struct ngene *dev) ++{ ++ printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); ++ ngene_command_gpio_set(dev, 4, 0); ++ msleep(1); ++ ngene_command_gpio_set(dev, 4, 1); ++ msleep(2000); ++} ++#endif + + /* + 02000640 is sample on rising edge. +@@ -510,6 +647,17 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags) + } + } + ++#if 0 ++static void clear_tsin(struct ngene_channel *chan) ++{ ++ struct SBufferHeader *Cur = chan->nextBuffer; ++ ++ do { ++ memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); ++ Cur = Cur->Next; ++ } while (Cur != chan->nextBuffer); ++} ++#endif + + static void flush_buffers(struct ngene_channel *chan) + { +@@ -730,6 +878,14 @@ void set_transfer(struct ngene_channel *chan, int state) + if (dev->card_info->switch_ctrl) + dev->card_info->switch_ctrl(chan, 1, state ^ 1); + ++#if 0 ++ /* Disable AVF output if present. */ ++ if (dev->card_info->avf[chan->number]) ++ i2c_write_register(&chan->i2c_adapter, ++ chan->dev->card_info->avf[chan->number], ++ 0xf2, state ? 0x80 : 0x89); ++ ++#endif + if (state) { + spin_lock_irq(&chan->state_lock); + +@@ -750,8 +906,8 @@ void set_transfer(struct ngene_channel *chan, int state) + if (chan->mode & NGENE_IO_TSIN) + chan->pBufferExchange = tsin_exchange; + spin_unlock_irq(&chan->state_lock); +- } +- /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", ++ } else ++ ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", + ngreadl(0x9310)); */ + + ret = ngene_command_stream_control(dev, chan->number, +@@ -769,6 +925,89 @@ void set_transfer(struct ngene_channel *chan, int state) + } + } + ++#if 0 ++/****************************************************************************/ ++/* Decypher firmware loading ************************************************/ ++/****************************************************************************/ ++ ++#define DECYPHER_FW "decypher.fw" ++ ++static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) ++{ ++#if 0 ++ if (wait_event_interruptible(dev->tsout_rbuf.queue, ++ dvb_ringbuffer_free ++ (&dev->tsout_rbuf) >= len) < 0) ++ return 0; ++#else ++ while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) ++ msleep(1); ++ ++#endif ++ ++ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); ++ ++ return len; ++} ++ ++u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; ++ ++int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) ++{ ++ struct ngene_channel *chan = &dev->channel[4]; ++ u32 len = 180, cc = 0; ++ u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; ++ ++ set_transfer(chan, 1); ++ msleep(100); ++ while (size) { ++ len = 180; ++ if (len > size) ++ len = size; ++ buf[3] = 0x10 | (cc & 0x0f); ++ buf[4] = (cc >> 8); ++ buf[5] = cc & 0xff; ++ buf[6] = len; ++ ++ dec_ts_send(dev, buf, 8); ++ dec_ts_send(dev, fw, len); ++ if (len < 180) ++ dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); ++ cc++; ++ size -= len; ++ fw += len; ++ } ++ for (len = 0; len < 512; len++) ++ dec_ts_send(dev, dec_fw_fill_ts, 188); ++ while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) ++ msleep(10); ++ msleep(100); ++ set_transfer(chan, 0); ++ return 0; ++} ++ ++int dec_fw_boot(struct ngene *dev) ++{ ++ u32 size; ++ const struct firmware *fw = NULL; ++ u8 *dec_fw; ++ ++ if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { ++ printk(KERN_ERR DEVICE_NAME ++ ": %s not found. Check hotplug directory.\n", ++ DECYPHER_FW); ++ return -1; ++ } ++ printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", ++ DECYPHER_FW); ++ ++ size = fw->size; ++ dec_fw = (u8 *)fw->data; ++ dec_fw_send(dev, dec_fw, size); ++ release_firmware(fw); ++ return 0; ++} ++#endif + + /****************************************************************************/ + /* nGene hardware init and release functions ********************************/ +@@ -908,6 +1147,7 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, + { + dma_addr_t tmp; + u32 i, j; ++ int status = 0; + u32 SCListMemSize = pRingBuffer->NumBuffers + * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : + NUM_SCATTER_GATHER_ENTRIES) +@@ -1007,12 +1247,14 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, + + } + +- return 0; ++ return status; + } + + static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, + struct SRingBufferDescriptor *pRingBuffer) + { ++ int status = 0; ++ + /* Copy pointer to scatter gather list in TSRingbuffer + structure for buffer 2 + Load number of buffer +@@ -1033,7 +1275,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, + pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; + Cur = Cur->Next; + } +- return 0; ++ return status; + } + + static u32 RingBufferSizes[MAX_STREAM] = { +@@ -1060,6 +1302,85 @@ static u32 Buffer2Sizes[MAX_STREAM] = { + 0 + }; + ++#if 0 ++static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, ++ struct SRingBufferDescriptor *rbuf, ++ u32 entries, u32 size1, u32 size2) ++{ ++ if (create_ring_buffer(pci_dev, rbuf, entries) < 0) ++ return -ENOMEM; ++ ++ if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int channel_allocate_buffers(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ int type = dev->card_info->io_type[chan->number]; ++ int status; ++ ++ chan->State = KSSTATE_STOP; ++ ++ if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->RingBuffer, ++ RingBufferSizes[chan->number]); ++ if (status < 0) ++ return -ENOMEM; ++ ++ if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->RingBuffer, ++ Buffer1Sizes[chan->number], ++ Buffer2Sizes[chan-> ++ number]); ++ if (status < 0) ++ return -ENOMEM; ++ } else if (type & NGENE_IO_HDTV) { ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->RingBuffer, ++ MAX_HDTV_BUFFER_SIZE, 0); ++ if (status < 0) ++ return -ENOMEM; ++ } ++ } ++ ++ if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { ++ ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->TSRingBuffer, RING_SIZE_TS); ++ if (status < 0) ++ return -ENOMEM; ++ ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->TSRingBuffer, ++ MAX_TS_BUFFER_SIZE, 0); ++ if (status) ++ return -ENOMEM; ++ } ++ ++ if (type & NGENE_IO_TSOUT) { ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->TSIdleBuffer, 1); ++ if (status < 0) ++ return -ENOMEM; ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->TSIdleBuffer, ++ MAX_TS_BUFFER_SIZE, 0); ++ if (status) ++ return -ENOMEM; ++ FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); ++ } ++ return 0; ++} ++#endif + + static int AllocCommonBuffers(struct ngene *dev) + { +@@ -1073,11 +1394,12 @@ static int AllocCommonBuffers(struct ngene *dev) + dev->ngenetohost = dev->FWInterfaceBuffer + 256; + dev->EventBuffer = dev->FWInterfaceBuffer + 512; + +- dev->OverflowBuffer = pci_zalloc_consistent(dev->pci_dev, +- OVERFLOW_BUFFER_SIZE, +- &dev->PAOverflowBuffer); ++ dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, ++ OVERFLOW_BUFFER_SIZE, ++ &dev->PAOverflowBuffer); + if (!dev->OverflowBuffer) + return -ENOMEM; ++ memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); + + for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { + int type = dev->card_info->io_type[i]; +@@ -1312,6 +1634,10 @@ static int ngene_buffer_config(struct ngene *dev) + u8 tsin12_config[6] = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 }; + u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 }; + u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 }; ++#if 0 ++ u8 tsin34_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x60, 0x00 }; ++ u8 tsio35_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x00, 0x60 }; ++#endif + u8 *bconf = tsin12_config; + + if (dev->card_info->io_type[2]&NGENE_IO_TSIN && +@@ -1321,10 +1647,22 @@ static int ngene_buffer_config(struct ngene *dev) + dev->ci.en) + bconf = tsio1235_config; + } ++#if 0 ++ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { ++ bconf = hdtv_config; ++ ngene_reset_decypher(dev); ++ } ++#endif + stat = ngene_command_config_free_buf(dev, bconf); + } else { + int bconf = BUFFER_CONFIG_4422; + ++#if 0 ++ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { ++ bconf = BUFFER_CONFIG_8022; ++ ngene_reset_decypher(dev); ++ } ++#endif + if (dev->card_info->io_type[3] == NGENE_IO_TSIN) + bconf = BUFFER_CONFIG_3333; + stat = ngene_command_config_buf(dev, bconf); +@@ -1397,8 +1735,10 @@ static int ngene_start(struct ngene *dev) + if (stat < 0) + goto fail; + +- return 0; ++ if (!stat) ++ return stat; + ++ /* otherwise error: fall through */ + fail: + ngwritel(0, NGENE_INT_ENABLE); + free_irq(dev->pci_dev->irq, dev); +@@ -1590,7 +1930,7 @@ static void cxd_detach(struct ngene *dev) + + dvb_ca_en50221_release(ci->en); + kfree(ci->en); +- ci->en = NULL; ++ ci->en = 0; + } + + /***********************************/ +@@ -1616,7 +1956,7 @@ static void ngene_unlink(struct ngene *dev) + + void ngene_shutdown(struct pci_dev *pdev) + { +- struct ngene *dev = pci_get_drvdata(pdev); ++ struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); + + if (!dev || !shutdown_workaround) + return; +@@ -1642,6 +1982,7 @@ void ngene_remove(struct pci_dev *pdev) + cxd_detach(dev); + ngene_stop(dev); + ngene_release_buffers(dev); ++ pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); + } + +@@ -1681,10 +2022,36 @@ int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) + + + dev->i2c_current_bus = -1; ++#if 0 ++ exp_init(dev); ++ ++ /* Disable analog TV decoder chips if present */ ++ if (dev->card_info->msp[0]) ++ i2c_write_msp_register(&dev->channel[0].i2c_adapter, ++ dev->card_info->msp[0], 0x00, 0x0000); ++ if (dev->card_info->msp[1]) ++ i2c_write_msp_register(&dev->channel[1].i2c_adapter, ++ dev->card_info->msp[1], 0x00, 0x0000); ++ { ++ u16 data; ++ read_msp(&dev->channel[0].i2c_adapter, ++ dev->card_info->msp[0], 0x00, &data); ++ } ++ if (dev->card_info->avf[0]) ++ i2c_write_register(&dev->channel[0].i2c_adapter, ++ dev->card_info->avf[0], 0xf2, 0x80); ++ if (dev->card_info->avf[1]) ++ i2c_write_register(&dev->channel[1].i2c_adapter, ++ dev->card_info->avf[1], 0xf2, 0x80); ++ if (copy_eeprom) { ++ i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); ++ i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); ++ } ++ /*i2c_check_eeprom(&dev->i2c_adapter);*/ ++#endif + + /* Register DVB adapters and devices for both channels */ +- stat = init_channels(dev); +- if (stat < 0) ++ if (init_channels(dev) < 0) + goto fail2; + + return 0; +@@ -1695,5 +2062,6 @@ fail1: + ngene_release_buffers(dev); + fail0: + pci_disable_device(pci_dev); ++ pci_set_drvdata(pci_dev, NULL); + return stat; + } +diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c +index 59bb285..8049e2b 100644 +--- a/drivers/media/pci/ngene/ngene-dvb.c ++++ b/drivers/media/pci/ngene/ngene-dvb.c +@@ -42,12 +42,321 @@ + + #include "ngene.h" + ++#if 0 ++int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, ++ u16 lines, u16 bpl, u16 vblines, u16 vbibpl) ++{ ++ if (!(mode & SMODE_TRANSPORT_STREAM)) ++ return -EINVAL; ++ ++ if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) ++ return -EINVAL; ++ ++ if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) ++ return -EINVAL; ++ ++ if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) ++ return -EINVAL; ++ ++ return ngene_command_stream_control(dev, stream, control, mode, 0); ++} ++#endif + + /****************************************************************************/ + /* COMMAND API interface ****************************************************/ + /****************************************************************************/ ++#if 0 ++ ++static int command_do_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int err = 0; ++ ++ switch (cmd) { ++ case IOCTL_MIC_NO_OP: ++ err = ngene_command_nop(dev); ++ break; ++ ++ case IOCTL_MIC_DOWNLOAD_FIRMWARE: ++ break; ++ ++ case IOCTL_MIC_I2C_READ: ++ { ++ MIC_I2C_READ *msg = parg; ++ ++ err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, ++ msg->OutData, msg->OutLength, ++ msg->OutData, msg->InLength, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_I2C_WRITE: ++ { ++ MIC_I2C_WRITE *msg = parg; ++ ++ err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, ++ msg->Data, msg->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_TEST_GETMEM: ++ { ++ MIC_MEM *m = parg; ++ ++ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) ++ return -EINVAL; ++ ++ /* WARNING, only use this on x86, ++ other archs may not swallow this */ ++ err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_TEST_SETMEM: ++ { ++ MIC_MEM *m = parg; ++ ++ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) ++ return -EINVAL; ++ ++ err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_SFR_READ: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_SFR_WRITE: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_write(dev, m->Address, m->Data, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_IRAM_READ: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); ++ break; ++ } ++ ++ case IOCTL_MIC_IRAM_WRITE: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_write(dev, m->Address, m->Data, 0); ++ break; ++ } ++ ++ case IOCTL_MIC_STREAM_CONTROL: ++ { ++ MIC_STREAM_CONTROL *m = parg; ++ ++ err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, ++ m->nLines, m->nBytesPerLine, ++ m->nVBILines, m->nBytesPerVBILine); ++ break; ++ } ++ ++ default: ++ err = -EINVAL; ++ break; ++ } ++ return err; ++} ++ ++static int command_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ void *parg = (void *)arg, *pbuf = NULL; ++ char buf[64]; ++ int res = -EFAULT; ++ ++ if (_IOC_DIR(cmd) & _IOC_WRITE) { ++ parg = buf; ++ if (_IOC_SIZE(cmd) > sizeof(buf)) { ++ pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); ++ if (!pbuf) ++ return -ENOMEM; ++ parg = pbuf; ++ } ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto error; ++ } ++ res = command_do_ioctl(inode, file, cmd, parg); ++ if (res < 0) ++ goto error; ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ res = -EFAULT; ++error: ++ kfree(pbuf); ++ return res; ++} ++ ++struct page *ngene_nopage(struct vm_area_struct *vma, ++ unsigned long address, int *type) ++{ ++ return 0; ++} ++ ++static int ngene_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ ++ unsigned long size = vma->vm_end - vma->vm_start; ++ unsigned long off = vma->vm_pgoff << PAGE_SHIFT; ++ unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; ++ unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; ++ ++ if (size > psize) ++ return -EINVAL; ++ ++ if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ return 0; ++} ++ ++ ++static int write_uart(struct ngene *dev, u8 *data, int len) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_WRITE_UART; ++ com.cmd.hdr.Length = len; ++ memcpy(com.cmd.WriteUart.Data, data, len); ++ com.cmd.WriteUart.Data[len] = 0; ++ com.cmd.WriteUart.Data[len + 1] = 0; ++ com.in_len = len; ++ com.out_len = 0; + +-static ssize_t ts_write(struct file *file, const char __user *buf, ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int send_cli(struct ngene *dev, char *cmd) ++{ ++ /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ ++ return write_uart(dev, cmd, strlen(cmd)); ++} ++ ++static int send_cli_val(struct ngene *dev, char *cmd, u32 val) ++{ ++ char s[32]; ++ ++ snprintf(s, 32, "%s %d\n", cmd, val); ++ /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ ++ return write_uart(dev, s, strlen(s)); ++} ++ ++static int ngene_command_write_uart_user(struct ngene *dev, ++ const u8 *data, int len) ++{ ++ struct ngene_command com; ++ ++ dev->tx_busy = 1; ++ com.cmd.hdr.Opcode = CMD_WRITE_UART; ++ com.cmd.hdr.Length = len; ++ ++ if (copy_from_user(com.cmd.WriteUart.Data, data, len)) ++ return -EFAULT; ++ com.in_len = len; ++ com.out_len = 0; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static ssize_t uart_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int len, ret = 0; ++ size_t left = count; ++ ++ while (left) { ++ len = left; ++ if (len > 250) ++ len = 250; ++ ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); ++ if (ret < 0) ++ return ret; ++ ngene_command_write_uart_user(dev, buf, len); ++ left -= len; ++ buf += len; ++ } ++ return count; ++} ++ ++static ssize_t uart_read(struct file *file, char *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left; ++ int wp, rp, avail, len; ++ ++ if (!dev->uart_rbuf) ++ return -EINVAL; ++ if (count > 128) ++ count = 128; ++ left = count; ++ while (left) { ++ if (wait_event_interruptible(dev->rx_wq, ++ dev->uart_wp != dev->uart_rp) < 0) ++ return -EAGAIN; ++ wp = dev->uart_wp; ++ rp = dev->uart_rp; ++ avail = (wp - rp); ++ ++ if (avail < 0) ++ avail += UART_RBUF_LEN; ++ if (avail > left) ++ avail = left; ++ if (wp < rp) { ++ len = UART_RBUF_LEN - rp; ++ if (len > avail) ++ len = avail; ++ if (copy_to_user(buf, dev->uart_rbuf + rp, len)) ++ return -EFAULT; ++ if (len < avail) ++ if (copy_to_user(buf + len, dev->uart_rbuf, ++ avail - len)) ++ return -EFAULT; ++ } else { ++ if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) ++ return -EFAULT; ++ } ++ dev->uart_rp = (rp + avail) % UART_RBUF_LEN; ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++#endif ++ ++static ssize_t ts_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) + { + struct dvb_device *dvbdev = file->private_data; +@@ -59,12 +368,12 @@ static ssize_t ts_write(struct file *file, const char __user *buf, + (&dev->tsout_rbuf) >= count) < 0) + return 0; + +- dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count); ++ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); + + return count; + } + +-static ssize_t ts_read(struct file *file, char __user *buf, ++static ssize_t ts_read(struct file *file, char *buf, + size_t count, loff_t *ppos) + { + struct dvb_device *dvbdev = file->private_data; +@@ -97,6 +406,7 @@ static const struct file_operations ci_fops = { + }; + + struct dvb_device ngene_dvbdev_ci = { ++ .priv = 0, + .readers = -1, + .writers = -1, + .users = -1, +@@ -132,6 +442,11 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) + struct ngene_channel *chan = priv; + struct ngene *dev = chan->dev; + ++#if 0 ++ printk(KERN_INFO DEVICE_NAME ": tsin %08x %02x %02x %02x %02x\n", ++ len, ((u8 *) buf)[512 * 188], ((u8 *) buf)[0], ++ ((u8 *) buf)[1], ((u8 *) buf)[2]); ++#endif + + if (flags & DF_SWAP32) + swap_buffer(buf, len); +@@ -190,12 +505,49 @@ void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) + return buf; + } + ++#if 0 ++static void set_dto(struct ngene_channel *chan, u32 rate) ++{ ++ u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ ++ ++ val = ((val >> 25) + 1) >> 1; ++ chan->AudioDTOValue = (u32) val; ++ /* chan->AudioDTOUpdated=1; */ ++ /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ ++} ++#endif + + + int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) + { + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; ++#if 0 ++ struct ngene *dev = chan->dev; ++ ++ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { ++ switch (dvbdmxfeed->pes_type) { ++ case DMX_TS_PES_VIDEO: ++ send_cli_val(dev, "vpid", dvbdmxfeed->pid); ++ send_cli(dev, "res 1080i50\n"); ++ /* send_cli(dev, "vdec mpeg2\n"); */ ++ break; ++ ++ case DMX_TS_PES_AUDIO: ++ send_cli_val(dev, "apid", dvbdmxfeed->pid); ++ send_cli(dev, "start\n"); ++ break; ++ ++ case DMX_TS_PES_PCR: ++ send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); ++ break; ++ ++ default: ++ break; ++ } ++ ++ } ++#endif + + if (chan->users == 0) { + if (!chan->dev->cmd_timeout_workaround || !chan->running) +@@ -209,6 +561,27 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) + { + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; ++#if 0 ++ struct ngene *dev = chan->dev; ++ ++ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { ++ switch (dvbdmxfeed->pes_type) { ++ case DMX_TS_PES_VIDEO: ++ send_cli(dev, "stop\n"); ++ break; ++ ++ case DMX_TS_PES_AUDIO: ++ break; ++ ++ case DMX_TS_PES_PCR: ++ break; ++ ++ default: ++ break; ++ } ++ ++ } ++#endif + + if (--chan->users) + return chan->users; +diff --git a/drivers/media/pci/ngene/ngene-eeprom.c b/drivers/media/pci/ngene/ngene-eeprom.c +new file mode 100644 +index 0000000..281d9f9 +--- /dev/null ++++ b/drivers/media/pci/ngene/ngene-eeprom.c +@@ -0,0 +1,284 @@ ++/* ++ * ngene-eeprom.c: nGene PCIe bridge driver - eeprom support ++ * ++ * Copyright (C) 2005-2007 Micronas ++ * ++ * Copyright (C) 2008-2009 Ralph Metzler ++ * Modifications for new nGene firmware, ++ * support for EEPROM-copying, ++ * support for new dual DVB-S2 card prototype ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#if 0 ++static int copy_eeprom; ++module_param(copy_eeprom, int, 0444); ++MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); ++ ++#define MICNG_EE_START 0x0100 ++#define MICNG_EE_END 0x0FF0 ++ ++#define MICNG_EETAG_END0 0x0000 ++#define MICNG_EETAG_END1 0xFFFF ++ ++/* 0x0001 - 0x000F reserved for housekeeping */ ++/* 0xFFFF - 0xFFFE reserved for housekeeping */ ++ ++/* Micronas assigned tags ++ EEProm tags for hardware support */ ++ ++#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ ++#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ ++ ++#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ ++#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ ++ ++/* Tag range for OEMs */ ++ ++#define MICNG_EETAG_OEM_FIRST 0xC000 ++#define MICNG_EETAG_OEM_LAST 0xFFEF ++ ++static int i2c_write_eeprom(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 data) ++{ ++ u8 m[3] = {(reg >> 8), (reg & 0xff), data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, ++ .len = sizeof(m)}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int i2c_read_eeprom(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 *data, int len) ++{ ++ u8 msg[2] = {(reg >> 8), (reg & 0xff)}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = data, .len = len} }; ++ ++ if (i2c_transfer(adapter, msgs, 2) != 2) { ++ dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ReadEEProm(struct i2c_adapter *adapter, ++ u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) ++{ ++ int status = 0; ++ u16 Addr = MICNG_EE_START, Length, tag = 0; ++ u8 EETag[3]; ++ ++ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { ++ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) ++ return -1; ++ tag = (EETag[0] << 8) | EETag[1]; ++ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) ++ return -1; ++ if (tag == Tag) ++ break; ++ Addr += sizeof(u16) + 1 + EETag[2]; ++ } ++ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Reached EOEE @ Tag = %04x Length = %3d\n", ++ tag, EETag[2]); ++ return -1; ++ } ++ Length = EETag[2]; ++ if (Length > MaxLen) ++ Length = (u16) MaxLen; ++ if (Length > 0) { ++ Addr += sizeof(u16) + 1; ++ status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); ++ if (!status) { ++ *pLength = EETag[2]; ++ if (Length < EETag[2]) ++ ; /*status=STATUS_BUFFER_OVERFLOW; */ ++ } ++ } ++ return status; ++} ++ ++static int WriteEEProm(struct i2c_adapter *adapter, ++ u16 Tag, u32 Length, u8 *data) ++{ ++ int status = 0; ++ u16 Addr = MICNG_EE_START; ++ u8 EETag[3]; ++ u16 tag = 0; ++ int retry, i; ++ ++ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { ++ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) ++ return -1; ++ tag = (EETag[0] << 8) | EETag[1]; ++ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) ++ return -1; ++ if (tag == Tag) ++ break; ++ Addr += sizeof(u16) + 1 + EETag[2]; ++ } ++ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Reached EOEE @ Tag = %04x Length = %3d\n", ++ tag, EETag[2]); ++ return -1; ++ } ++ ++ if (Length > EETag[2]) ++ return -EINVAL; ++ /* Note: We write the data one byte at a time to avoid ++ issues with page sizes. (which are different for ++ each manufacture and eeprom size) ++ */ ++ Addr += sizeof(u16) + 1; ++ for (i = 0; i < Length; i++, Addr++) { ++ status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); ++ ++ if (status) ++ break; ++ ++ /* Poll for finishing write cycle */ ++ retry = 10; ++ while (retry) { ++ u8 Tmp; ++ ++ msleep(50); ++ status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); ++ if (status) ++ break; ++ if (Tmp != data[i]) ++ printk(KERN_ERR DEVICE_NAME ++ "eeprom write error\n"); ++ retry -= 1; ++ } ++ if (status) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Timeout polling eeprom\n"); ++ break; ++ } ++ } ++ return status; ++} ++ ++static void i2c_init_eeprom(struct i2c_adapter *adapter) ++{ ++ u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, ++ 0x10, 0x01, 0x02, 0x00, 0x00, ++ 0x00, 0x00, 0x00}; ++ ++ int i; ++ ++ for (i = 0; i < sizeof(tags); i++) ++ i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); ++} ++ ++int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) ++{ ++ int stat; ++ u8 buf[2]; ++ u32 len = 0; ++ ++ stat = ReadEEProm(adapter, tag, 2, buf, &len); ++ if (stat) ++ return stat; ++ if (len != 2) ++ return -EINVAL; ++ ++ *data = (buf[0] << 8) | buf[1]; ++ return 0; ++} ++ ++static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) ++{ ++ int stat; ++ u8 buf[2]; ++ ++ buf[0] = data >> 8; ++ buf[1] = data & 0xff; ++ stat = WriteEEProm(adapter, tag, 2, buf); ++ if (stat) ++ return stat; ++ return 0; ++} ++ ++int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) ++{ ++ u8 buf[64]; ++ int i; ++ ++ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ for (i = 0; i < sizeof(buf); i++) { ++ if (!(i & 15)) ++ printk(KERN_DEBUG "\n"); ++ printk(KERN_DEBUG "%02x ", buf[i]); ++ } ++ printk("\n"); ++ ++ return 0; ++} ++ ++int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) ++{ ++ u8 buf[64]; ++ int i; ++ ++ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ buf[36] = 0xc3; ++ buf[39] = 0xab; ++ for (i = 0; i < sizeof(buf); i++) { ++ i2c_write_eeprom(adapter, adr2, i, buf[i]); ++ msleep(10); ++ } ++ return 0; ++} ++ ++int i2c_check_eeprom(struct i2c_adapter *adapter) ++{ ++ u8 buf[13]; ++ ++ i2c_dump_eeprom(adapter); ++ ++ if (i2c_read_eeprom(adapter, 0x50, 0x0100, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ if (buf[0] != 0x10 || buf[1] != 0x00) { ++ printk(KERN_INFO DEVICE_NAME ++ ": Initializing EEPROM TAG area\n"); ++ i2c_init_eeprom(adapter); ++ } ++ return 0; ++} ++ ++#endif +diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c +index d28554f..601bea4 100644 +--- a/drivers/media/pci/ngene/ngene-i2c.c ++++ b/drivers/media/pci/ngene/ngene-i2c.c +@@ -77,6 +77,11 @@ static int ngene_command_i2c_write(struct ngene *dev, u8 adr, + { + struct ngene_command com; + ++#if 0 ++ /* Probing by writing 0 bytes does not work */ ++ if (!outlen) ++ outlen++; ++#endif + + com.cmd.hdr.Opcode = CMD_I2C_WRITE; + com.cmd.hdr.Length = outlen + 1; +@@ -148,6 +153,39 @@ done: + return num; + } + ++#if 0 ++static int ngene_i2c_algo_control(struct i2c_adapter *adap, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct ngene_channel *chan = ++ (struct ngene_channel *)i2c_get_adapdata(adap); ++ ++ switch (cmd) { ++ case IOCTL_MIC_TUN_RDY: ++ chan->tun_rdy = 1; ++ if (chan->dec_rdy == 1) ++ chan->tun_dec_rdy = 1; ++ break; ++ ++ case IOCTL_MIC_DEC_RDY: ++ chan->dec_rdy = 1; ++ if (chan->tun_rdy == 1) ++ chan->tun_dec_rdy = 1; ++ break; ++ ++ case IOCTL_MIC_TUN_DETECT: ++ { ++ int *palorbtsc = (int *)arg; ++ *palorbtsc = chan->dev->card_info->ntsc; ++ break; ++ } ++ ++ default: ++ break; ++ } ++ return 0; ++} ++#endif + + static u32 ngene_i2c_functionality(struct i2c_adapter *adap) + { +@@ -174,3 +212,78 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr) + return i2c_add_adapter(adap); + } + ++#if 0 ++int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) ++{ ++ u8 m[1] = {data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C adr %02x!\n", adr); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write_register(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 data) ++{ ++ u8 m[2] = {reg, data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C register %02x@%02x!\n", ++ reg, adr); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write_read(struct i2c_adapter *adapter, ++ u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = w, .len = wlen}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = r, .len = rlen} }; ++ ++ if (i2c_transfer(adapter, msgs, 2) != 2) { ++ printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int test_dec_i2c(struct i2c_adapter *adapter, int reg) ++{ ++ u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; ++ u8 data2[256]; ++ int i; ++ ++ memset(data2, 0, 256); ++ i2c_write_read(adapter, 0x66, data, 2, data2, 4); ++ for (i = 0; i < 4; i++) ++ printk(KERN_DEBUG "%02x ", data2[i]); ++ printk(KERN_DEBUG "\n"); ++ ++ return 0; ++} ++ ++static int i2c_write_msp_register(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u16 data) ++{ ++ u8 m[3] = {reg, (data >> 8) & 0xff, data & 0xff}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 3 }; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C register %02x@%02x!\n", ++ reg, adr); ++ return -1; ++ } ++ return 0; ++} ++ ++#endif +diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h +index 51e2fbd..e3ae00c 100644 +--- a/drivers/media/pci/ngene/ngene.h ++++ b/drivers/media/pci/ngene/ngene.h +@@ -653,6 +653,11 @@ struct ngene_channel { + struct dmx_frontend mem_frontend; + int users; + struct video_device *v4l_dev; ++#if 0 ++ struct dvb_device *command_dev; ++ struct dvb_device *audio_dev; ++ struct dvb_device *video_dev; ++#endif + struct dvb_device *ci_dev; + struct tasklet_struct demux_tasklet; + +@@ -691,6 +696,9 @@ struct ngene_channel { + struct mychip *mychip; + struct snd_card *soundcard; + u8 *evenbuffer; ++#if 0 ++ u8 *soundbuffer; ++#endif + u8 dma_on; + int soundstreamon; + int audiomute; +@@ -737,7 +745,7 @@ typedef void (tx_cb_t)(struct ngene *, u32); + struct ngene { + int nr; + struct pci_dev *pci_dev; +- unsigned char __iomem *iomem; ++ unsigned char *iomem; + + /*struct i2c_adapter i2c_adapter;*/ + +@@ -849,6 +857,10 @@ struct ngene_info { + u8 lnb[4]; + int i2c_access; + u8 ntsc; ++#if 0 ++ u8 exp; ++ u8 exp_init; ++#endif + u8 tsf[4]; + u8 i2s[4]; + +@@ -885,6 +897,25 @@ struct ngene_buffer { + }; + #endif + ++#if 0 ++int ngene_command_stream_control(struct ngene *dev, ++ u8 stream, u8 control, u8 mode, u8 flags); ++int ngene_command_nop(struct ngene *dev); ++int ngene_command_i2c_read(struct ngene *dev, u8 adr, ++ u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); ++int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); ++int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); ++int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); ++int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, ++ u16 lines, u16 bpl, u16 vblines, u16 vbibpl); ++ ++int ngene_v4l2_init(struct ngene_channel *chan); ++void ngene_v4l2_remove(struct ngene_channel *chan); ++int ngene_snd_exit(struct ngene_channel *chan); ++int ngene_snd_init(struct ngene_channel *chan); ++ ++struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); ++#endif + + /* Provided by ngene-core.c */ + int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); +@@ -914,6 +945,15 @@ int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, + struct dmx_frontend *mem_frontend, + struct dvb_adapter *dvb_adapter); + ++/* Provided by ngene-eeprom.c */ ++#if 0 ++int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2); ++int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr); ++int i2c_check_eeprom(struct i2c_adapter *adapter); ++int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data); ++int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data); ++#endif ++ + #endif + + /* LocalWords: Endif +diff --git a/include/uapi/linux/dvb/mod.h b/include/uapi/linux/dvb/mod.h +new file mode 100644 +index 0000000..c733a39 +--- /dev/null ++++ b/include/uapi/linux/dvb/mod.h +@@ -0,0 +1,22 @@ ++#ifndef _UAPI_DVBMOD_H_ ++#define _UAPI_DVBMOD_H_ ++ ++#include ++#include "frontend.h" ++ ++struct dvb_mod_params { ++ __u32 base_frequency; ++ __u32 attenuator; ++}; ++ ++struct dvb_mod_channel_params { ++ enum fe_modulation modulation; ++ __u64 input_bitrate; /* 2^-32 Hz */ ++ int pcr_correction; ++}; ++ ++ ++#define DVB_MOD_SET _IOW('o', 208, struct dvb_mod_params) ++#define DVB_MOD_CHANNEL_SET _IOW('o', 209, struct dvb_mod_channel_params) ++ ++#endif /*_UAPI_DVBMOD_H_*/ +diff --git a/include/uapi/linux/dvb/ns.h b/include/uapi/linux/dvb/ns.h +new file mode 100644 +index 0000000..691c65d +--- /dev/null ++++ b/include/uapi/linux/dvb/ns.h +@@ -0,0 +1,68 @@ ++#ifndef _UAPI_DVBNS_H_ ++#define _UAPI_DVBNS_H_ ++ ++#include ++ ++struct dvb_ns_params { ++ __u8 smac[6]; ++ __u8 dmac[6]; ++ __u8 sip[16]; ++ __u8 dip[16]; ++ __u16 sport; ++ __u16 dport; ++ __u16 sport2; ++ __u16 dport2; ++ __u8 ssrc[8]; ++ __u8 flags; ++ __u8 qos; ++ __u16 vlan; ++ __u8 ttl; ++}; ++ ++#define DVB_NS_IPV6 1 ++#define DVB_NS_RTP 2 ++#define DVB_NS_RTCP 4 ++#define DVB_NS_RTP_TO 8 ++ ++struct dvb_ns_rtcp { ++ __u8 *msg; ++ __u16 len; ++}; ++ ++struct dvb_ns_packet { ++ __u8 *buf; ++ __u8 count; ++}; ++ ++struct dvb_nsd_ts { ++ __u16 pid; ++ __u16 num; ++ __u16 input; ++ __u16 timeout; ++ __u16 len; ++ __u8 *ts; ++ __u8 mode; ++ __u8 table; ++ ++ __u8 filter_mask; ++ __u8 section; ++ __u16 section_id; ++}; ++ ++#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params) ++#define NS_START _IO('o', 193) ++#define NS_STOP _IO('o', 194) ++#define NS_SET_PID _IOW('o', 195, __u16) ++#define NS_SET_PIDS _IOW('o', 196, __u8 *) ++#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp) ++ ++#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts) ++#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts) ++#define NSD_CANCEL_GET_TS _IO('o', 200) ++#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts) ++ ++#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet) ++#define NS_INSERT_PACKETS _IOW('o', 203, __u8) ++#define NS_SET_CI _IOW('o', 204, __u8) ++ ++#endif /*_UAPI_DVBNS_H_*/ +-- +2.1.4 + diff --git a/packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch b/packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch new file mode 100644 index 0000000000..fd6539d2bf --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch @@ -0,0 +1,62 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:33:10.323380937 +0100 +@@ -971,6 +971,16 @@ + + *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val); + *strength += 750; ++ ++ const int MIN_STRENGTH_DVBS = 0; ++ const int MAX_STRENGTH_DVBS = 680; ++ if (*strength < MIN_STRENGTH_DVBS) ++ *strength = 0; ++ else if(*strength > MAX_STRENGTH_DVBS) ++ *strength = 0xFFFF; ++ else ++ *strength = (*strength - MIN_STRENGTH_DVBS) * 0xFFFF / (MAX_STRENGTH_DVBS - MIN_STRENGTH_DVBS); ++ + dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm", + val & 0xff, *strength); + } +@@ -983,6 +993,7 @@ + + *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); + *strength += 950; ++ *strength = *strength << 4; + dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", + val & 0x3fff, *strength); + } +@@ -1016,6 +1027,16 @@ + val = MAKEWORD16(buf[0], buf[1]); + + *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val); ++ ++ const int MIN_SNR_DVBS = 0; ++ const int MAX_SNR_DVBS = 200; ++ if (*snr < MIN_SNR_DVBS) ++ *snr = 0; ++ else if(*snr > MAX_SNR_DVBS) ++ *snr = 0xFFFF; ++ else ++ *snr = (*snr - MIN_SNR_DVBS) * 0xFFFF / (MAX_SNR_DVBS - MIN_SNR_DVBS); ++ + dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n", + buf[0], buf[1], val, *snr); + } +@@ -1040,6 +1061,16 @@ + val = (quantn - estn) / 10; + } + *snr = val; ++ ++ const int MIN_SNR_DVBS2 = 10; ++ const int MAX_SNR_DVBS2 = 70; ++ if (*snr < MIN_SNR_DVBS2) ++ *snr = 0; ++ else if(*snr > MAX_SNR_DVBS2) ++ *snr = 0xFFFF; ++ else ++ *snr = (*snr - MIN_SNR_DVBS2) * 0xFFFF / (MAX_SNR_DVBS2 - MIN_SNR_DVBS2); ++ + dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm", + quant, quantn, est, estn, val); + } diff --git a/packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch b/packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch new file mode 100644 index 0000000000..7aaabc48c0 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch @@ -0,0 +1,17 @@ +diff -Naur linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c +--- linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-16 10:35:01.131342123 +0100 +@@ -995,11 +995,11 @@ + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_ISOC, +- .count = 7, ++ .count = 4, + .endpoint = 0x02, + .u = { + .isoc = { +- .framesperurb = 4, ++ .framesperurb = 64, + .framesize = 940, + .interval = 1 + } diff --git a/packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch b/packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch new file mode 100644 index 0000000000..2b6f59c9a0 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch @@ -0,0 +1,284 @@ +From edf8977b62ae86859cccf3d0ea4883333ea4d138 Mon Sep 17 00:00:00 2001 +From: Dale Hamel +Date: Tue, 24 Feb 2015 10:31:04 -0500 +Subject: [PATCH] Add framescaling support to stk1160 + +Implements frame scaling support for stk1160 to support format changes instead of a static frame size. + +This is effectively a dumb sampling, and could perhaps benefit from being an averaging instead. + +This was a requested "TO DO" for this driver, and allows support for userspace programs like Hyperion and Boblight. + +Submitted on behalf of the original author, Michael Stegemann +--- + drivers/media/usb/stk1160/stk1160-core.c | 1 + + drivers/media/usb/stk1160/stk1160-reg.h | 26 +++++++ + drivers/media/usb/stk1160/stk1160-v4l.c | 112 +++++++++++++++++++++++------- + drivers/media/usb/stk1160/stk1160-video.c | 17 ++++- + drivers/media/usb/stk1160/stk1160.h | 1 + + 5 files changed, 130 insertions(+), 27 deletions(-) + +diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c +index 03504dc..1881770 100644 +--- a/drivers/media/usb/stk1160/stk1160-core.c ++++ b/drivers/media/usb/stk1160/stk1160-core.c +@@ -418,6 +418,7 @@ static void stk1160_disconnect(struct usb_interface *interface) + stk1160_ac97_unregister(dev); + + stk1160_clear_queue(dev); ++ vb2_queue_release(&dev->vb_vidq); + + video_unregister_device(&dev->vdev); + v4l2_device_disconnect(&dev->v4l2_dev); +diff --git a/drivers/media/usb/stk1160/stk1160-reg.h b/drivers/media/usb/stk1160/stk1160-reg.h +index 3e49da6..b1fa11d 100644 +--- a/drivers/media/usb/stk1160/stk1160-reg.h ++++ b/drivers/media/usb/stk1160/stk1160-reg.h +@@ -33,6 +33,32 @@ + */ + #define STK1160_DCTRL 0x100 + ++/* ++ * Decimation Control Register: ++ * Byte 104: ++ * Horizontal Decimation Line Unit Count ++ * Byte 105: ++ * Vertical Decimation Line Unit Count ++ * Byte 106: ++ * Bit 0 - Horizontal Decimation Control ++ * 0 Horizontal decimation is disabled. ++ * 1 Horizontal decimation is enabled. ++ * Bit 1 - Decimates Half or More Column ++ * 0 Decimates less than half from original column, ++ * -> send count unit (0x105) before each unit skipped. ++ * 1 Decimates half or more from original column, ++ * -> skip count unit (0x105) before each unit sent. ++ * Bit 2 - Vertical Decimation Control ++ * see Bit 0, only vertical ++ * Bit 3 - Vertical Greater or Equal to Half ++ * see Bit 1, only vertical ++ * Bit 4 - Decimation Unit ++ * 0 Decimation will work with 2 rows or columns per unit. ++ * 1 Decimation will work with 4 rows or columns per unit. ++ */ ++#define STK1160_DMCTRL 0x104 ++ ++ + /* Capture Frame Start Position */ + #define STK116_CFSPO 0x110 + #define STK116_CFSPO_STX_L 0x110 +diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c +index 65a326c..94dafeb 100644 +--- a/drivers/media/usb/stk1160/stk1160-v4l.c ++++ b/drivers/media/usb/stk1160/stk1160-v4l.c +@@ -106,6 +106,76 @@ static void stk1160_set_std(struct stk1160 *dev) + + } + ++static void stk1160_try_fmt(struct stk1160 *dev, struct v4l2_format *f, bool try) ++{ ++ int base_width, base_height; ++ ++ if (dev->norm & V4L2_STD_525_60){ ++ base_width = 720; ++ base_height = 480; ++ } else { ++ base_width = 720; ++ base_height = 576; ++ } ++ ++ if (f->fmt.pix.width <= (base_width / 3) ++ || f->fmt.pix.height <= (base_height / 3)){ ++ f->fmt.pix.width = base_width / 3; ++ f->fmt.pix.height = base_height / 3; ++ if (!try){ ++ dev->decimate = 3; ++ } ++ } else if ((f->fmt.pix.width >= base_width >> 1 ++ && f->fmt.pix.width < base_width) ++ ||((f->fmt.pix.height >= base_height >> 1 ++ && f->fmt.pix.height < base_height))){ ++ f->fmt.pix.width = base_width >> 1; ++ f->fmt.pix.height = base_height >> 1; ++ if (!try){ ++ dev->decimate = 2; ++ } ++ } else { ++ f->fmt.pix.width = base_width; ++ f->fmt.pix.height = base_height; ++ if (!try){ ++ dev->decimate = 0; ++ } ++ } ++} ++ ++static void stk1160_set_fmt(struct stk1160 *dev) ++{ ++ if (dev->norm & V4L2_STD_525_60){ ++ dev->width = 720; ++ dev->height = 480; ++ } else { ++ dev->width = 720; ++ dev->height = 576; ++ } ++ ++ switch (dev->decimate){ ++ case 0: ++ stk1160_write_reg(dev, STK1160_DMCTRL, 0x00); ++ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x00); ++ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x00); ++ break; ++ case 2: ++ stk1160_write_reg(dev, STK1160_DMCTRL, 0x01); ++ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x01); ++ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x1f); ++ dev->width = dev->width >> 1; ++ dev->height = dev->height >> 1; ++ break; ++ case 3: ++ stk1160_write_reg(dev, STK1160_DMCTRL, 0x02); ++ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x02); ++ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x1f); ++ dev->width = dev->width / 3; ++ dev->height = dev->height / 3; ++ break; ++ } ++} ++ + /* + * Set a new alternate setting. + * Returns true is dev->max_pkt_size has changed, false otherwise. +@@ -321,17 +391,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + { + struct stk1160 *dev = video_drvdata(file); + +- /* +- * User can't choose size at his own will, +- * so we just return him the current size chosen +- * at standard selection. +- * TODO: Implement frame scaling? +- */ ++ stk1160_try_fmt(dev, f, true); + +- f->fmt.pix.pixelformat = dev->fmt->fourcc; +- f->fmt.pix.width = dev->width; +- f->fmt.pix.height = dev->height; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; ++ f->fmt.pix.pixelformat = dev->fmt->fourcc; + f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; +@@ -348,9 +411,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + if (vb2_is_busy(q)) + return -EBUSY; + +- vidioc_try_fmt_vid_cap(file, priv, f); ++ stk1160_try_fmt(dev, f, false); ++ stk1160_set_fmt(dev); + +- /* We don't support any format changes */ ++ f->fmt.pix.field = V4L2_FIELD_INTERLACED; ++ f->fmt.pix.pixelformat = dev->fmt->fourcc; ++ f->fmt.pix.bytesperline = dev->width * 2; ++ f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; ++ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; + } +@@ -389,23 +457,18 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) + dev->norm = norm; + + /* This is taken from saa7115 video decoder */ +- if (dev->norm & V4L2_STD_525_60) { +- dev->width = 720; +- dev->height = 480; +- } else if (dev->norm & V4L2_STD_625_50) { +- dev->width = 720; +- dev->height = 576; ++ if (dev->norm & V4L2_STD_525_60 || dev->norm & V4L2_STD_625_50) { ++ stk1160_set_std(dev); ++ stk1160_set_fmt(dev); ++ ++ v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, ++ dev->norm); ++ ++ return 0; + } else { + stk1160_err("invalid standard\n"); + return -EINVAL; + } +- +- stk1160_set_std(dev); +- +- v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, +- dev->norm); +- +- return 0; + } + + +@@ -671,6 +734,7 @@ int stk1160_video_register(struct stk1160 *dev) + dev->norm = V4L2_STD_NTSC_M; + dev->width = 720; + dev->height = 480; ++ dev->decimate = 0; + + /* set default format */ + dev->fmt = &format[0]; +diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c +index 39f1aae..5a55028 100644 +--- a/drivers/media/usb/stk1160/stk1160-video.c ++++ b/drivers/media/usb/stk1160/stk1160-video.c +@@ -84,7 +84,6 @@ struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) + if (!list_empty(&dev->avail_bufs)) { + buf = list_first_entry(&dev->avail_bufs, + struct stk1160_buffer, list); +- list_del(&buf->list); + } + spin_unlock_irqrestore(&dev->buf_lock, flags); + +@@ -95,7 +94,7 @@ static inline + void stk1160_buffer_done(struct stk1160 *dev) + { + struct stk1160_buffer *buf = dev->isoc_ctl.buf; +- ++ unsigned long flags = 0; + dev->field_count++; + + buf->vb.v4l2_buf.sequence = dev->field_count >> 1; +@@ -104,7 +103,19 @@ void stk1160_buffer_done(struct stk1160 *dev) + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + + vb2_set_plane_payload(&buf->vb, 0, buf->bytesused); +- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); ++ ++ spin_lock_irqsave(&dev->buf_lock, flags); ++ if (buf->bytesused == vb2_plane_size(&buf->vb, 0)) ++ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); ++ else ++ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); ++ ++ if (!list_empty(&dev->avail_bufs)) { ++ list_del(&buf->list); ++ } ++ ++ spin_unlock_irqrestore(&dev->buf_lock, flags); ++ + + dev->isoc_ctl.buf = NULL; + } +diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h +index abdea48..895ed35 100644 +--- a/drivers/media/usb/stk1160/stk1160.h ++++ b/drivers/media/usb/stk1160/stk1160.h +@@ -150,6 +150,7 @@ struct stk1160 { + unsigned int ctl_input; /* selected input */ + v4l2_std_id norm; /* current norm */ + struct stk1160_fmt *fmt; /* selected format */ ++ int decimate; + + unsigned int field_count; /* not sure ??? */ + enum v4l2_field field; /* also not sure :/ */ +-- +2.1.1 + diff --git a/packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch b/packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch new file mode 100644 index 0000000000..79e04f2f82 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch @@ -0,0 +1,18 @@ +diff -rupN a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c +--- a/drivers/media/dvb-frontends/ds3000.c 2015-01-28 23:24:59.000000000 +0100 ++++ b/drivers/media/dvb-frontends/ds3000.c 2015-01-29 21:57:56.000000000 +0100 +@@ -958,6 +958,14 @@ static int ds3000_set_frontend(struct dv + /* enable ac coupling */ + ds3000_writereg(state, 0x25, 0x8a); + ++ dprintk("%s() frequency:%u symbol_rate:%u\n", __func__, c->frequency, c->symbol_rate); ++ ++ if (c->symbol_rate < ds3000_ops.info.symbol_rate_min || c->symbol_rate > ds3000_ops.info.symbol_rate_max ) { ++ dprintk("%s() symbol_rate %u out of range (%u ... %u)\n", __func__, c->symbol_rate, ++ ds3000_ops.info.symbol_rate_min, ds3000_ops.info.symbol_rate_max); ++ return 1; ++ } ++ + /* enhance symbol rate performance */ + if ((c->symbol_rate / 1000) <= 5000) { + value = 29777 / (c->symbol_rate / 1000) + 1; \ No newline at end of file diff --git a/packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch b/packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch new file mode 100644 index 0000000000..9f52eeb2d5 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch @@ -0,0 +1,11 @@ +diff -Naur linux-3.10.16/drivers/staging/rtl8712/usb_intf.c linux-3.10.16.patch/drivers/staging/rtl8712/usb_intf.c +--- linux-3.10.16/drivers/staging/rtl8712/usb_intf.c 2013-10-14 01:08:56.000000000 +0200 ++++ linux-3.10.16.patch/drivers/staging/rtl8712/usb_intf.c 2013-10-16 13:27:44.032951265 +0200 +@@ -92,6 +92,7 @@ + {USB_DEVICE(0x0DF6, 0x005B)}, + {USB_DEVICE(0x0DF6, 0x005D)}, + {USB_DEVICE(0x0DF6, 0x0063)}, ++ {USB_DEVICE(0x0DF6, 0x006C)}, + /* Sweex */ + {USB_DEVICE(0x177F, 0x0154)}, + /* Thinkware */ diff --git a/packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch new file mode 100644 index 0000000000..71cac81ac0 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch @@ -0,0 +1,13031 @@ +diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig +index b85f88c..238b2ed 100644 +--- a/drivers/media/common/Kconfig ++++ b/drivers/media/common/Kconfig +@@ -22,4 +22,5 @@ config CYPRESS_FIRMWARE + + source "drivers/media/common/b2c2/Kconfig" + source "drivers/media/common/saa7146/Kconfig" ++source "drivers/media/common/saa716x/Kconfig" + source "drivers/media/common/siano/Kconfig" +diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile +index d208de3..b3c373d 100644 +--- a/drivers/media/common/Makefile ++++ b/drivers/media/common/Makefile +@@ -1,4 +1,4 @@ +-obj-y += b2c2/ saa7146/ siano/ ++obj-y += b2c2/ saa7146/ saa716x/ siano/ + obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o + obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o + obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +diff --git a/drivers/media/common/saa716x/Kconfig b/drivers/media/common/saa716x/Kconfig +new file mode 100644 +index 0000000..e667a58 +--- /dev/null ++++ b/drivers/media/common/saa716x/Kconfig +@@ -0,0 +1,67 @@ ++menuconfig SAA716X_SUPPORT ++ bool "Support for SAA716x family from NXP/Philips" ++ depends on PCI && I2C ++ help ++ support for saa716x ++ ++if SAA716X_SUPPORT ++config SAA716X_CORE ++ tristate "SAA7160/1/2 PCI Express bridge based devices" ++ depends on PCI && I2C ++ ++ help ++ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_BUDGET ++ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" ++ depends on SAA716X_CORE && DVB_CORE ++ select DVB_DS3000 if !DVB_FE_CUSTOMISE ++ select DVB_DS3103 if !DVB_FE_CUSTOMISE ++ select DVB_TS2022 if !DVB_FE_CUSTOMISE ++ ++ help ++ Support for the SAA7160/1/2 based Budget PCIe DVB cards ++ Currently supported devices are: ++ ++ * KNC1 Dual S2 (DVB-S, DVB-S/S2) ++ * Twinhan/Azurewave VP-1028 (DVB-S) ++ * Twinhan/Azurewave VP-3071 (DVB-T x2) ++ * Twinhan/Azurewave VP-6002 (DVB-S) ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_HYBRID ++ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" ++ depends on SAA716X_CORE && DVB_CORE ++ ++ help ++ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards ++ Currently supported devices are: ++ ++ * Avermedia H-788 (DVB-T) ++ * Avermedia HC-82 (DVB-T) ++ * NXP Reference (Atlantis) (DVB-T x2) ++ * NXP Reference (Nemo) (DVB-T) ++ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) ++ ++ Say Y if you own such a device and want to use it. ++ ++#config DVB_SAA716X_FF ++# tristate "SAA7160/1/2 based Full Fledged PCIe cards" ++# depends on SAA716X_CORE && DVB_CORE ++# depends on INPUT # IR ++# default n ++ ++# help ++# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards ++# These cards do feature a hardware MPEG decoder and other ++# peripherals. Also known as Premium cards. ++# Currently supported devices are: ++ ++# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) ++ ++# Say Y if you own such a device and want to use it. ++ ++endif # SAA716X_SUPPORT +diff --git a/drivers/media/common/saa716x/Makefile b/drivers/media/common/saa716x/Makefile +new file mode 100644 +index 0000000..c86f224 +--- /dev/null ++++ b/drivers/media/common/saa716x/Makefile +@@ -0,0 +1,26 @@ ++saa716x_core-objs := saa716x_pci.o \ ++ saa716x_i2c.o \ ++ saa716x_cgu.o \ ++ saa716x_msi.o \ ++ saa716x_dma.o \ ++ saa716x_vip.o \ ++ saa716x_aip.o \ ++ saa716x_phi.o \ ++ saa716x_boot.o \ ++ saa716x_fgpi.o \ ++ saa716x_adap.o \ ++ saa716x_gpio.o \ ++ saa716x_greg.o \ ++ saa716x_rom.o \ ++ saa716x_spi.o ++ ++#saa716x_ff-objs := saa716x_ff_main.o \ ++# saa716x_ff_cmd.o \ ++# saa716x_ff_ir.o ++ ++obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o ++obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o ++obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o ++#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o ++ ++EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ +diff --git a/drivers/media/common/saa716x/saa716x_adap.c b/drivers/media/common/saa716x/saa716x_adap.c +new file mode 100644 +index 0000000..6d7346c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_adap.c +@@ -0,0 +1,274 @@ ++#include ++ ++#include "dmxdev.h" ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dvb_frontend.h" ++ ++#include "saa716x_mod.h" ++#include "saa716x_spi.h" ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_gpio.h" ++#include "saa716x_priv.h" ++#include "saa716x_budget.h" ++ ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++ ++void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ struct fgpi_stream_params params; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); ++ ++ params.bits = 8; ++ params.samples = 188; ++ params.lines = 348; ++ params.pitch = 188; ++ params.offset = 0; ++ params.page_tables = 0; ++ params.stream_type = FGPI_TRANSPORT_STREAM; ++ params.stream_flags = 0; ++ ++ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); ++} ++ ++void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); ++ ++ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); ++} ++ ++static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds++; ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", ++ saa716x_adap->feeds); ++ ++ if (saa716x_adap->feeds == 1) { ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); ++ saa716x_dma_start(saa716x, saa716x_adap->count); ++ } ++ ++ return saa716x_adap->feeds; ++} ++ ++static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds--; ++ if (saa716x_adap->feeds == 0) { ++ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); ++ saa716x_dma_stop(saa716x, saa716x_adap->count); ++ } ++ ++ return 0; ++} ++ ++int saa716x_dvb_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct saa716x_config *config = saa716x->config; ++ int result, i; ++ ++ mutex_init(&saa716x->adap_lock); ++ ++ for (i = 0; i < config->adapters; i++) { ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); ++ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, ++ "SAA716x dvb adapter", ++ THIS_MODULE, ++ &saa716x->pdev->dev, ++ adapter_nr) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); ++ return -ENODEV; ++ } ++ ++ saa716x_adap->count = i; ++ ++ saa716x_adap->dvb_adapter.priv = saa716x_adap; ++ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING; ++ ++ saa716x_adap->demux.priv = saa716x_adap; ++ saa716x_adap->demux.filternum = 256; ++ saa716x_adap->demux.feednum = 256; ++ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; ++ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; ++ saa716x_adap->demux.write_to_decoder = NULL; ++ switch (saa716x->pdev->subsystem_device) { ++ case TEVII_S472: { ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ u8 mac[6]; ++ u8 b0[] = { 0, 9 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .buf = b0, ++ .len = 2 ++ }, { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .buf = mac, ++ .len = 6 ++ } ++ }; ++ ++ i2c_transfer(adapter, msg, 2); ++ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); ++ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); ++ } ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); ++ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err0; ++ } ++ ++ saa716x_adap->dmxdev.filternum = 256; ++ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; ++ saa716x_adap->dmxdev.capabilities = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); ++ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, ++ &saa716x_adap->dvb_adapter)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); ++ goto err1; ++ } ++ ++ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err2; ++ } ++ ++ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_mem)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err3; ++ } ++ ++ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err4; ++ } ++ ++ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); ++// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); ++ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); ++ saa716x_adap->saa716x = saa716x; ++ ++ if (config->frontend_attach) { ++ result = config->frontend_attach(saa716x_adap, i); ++ if (result < 0) ++ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); ++ ++ if (saa716x_adap->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", ++ saa716x->pdev->vendor, ++ saa716x->pdev->device, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ } else { ++ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); ++ if (result < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); ++ goto err6; ++ } ++ } ++ ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); ++ } ++ ++ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, ++ config->adap_config[i].worker); ++ ++ saa716x_adap++; ++ } ++ ++ ++ return 0; ++ ++ /* Error conditions */ ++err6: ++ dvb_frontend_detach(saa716x_adap->fe); ++err4: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++err3: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++err2: ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++err1: ++ dvb_dmx_release(&saa716x_adap->demux); ++err0: ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ return result; ++} ++EXPORT_SYMBOL(saa716x_dvb_init); ++ ++void saa716x_dvb_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ int i; ++ ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ ++ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); ++ ++ if (saa716x_adap->fe) { ++ dvb_unregister_frontend(saa716x_adap->fe); ++ dvb_frontend_detach(saa716x_adap->fe); ++ } ++ ++// tasklet_kill(&saa716x->tasklet); ++ dvb_net_release(&saa716x_adap->dvb_net); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++ dvb_dmx_release(&saa716x_adap->demux); ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ saa716x_adap++; ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(saa716x_dvb_exit); +diff --git a/drivers/media/common/saa716x/saa716x_adap.h b/drivers/media/common/saa716x/saa716x_adap.h +new file mode 100644 +index 0000000..7822e36 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_adap.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_ADAP_H ++#define __SAA716x_ADAP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_dvb_init(struct saa716x_dev *saa716x); ++extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ADAP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_aip.c b/drivers/media/common/saa716x/saa716x_aip.c +new file mode 100644 +index 0000000..3bdb265 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip.c +@@ -0,0 +1,20 @@ ++#include ++ ++#include "saa716x_mod.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_aip.h" ++#include "saa716x_priv.h" ++ ++int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) ++{ ++ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_status); ++ ++void saa716x_aip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(AI0, AI_CTL, 0x00); ++ SAA716x_EPWR(AI1, AI_CTL, 0x00); ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_disable); +diff --git a/drivers/media/common/saa716x/saa716x_aip.h b/drivers/media/common/saa716x/saa716x_aip.h +new file mode 100644 +index 0000000..36277b7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_AIP_H ++#define __SAA716x_AIP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); ++extern void saa716x_aip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_AIP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_aip_reg.h b/drivers/media/common/saa716x/saa716x_aip_reg.h +new file mode 100644 +index 0000000..3e0893a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip_reg.h +@@ -0,0 +1,62 @@ ++#ifndef __SAA716x_AIP_REG_H ++#define __SAA716x_AIP_REG_H ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++#endif /* __SAA716x_AIP_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_boot.c b/drivers/media/common/saa716x/saa716x_boot.c +new file mode 100644 +index 0000000..21e59d0 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_boot.c +@@ -0,0 +1,319 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_cgu_reg.h" ++#include "saa716x_vip_reg.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_gpio_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dcs_reg.h" ++ ++#include "saa716x_boot.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static int saa716x_ext_boot(struct saa716x_dev *saa716x) ++{ ++ /* Write GREG boot_ready to 0 ++ * DW_0 = 0x0001_2018 ++ * DW_1 = 0x0000_0000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); ++ ++ /* Clear VI0 interrupt ++ * DW_2 = 0x0000_0fe8 ++ * DW_3 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); ++ ++ /* Clear VI1 interrupt ++ * DW_4 = 0x0000_1fe8 ++ * DW_5 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); ++ ++ /* CLear FGPI0 interrupt ++ * DW_6 = 0x0000_2fe8 ++ * DW_7 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI1 interrupt ++ * DW_8 = 0x0000_3fe8 ++ * DW_9 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI2 interrupt ++ * DW_10 = 0x0000_4fe8 ++ * DW_11 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI3 interrupt ++ * DW_12 = 0x0000_5fe8 ++ * DW_13 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear AI0 interrupt ++ * DW_14 = 0x0000_6020 ++ * DW_15 = 0x0000_000f ++ */ ++ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); ++ ++ /* Clear AI1 interrupt ++ * DW_16 = 0x0000_7020 ++ * DW_17 = 0x0000_200f ++ */ ++ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); ++ ++ /* Set GREG boot_ready bit to 1 ++ * DW_18 = 0x0001_2018 ++ * DW_19 = 0x0000_2000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++#if 0 ++ /* End of Boot script command ++ * DW_20 = 0x0000_0006 ++ * Where to write this value ?? ++ * This seems very odd an address to trigger the ++ * Boot Control State Machine ! ++ */ ++ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); ++#endif ++ return 0; ++} ++ ++/* Internal Bootscript configuration */ ++static void saa716x_int_boot(struct saa716x_dev *saa716x) ++{ ++ /* #1 Configure PCI COnfig space ++ * GREG_JETSTR_CONFIG_0 ++ */ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); ++ ++ /* GREG_JETSTR_CONFIG_1 ++ * pmcsr_scale:7 = 0x00 ++ * pmcsr_scale:6 = 0x00 ++ * pmcsr_scale:5 = 0x00 ++ * pmcsr_scale:4 = 0x00 ++ * pmcsr_scale:3 = 0x00 ++ * pmcsr_scale:2 = 0x00 ++ * pmcsr_scale:1 = 0x00 ++ * pmcsr_scale:0 = 0x00 ++ * BAR mask = 20 bit ++ * BAR prefetch = no ++ * MSI capable = 32 messages ++ */ ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); ++ ++ /* GREG_JETSTR_CONFIG_2 ++ * pmcsr_data:3 = 0x0 ++ * pmcsr_data:2 = 0x0 ++ * pmcsr_data:1 = 0x0 ++ * pmcsr_data:0 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); ++ ++ /* GREG_JETSTR_CONFIG_3 ++ * pmcsr_data:7 = 0x0 ++ * pmcsr_data:6 = 0x0 ++ * pmcsr_data:5 = 0x0 ++ * pmcsr_data:4 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); ++ ++ /* #2 Release GREG resets ++ * ip_rst_an ++ * dpa1_rst_an ++ * jetsream_reset_an ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); ++ ++ /* #3 GPIO Setup ++ * GPIO 25:24 = Output ++ * GPIO Output "0" after Reset ++ */ ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ ++ /* #4 Custom stuff goes in here */ ++ ++ /* #5 Disable CGU Clocks ++ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG ++ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 ++ */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); ++ ++ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); ++ ++ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); ++ ++ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); ++ ++ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); ++ ++ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); ++ ++ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); ++ ++ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); ++ ++ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); ++ ++ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); ++ ++ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); ++ ++ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); ++ ++ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); ++ ++ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); ++ ++ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); ++ ++ /* #6 Set GREG boot_ready = 0x1 */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++ ++ /* #7 Disable GREG CGU Clock */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); ++ ++ /* End of Bootscript command ?? */ ++} ++ ++int saa716x_core_boot(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_config *config = saa716x->config; ++ ++ switch (config->boot_mode) { ++ case SAA716x_EXT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); ++ saa716x_ext_boot(saa716x); ++ break; ++ case SAA716x_INT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); ++ saa716x_int_boot(saa716x); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_core_boot); ++ ++static void saa716x_bus_report(struct pci_dev *pdev, int enable) ++{ ++ u32 reg; ++ ++ pci_read_config_dword(pdev, 0x04, ®); ++ if (enable) ++ reg |= 0x00000100; /* enable SERR */ ++ else ++ reg &= 0xfffffeff; /* disable SERR */ ++ pci_write_config_dword(pdev, 0x04, reg); ++ ++ pci_read_config_dword(pdev, 0x58, ®); ++ reg &= 0xfffffffd; ++ pci_write_config_dword(pdev, 0x58, reg); ++} ++ ++int saa716x_jetpack_init(struct saa716x_dev *saa716x) ++{ ++ /* ++ * configure PHY through config space not to report ++ * non-fatal error messages to avoid problems with ++ * quirky BIOS'es ++ */ ++ saa716x_bus_report(saa716x->pdev, 0); ++ ++ /* ++ * create time out for blocks that have no clock ++ * helps with lower bitrates on FGPI ++ */ ++ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); ++ ++ /* Reset all blocks */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ switch (saa716x->pdev->device) { ++ case SAA7162: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ ++ break; ++ case SAA7161: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ ++ break; ++ case SAA7160: ++ saa716x->i2c_rate = SAA716x_I2C_RATE_100; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); ++ return -ENODEV; ++ } ++ ++ /* General setup for MMU */ ++ SAA716x_EPWR(MMU, MMU_MODE, 0x14); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_jetpack_init); ++ ++void saa716x_core_reset(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); ++ ++ /* VIP */ ++ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); ++ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); ++ ++ /* FGPI */ ++ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* AIP */ ++ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); ++ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); ++ ++ /* BAM */ ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ /* MMU */ ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ ++ /* MSI */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++} ++EXPORT_SYMBOL_GPL(saa716x_core_reset); +diff --git a/drivers/media/common/saa716x/saa716x_boot.h b/drivers/media/common/saa716x/saa716x_boot.h +new file mode 100644 +index 0000000..8102853 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_boot.h +@@ -0,0 +1,18 @@ ++#ifndef __SAA716x_BOOT_H ++#define __SAA716x_BOOT_H ++ ++#define DISABLE_TIMEOUT 0x17 ++#define ENABLE_TIMEOUT 0x16 ++ ++enum saa716x_boot_mode { ++ SAA716x_EXT_BOOT = 1, ++ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++extern void saa716x_core_reset(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_BOOT_H */ +diff --git a/drivers/media/common/saa716x/saa716x_budget.c b/drivers/media/common/saa716x/saa716x_budget.c +new file mode 100644 +index 0000000..6b52fc1 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_budget.c +@@ -0,0 +1,717 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_budget.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "mb86a16.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "ds3103.h" ++#include "ts2022.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Budget" ++ ++static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); ++ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_budget_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" ++#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" ++ ++static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp3071_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP3071, ++ .dev_type = SAA716x_DEV_TWINHAN_VP3071, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_vp3071_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" ++#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" ++ ++static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp1028_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp1028_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count == 0) { ++ ++ mutex_lock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); ++ saa716x_gpio_set_output(saa716x, 10); ++ msleep(1); ++ ++ /* VP-1028 has inverted power supply control */ ++ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ ++ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ ++ msleep(100); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); ++ saa716x_gpio_set_output(saa716x, 12); ++ msleep(1); ++ ++ /* reset demodulator (Active LOW) */ ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 0); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ ++ mutex_unlock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp1028_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp1028_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP1028, ++ .dev_type = SAA716x_DEV_TWINHAN_VP1028, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp1028_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" ++#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" ++ ++static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp6002_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6002, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6002, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6002_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" ++#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" ++ ++static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_knc1_duals2_config = { ++ .model_name = SAA716x_MODEL_KNC1_DUALS2, ++ .dev_type = SAA716x_DEV_KNC1_DUALS2, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_knc1_duals2_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" ++#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" ++ ++static struct stv090x_config skystar2_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 8000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_sleep = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static int skystar2_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ int err; ++ u8 en = 0; ++ u8 sel = 0; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ en = 0; ++ break; ++ ++ case SEC_VOLTAGE_13: ++ en = 1; ++ sel = 0; ++ break; ++ ++ case SEC_VOLTAGE_18: ++ en = 1; ++ sel = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ err = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0); ++ if (err < 0) ++ goto exit; ++ err = skystar2_stv090x_config.set_gpio(fe, 3, 0, sel, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) ++{ ++ int err; ++ u8 value; ++ ++ if (arg) ++ value = 1; ++ else ++ value = 0; ++ ++ err = skystar2_stv090x_config.set_gpio(fe, 4, 0, value, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static struct stv6110x_config skystar2_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 16000000, ++ .clk_div = 2, ++}; ++ ++static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct stv6110x_devctl *ctl; ++ ++ if (count < saa716x->config->adapters) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ saa716x_gpio_set_output(saa716x, 26); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(stv090x_attach, ++ &skystar2_stv090x_config, ++ &i2c->i2c_adapter, ++ STV090x_DEMODULATOR_0); ++ ++ if (adapter->fe) { ++ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", ++ skystar2_stv090x_config.address); ++ } else { ++ goto exit; ++ } ++ ++ adapter->fe->ops.set_voltage = skystar2_set_voltage; ++ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; ++ ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &skystar2_stv6110x_config, ++ &i2c->i2c_adapter); ++ ++ if (ctl) { ++ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", ++ skystar2_stv6110x_config.addr); ++ ++ skystar2_stv090x_config.tuner_init = ctl->tuner_init; ++ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config skystar2_express_hd_config = { ++ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, ++ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = skystar2_express_hd_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct ds3103_config s472_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 1, ++}; ++ ++static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count != 0) ++ return 0; ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); ++ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, ++ &i2c->i2c_adapter); ++ ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", ++ s472_ds3103_config.demod_address); ++ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) ++ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); ++ else ++ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ ++} ++ ++static struct saa716x_config tevii_s472_config = { ++ .model_name = "TeVii S472 DVB-S2", ++ .dev_type = "DVB-S/S2", ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_s472_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct pci_device_id saa716x_budget_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ ++ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), ++ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), ++ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); ++ ++static struct pci_driver saa716x_budget_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_budget_pci_table, ++ .probe = saa716x_budget_pci_probe, ++ .remove = saa716x_budget_pci_remove, ++}; ++ ++static int saa716x_budget_init(void) ++{ ++ return pci_register_driver(&saa716x_budget_pci_driver); ++} ++ ++static void saa716x_budget_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_budget_pci_driver); ++} ++ ++module_init(saa716x_budget_init); ++module_exit(saa716x_budget_exit); ++ ++MODULE_DESCRIPTION("SAA716x Budget driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_budget.h b/drivers/media/common/saa716x/saa716x_budget.h +new file mode 100644 +index 0000000..d6b8c46 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_budget.h +@@ -0,0 +1,17 @@ ++#ifndef __SAA716x_BUDGET_H ++#define __SAA716x_BUDGET_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define TWINHAN_VP_3071 0x0039 ++#define TWINHAN_VP_1028 0x0044 ++#define TWINHAN_VP_6002 0x0047 ++ ++#define KNC_One 0x1894 ++#define KNC_Dual_S2 0x0110 ++ ++#define TECHNISAT 0x1AE4 ++#define SKYSTAR2_EXPRESS_HD 0x0700 ++#define TEVII 0x9022 ++#define TEVII_S472 0xd472 ++ ++#endif /* __SAA716x_BUDGET_H */ +diff --git a/drivers/media/common/saa716x/saa716x_cgu.c b/drivers/media/common/saa716x/saa716x_cgu.c +new file mode 100644 +index 0000000..a0ffb04 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu.c +@@ -0,0 +1,539 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_cgu_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++u32 cgu_clk[14] = { ++ CGU_FDC_0, ++ CGU_FDC_1, ++ CGU_FDC_2, ++ CGU_FDC_3, ++ CGU_FDC_4, ++ CGU_FDC_5, ++ CGU_FDC_6, ++ CGU_FDC_7, ++ CGU_FDC_8, ++ CGU_FDC_9, ++ CGU_FDC_10, ++ CGU_FDC_11, ++ CGU_FDC_12, ++ CGU_FDC_13 ++}; ++ ++char *clk_desc[14] = { ++ "Clk PSS", ++ "Clk DCS", ++ "Clk SPI", ++ "Clk I2C/Boot", ++ "Clk PHI", ++ "Clk VI0", ++ "Clk VI1", ++ "Clk FGPI0", ++ "Clk FGPI1", ++ "Clk FGPI2", ++ "Clk FGPI3", ++ "Clk AI0", ++ "Clk AI1", ++ "Clk Phy" ++}; ++ ++int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 i; ++ s8 N = 0; ++ s16 M = 0; ++ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ ++ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ ++ ++ /* get all dividers */ ++ for (i = 0; i < CGU_CLKS; i++) { ++ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); ++ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; ++ ++ N = (cgu->clk_boot_div[i] >> 11) & 0xff; ++ N *= -1; ++ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; ++ ++ if (M) ++ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; ++ else ++ cgu->clk_freq[i] = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", ++ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); ++ } ++ /* store clock settings */ ++ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ ++ return 0; ++} ++ ++int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ SAA716x_CGU_CLKRUN(7); ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ SAA716x_CGU_CLKRUN(8); ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ SAA716x_CGU_CLKRUN(9); ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ SAA716x_CGU_CLKRUN(10); ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ SAA716x_CGU_CLKRUN(11); ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ SAA716x_CGU_CLKRUN(12); ++ break; ++ ++ case PORT_ALL: ++ SAA716x_CGU_CLKRUN(5); ++ SAA716x_CGU_CLKRUN(6); ++ SAA716x_CGU_CLKRUN(7); ++ SAA716x_CGU_CLKRUN(8); ++ SAA716x_CGU_CLKRUN(9); ++ SAA716x_CGU_CLKRUN(10); ++ SAA716x_CGU_CLKRUN(11); ++ SAA716x_CGU_CLKRUN(12); ++ ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ cgu->clk_int_port[PORT_AI0] = 1; ++ cgu->clk_int_port[PORT_AI1] = 1; ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ } ++ ++ /* wait for PLL */ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ ++ } ++ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_get_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 *frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_VI0: ++ case CLK_DOMAIN_VI1: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ *frequency = cgu->clk_freq[domain]; ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_set_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u32 M = 1, N = 1, reset, i; ++ s8 N_tmp, M_tmp, sub, add, lsb; ++ ++ ++ if (cgu->clk_freq_min > frequency) ++ frequency = cgu->clk_freq_min; ++ ++ if (cgu->clk_freq_max < frequency) ++ frequency = cgu->clk_freq_max; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ ++ if (frequency == cgu->clk_freq[domain]) ++ return 0; /* same frequency */ ++ break; ++ ++ case CLK_DOMAIN_VI0: ++ ++ if (frequency == cgu->clk_vi_0[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_0[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI1: ++ if (frequency == cgu->clk_vi_1[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_1[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ if (frequency == cgu->clk_vi_0[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_0[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI0; /* change domain */ ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ if (frequency == cgu->clk_vi_1[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_1[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI1; /* change domain */ ++ break; ++ } ++ ++ /* calculate divider */ ++ do { ++ M = (N * PLL_FREQ) / frequency; ++ if (M == 0) ++ N++; ++ ++ } while (M == 0); ++ ++ /* calculate frequency */ ++ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; ++ ++ N_tmp = N & 0xff; ++ M_tmp = M & 0xff; ++ sub = -N_tmp; ++ add = M_tmp - N_tmp; ++ lsb = 4; /* run */ ++ ++ if (((10 * N) / M) < 5) ++ lsb |= 1; /* stretch */ ++ ++ /* store new divider */ ++ cgu->clk_curr_div[domain] = sub & 0xff; ++ cgu->clk_curr_div[domain] <<= 8; ++ cgu->clk_curr_div[domain] = add & 0xff; ++ cgu->clk_curr_div[domain] <<= 3; ++ cgu->clk_curr_div[domain] |= lsb; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", ++ domain, ++ frequency, ++ cgu->clk_freq[domain], ++ N, ++ M, ++ cgu->clk_curr_div[domain]); ++ ++ reset = 0; ++ ++ /* Reset */ ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); ++ ++ /* Reset disable */ ++ for (i = 0; i < 1000; i++) { ++ msleep(10); ++ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); ++ ++ if (cgu->clk_curr_div[domain == reset]) ++ break; ++ } ++ ++ if (cgu->clk_curr_div[domain] != reset) ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); ++ ++ return 0; ++} ++ ++int saa716x_cgu_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ cgu->clk_freq_min = PLL_FREQ / 255; ++ if (PLL_FREQ > (cgu->clk_freq_min * 255)) ++ cgu->clk_freq_min++; ++ ++ cgu->clk_freq_max = PLL_FREQ; ++ ++ saa716x_getbootscript_setup(saa716x); ++ saa716x_set_clk_internal(saa716x, PORT_ALL); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_cgu_init); +diff --git a/drivers/media/common/saa716x/saa716x_cgu.h b/drivers/media/common/saa716x/saa716x_cgu.h +new file mode 100644 +index 0000000..5353cf2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu.h +@@ -0,0 +1,61 @@ ++#ifndef __SAA716x_CGU_H ++#define __SAA716x_CGU_H ++ ++#define PLL_FREQ 2500 ++ ++#define SAA716x_CGU_CLKRUN(__reg) do { \ ++ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ ++ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ ++ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ ++ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ ++} while (0) ++ ++enum saa716x_clk_domain { ++ CLK_DOMAIN_PSS = 0, ++ CLK_DOMAIN_DCS = 1, ++ CLK_DOMAIN_SPI = 2, ++ CLK_DOMAIN_I2C = 3, ++ CLK_DOMAIN_PHI = 4, ++ CLK_DOMAIN_VI0 = 5, ++ CLK_DOMAIN_VI1 = 6, ++ CLK_DOMAIN_FGPI0 = 7, ++ CLK_DOMAIN_FGPI1 = 8, ++ CLK_DOMAIN_FGPI2 = 9, ++ CLK_DOMAIN_FGPI3 = 10, ++ CLK_DOMAIN_AI0 = 11, ++ CLK_DOMAIN_AI1 = 12, ++ CLK_DOMAIN_PHY = 13, ++ CLK_DOMAIN_VI0VBI = 14, ++ CLK_DOMAIN_VI1VBI = 15 ++}; ++ ++#define PORT_VI0_VIDEO 0 ++#define PORT_VI0_VBI 2 ++#define PORT_VI1_VIDEO 3 ++#define PORT_VI1_VBI 5 ++#define PORT_FGPI0 6 ++#define PORT_FGPI1 7 ++#define PORT_FGPI2 8 ++#define PORT_FGPI3 9 ++#define PORT_AI0 10 ++#define PORT_AI1 11 ++#define PORT_ALL 12 ++ ++#define CGU_CLKS 14 ++ ++struct saa716x_cgu { ++ u8 clk_int_port[12]; ++ u32 clk_vi_0[3]; ++ u32 clk_vi_1[3]; ++ u32 clk_boot_div[CGU_CLKS]; ++ u32 clk_curr_div[CGU_CLKS]; ++ u32 clk_freq[CGU_CLKS]; ++ u32 clk_freq_min; ++ u32 clk_freq_max; ++}; ++ ++extern int saa716x_cgu_init(struct saa716x_dev *saa716x); ++extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); ++extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); ++ ++#endif /* __SAA716x_CGU_H */ +diff --git a/drivers/media/common/saa716x/saa716x_cgu_reg.h b/drivers/media/common/saa716x/saa716x_cgu_reg.h +new file mode 100644 +index 0000000..f7d82ae +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu_reg.h +@@ -0,0 +1,178 @@ ++#ifndef __SAA716x_CGU_REG_H ++#define __SAA716x_CGU_REG_H ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++#endif /* __SAA716x_CGU_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dcs_reg.h b/drivers/media/common/saa716x/saa716x_dcs_reg.h +new file mode 100644 +index 0000000..26dba68 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dcs_reg.h +@@ -0,0 +1,56 @@ ++#ifndef __SAA716x_DCS_REG_H ++#define __SAA716x_DCS_REG_H ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_DCS_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dma.c b/drivers/media/common/saa716x/saa716x_dma.c +new file mode 100644 +index 0000000..21d1dd8 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma.c +@@ -0,0 +1,306 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "saa716x_dma.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++/* Allocates one page of memory, which is stores the data of one ++ * 716x page table. The result gets stored in the passed DMA buffer ++ * structure. ++ */ ++static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); ++ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); ++ ++ if (dmabuf->mem_ptab_virt == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); ++ return -ENOMEM; ++ } ++ ++ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, ++ dmabuf->mem_ptab_virt, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ if (dmabuf->mem_ptab_phys == 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); ++ return -ENOMEM; ++ } ++ ++ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); ++ ++ return 0; ++} ++ ++static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); ++ ++ /* free physical PCI memory */ ++ if (dmabuf->mem_ptab_phys != 0) { ++ dma_unmap_single(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ dmabuf->mem_ptab_phys = 0; ++ } ++ ++ /* free kernel memory */ ++ if (dmabuf->mem_ptab_virt != NULL) { ++ free_page((unsigned long) dmabuf->mem_ptab_virt); ++ dmabuf->mem_ptab_virt = NULL; ++ } ++} ++ ++static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG free"); ++ ++ dmabuf->mem_virt = NULL; ++ if (dmabuf->mem_virt_noalign != NULL) { ++ if (dmabuf->dma_type == SAA716x_DMABUF_INT) ++ vfree(dmabuf->mem_virt_noalign); ++ ++ dmabuf->mem_virt_noalign = NULL; ++ } ++ ++ if (dmabuf->sg_list != NULL) { ++ kfree(dmabuf->sg_list); ++ dmabuf->sg_list = NULL; ++ } ++} ++ ++/* ++ * Create a SG, when an allocated buffer is passed to it, ++ * otherwise the needed memory gets allocated by itself ++ */ ++static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct scatterlist *list; ++ struct page *pg; ++ ++ int i, pages; ++ ++ BUG_ON(!(size > 0)); ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG allocate"); ++ ++ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ ++ pages = size / SAA716x_PAGE_SIZE + 1; ++ else ++ pages = size / SAA716x_PAGE_SIZE; ++ ++ /* Allocate memory for SG list */ ++ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); ++ if (dmabuf->sg_list == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); ++ return -ENOMEM; ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); ++ sg_init_table(dmabuf->sg_list, pages); ++ ++ if (buf == NULL) { ++ ++ /* allocate memory, unaligned */ ++ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); ++ if (dmabuf->mem_virt_noalign == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); ++ return -ENOMEM; ++ } ++ ++ /* align memory to page */ ++ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); ++ ++ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); ++ } else { ++ dmabuf->mem_virt = buf; ++ } ++ ++ dmabuf->list_len = pages; /* scatterlist length */ ++ list = dmabuf->sg_list; ++ ++ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); ++ for (i = 0; i < pages; i++) { ++ if (buf == NULL) ++ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ else ++ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ ++ BUG_ON(pg == NULL); ++ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Done!"); ++ return 0; ++} ++ ++/* Fill the "page table" page with the pointers to the specified SG buffer */ ++static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ struct scatterlist *sg_cur; ++ ++ u32 *page; ++ int i, j, k = 0; ++ dma_addr_t addr = 0; ++ ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(sg_list == NULL); ++ BUG_ON(pages == 0); ++ dprintk(SAA716x_DEBUG, 1, "SG page fill"); ++ ++ /* make page writable for the PC */ ++ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); ++ page = dmabuf->mem_ptab_virt; ++ ++ /* create page table */ ++ for (i = 0; i < pages; i++) { ++ sg_cur = &sg_list[i]; ++ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); ++ ++ if (i == 0) ++ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; ++ else ++ BUG_ON(sg_cur->offset != 0); ++ ++ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { ++ ++ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { ++ offset -= SAA716x_PAGE_SIZE; ++ continue; ++ } ++ ++ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; ++ ++ BUG_ON(addr == 0); ++ page[k * 2] = (u32 )addr; /* Low */ ++ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ ++ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); ++ k++; ++ } ++ } ++ ++ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { ++ page[k * 2] = (u32 ) addr; ++ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); ++ } ++ ++ /* make "page table" page writable for the PC */ ++ dma_sync_single_for_device(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_device(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_cpu(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++} ++ ++/* Allocates a DMA buffer for the specified external linear buffer. */ ++int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ int ret; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(! (size > 0)); ++ ++ dmabuf->dma_type = SAA716x_DMABUF_INT; ++ ++ dmabuf->mem_virt_noalign = NULL; ++ dmabuf->mem_virt = NULL; ++ dmabuf->mem_ptab_phys = 0; ++ dmabuf->mem_ptab_virt = NULL; ++ ++ dmabuf->list_len = 0; ++ dmabuf->saa716x = saa716x; ++ ++ /* Allocate page table */ ++ ret = saa716x_allocate_ptable(dmabuf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); ++ goto err1; ++ } ++ ++ /* Allocate buffer as SG */ ++ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); ++ goto err2; ++ } ++ ++ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG map failed"); ++ goto err3; ++ } ++ ++ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); ++ ++ return 0; ++err3: ++ saa716x_dmabuf_sgfree(dmabuf); ++err2: ++ saa716x_free_ptable(dmabuf); ++err1: ++ return ret; ++} ++ ++void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ ++ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ saa716x_dmabuf_sgfree(dmabuf); ++ saa716x_free_ptable(dmabuf); ++} +diff --git a/drivers/media/common/saa716x/saa716x_dma.h b/drivers/media/common/saa716x/saa716x_dma.h +new file mode 100644 +index 0000000..f92d667 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma.h +@@ -0,0 +1,38 @@ ++#ifndef __SAA716x_DMA_H ++#define __SAA716x_DMA_H ++ ++#define SAA716x_PAGE_SIZE 4096 ++ ++enum saa716x_dma_type { ++ SAA716x_DMABUF_EXT_LIN, /* Linear external */ ++ SAA716x_DMABUF_EXT_SG, /* SG external */ ++ SAA716x_DMABUF_INT /* Linear internal */ ++}; ++ ++struct saa716x_dev; ++ ++struct saa716x_dmabuf { ++ enum saa716x_dma_type dma_type; ++ ++ void *mem_virt_noalign; ++ void *mem_virt; /* page aligned */ ++ dma_addr_t mem_ptab_phys; ++ void *mem_ptab_virt; ++ void *sg_list; /* SG list */ ++ ++ struct saa716x_dev *saa716x; ++ ++ int list_len; /* buffer len */ ++ int offset; /* page offset */ ++}; ++ ++extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf, ++ int size); ++extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf); ++ ++extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); ++extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); ++ ++#endif /* __SAA716x_DMA_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dma_reg.h b/drivers/media/common/saa716x/saa716x_dma_reg.h +new file mode 100644 +index 0000000..6037ca9 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma_reg.h +@@ -0,0 +1,200 @@ ++#ifndef __SAA716x_DMA_REG_H ++#define __SAA716x_DMA_REG_H ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++#endif /* __SAA716x_DMA_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff.h b/drivers/media/common/saa716x/saa716x_ff.h +new file mode 100644 +index 0000000..cb65929 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff.h +@@ -0,0 +1,158 @@ ++#ifndef __SAA716x_FF_H ++#define __SAA716x_FF_H ++ ++#include "dvb_filter.h" ++#include "dvb_ringbuffer.h" ++ ++#define TECHNOTREND 0x13c2 ++#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 ++#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A ++ ++#define TT_PREMIUM_GPIO_POWER_ENABLE 27 ++#define TT_PREMIUM_GPIO_RESET_BACKEND 26 ++#define TT_PREMIUM_GPIO_FPGA_CS1 17 ++#define TT_PREMIUM_GPIO_FPGA_CS0 16 ++#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 ++#define TT_PREMIUM_GPIO_FPGA_DONE 14 ++#define TT_PREMIUM_GPIO_FPGA_INITN 13 ++ ++/* fpga interrupt register addresses */ ++#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ ++#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ ++#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ ++#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ ++#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ ++#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ ++#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ ++#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ ++ ++/* fpga TS router register addresses */ ++#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ ++#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ ++#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ ++#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ ++#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ ++#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ ++ ++#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ ++#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ ++#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ ++#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ ++#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ ++#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ ++ ++/* fpga TS FIFO register addresses */ ++#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ ++#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ ++ ++#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ ++ ++#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ ++ ++#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ ++#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ ++#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ ++#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ ++#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ ++#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ ++#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ ++#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ ++#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ ++#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ ++#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ ++#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ ++#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ ++#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ ++#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ ++#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ ++ ++#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ ++#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ ++#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ ++#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ ++#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ ++#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ ++#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ ++#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ ++#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ ++#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ ++ ++#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ ++#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ ++#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ ++#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ ++#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ ++ ++#define SIZE_BLOCK_HEADER 8 /* block header size */ ++ ++#define MAX_RESULT_LEN 256 ++#define MAX_DATA_LEN (1024 * 1024) ++ ++#define TSOUT_LEN (1024 * TS_SIZE) ++#define TSBUF_LEN (8 * 1024) ++ ++/* place to store all the necessary device information */ ++struct sti7109_dev { ++ struct saa716x_dev *dev; ++ struct dvb_device *osd_dev; ++ struct dvb_device *video_dev; ++ struct dvb_device *audio_dev; ++ ++ void *iobuf; /* memory for all buffers */ ++ struct dvb_ringbuffer tsout; /* buffer for TS output */ ++ u8 *tsbuf; /* temp ts buffer */ ++ ++ struct tasklet_struct fifo_tasklet; ++ ++ wait_queue_head_t boot_finish_wq; ++ int boot_finished; ++ ++ wait_queue_head_t cmd_ready_wq; ++ int cmd_ready; ++ u8 cmd_data[SIZE_CMD_DATA]; ++ u32 cmd_len; ++ ++ wait_queue_head_t result_avail_wq; ++ int result_avail; ++ u8 result_data[MAX_RESULT_LEN]; ++ u32 result_len; ++ u32 result_max_len; ++ ++ wait_queue_head_t osd_cmd_ready_wq; ++ int osd_cmd_ready; ++ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; ++ u32 osd_cmd_len; ++ ++ wait_queue_head_t osd_result_avail_wq; ++ int osd_result_avail; ++ u8 osd_result_data[MAX_RESULT_LEN]; ++ u32 osd_result_len; ++ u32 osd_result_max_len; ++ ++ u16 data_handle; ++ u8 *data_buffer; /* raw data transfer buffer */ ++ wait_queue_head_t data_ready_wq; ++ int data_ready; ++ wait_queue_head_t block_done_wq; ++ int block_done; ++ ++ struct mutex cmd_lock; ++ struct mutex osd_cmd_lock; ++ struct mutex data_lock; ++ ++ u64 audio_pts; ++ u64 video_pts; ++ u64 current_stc; ++ ++ u32 int_count_enable; ++ u32 total_int_count; ++ u32 fgpi_int_count[2]; ++ u32 i2c_int_count[2]; ++ u32 ext_int_total_count; ++ u32 ext_int_source_count[16]; ++ u32 last_int_ticks; ++ ++ u16 fpga_version; ++}; ++ ++#endif /* __SAA716x_FF_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.c b/drivers/media/common/saa716x/saa716x_ff_cmd.c +new file mode 100644 +index 0000000..81c1078 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_cmd.c +@@ -0,0 +1,412 @@ ++#include ++ ++#include ++#include ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_phi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++ ++int sti7109_cmd_init(struct sti7109_dev *sti7109) ++{ ++ mutex_init(&sti7109->cmd_lock); ++ mutex_init(&sti7109->osd_cmd_lock); ++ mutex_init(&sti7109->data_lock); ++ ++ init_waitqueue_head(&sti7109->boot_finish_wq); ++ sti7109->boot_finished = 0; ++ ++ init_waitqueue_head(&sti7109->cmd_ready_wq); ++ sti7109->cmd_ready = 0; ++ ++ init_waitqueue_head(&sti7109->result_avail_wq); ++ sti7109->result_avail = 0; ++ ++ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); ++ sti7109->osd_cmd_ready = 0; ++ init_waitqueue_head(&sti7109->osd_result_avail_wq); ++ sti7109->osd_result_avail = 0; ++ ++ sti7109->data_handle = 0; ++ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); ++ init_waitqueue_head(&sti7109->data_ready_wq); ++ sti7109->data_ready = 0; ++ init_waitqueue_head(&sti7109->block_done_wq); ++ sti7109->block_done = 0; ++ return 0; ++} ++ ++static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, ++ sti7109->cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command ready"); ++ return -EIO; ++ } ++ ++ sti7109->cmd_ready = 0; ++ sti7109->result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, ++ sti7109->cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); ++ ++ if (sti7109->result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->result_avail_wq, ++ sti7109->result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { ++ sti7109->result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->result_len > sti7109->result_max_len) { ++ sti7109->result_len = sti7109->result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->cmd_len = cmd->cmd_len; ++ sti7109->result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->result_len; ++ if (sti7109->result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->result_data, ++ sti7109->result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, ++ sti7109->osd_cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command ready"); ++ return -EIO; ++ } ++ ++ sti7109->osd_cmd_ready = 0; ++ sti7109->osd_result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, ++ sti7109->osd_cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); ++ ++ if (sti7109->osd_result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->osd_result_avail_wq, ++ sti7109->osd_result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { ++ sti7109->osd_result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, ++ "osd result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { ++ sti7109->osd_result_len = sti7109->osd_result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->osd_cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->osd_cmd_len = cmd->cmd_len; ++ sti7109->osd_result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_osd_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->osd_result_len; ++ if (sti7109->osd_result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->osd_result_data, ++ sti7109->osd_result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->osd_cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ u16 blockSize; ++ u16 lastBlockSize; ++ u16 numBlocks; ++ u16 blockIndex; ++ u8 blockHeader[SIZE_BLOCK_HEADER]; ++ u8 * blockPtr; ++ int activeBlock; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, ++ sti7109->data_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); ++ return -EIO; ++ } ++ ++ sti7109->data_ready = 0; ++ ++ /* ++ * 8 bytes is the size of the block header. Block header structure is: ++ * 16 bit - block index ++ * 16 bit - number of blocks ++ * 16 bit - current block data size ++ * 16 bit - block handle. This is used to reference the data in the ++ * command that uses it. ++ */ ++ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; ++ numBlocks = data->data_length / blockSize; ++ lastBlockSize = data->data_length % blockSize; ++ if (lastBlockSize > 0) ++ numBlocks++; ++ ++ blockHeader[2] = (u8) (numBlocks >> 8); ++ blockHeader[3] = (u8) numBlocks; ++ blockHeader[6] = (u8) (sti7109->data_handle >> 8); ++ blockHeader[7] = (u8) sti7109->data_handle; ++ blockPtr = sti7109->data_buffer; ++ activeBlock = 0; ++ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { ++ u32 addr; ++ ++ if (lastBlockSize && (blockIndex == (numBlocks - 1))) ++ blockSize = lastBlockSize; ++ ++ blockHeader[0] = (uint8_t) (blockIndex >> 8); ++ blockHeader[1] = (uint8_t) blockIndex; ++ blockHeader[4] = (uint8_t) (blockSize >> 8); ++ blockHeader[5] = (uint8_t) blockSize; ++ ++ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); ++ saa716x_phi_write(saa716x, addr, blockHeader, ++ SIZE_BLOCK_HEADER); ++ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, ++ blockSize); ++ activeBlock = (activeBlock + 1) & 1; ++ if (blockIndex > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for block done"); ++ return -EIO; ++ } ++ } ++ sti7109->block_done = 0; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); ++ blockPtr += blockSize; ++ } ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); ++ return -EIO; ++ } ++ sti7109->block_done = 0; ++ ++ data->data_handle = sti7109->data_handle; ++ sti7109->data_handle++; ++ return 0; ++} ++ ++int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (data->data_length > MAX_DATA_LEN) { ++ dprintk(SAA716x_ERROR, 1, "data too big"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->data_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->data_buffer, ++ (void __user *)data->data_buffer, ++ data->data_length)) ++ goto out; ++ ++ err = sti7109_do_raw_data(sti7109, data); ++ if (err) ++ goto out; ++ ++out: ++ mutex_unlock(&sti7109->data_lock); ++ return err; ++} ++ ++int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x04; ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x00; ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x00; ++ sti7109->cmd_len = 6; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ *fw_version = (sti7109->result_data[6] << 16) ++ | (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ ++int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x05; /* command length */ ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x10; /* get video format info command */ ++ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ ++ sti7109->cmd_len = 7; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ vs->w = (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ vs->h = (sti7109->result_data[9] << 8) ++ | sti7109->result_data[10]; ++ vs->aspect_ratio = sti7109->result_data[11] >> 4; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ +diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.h b/drivers/media/common/saa716x/saa716x_ff_cmd.h +new file mode 100644 +index 0000000..fc79f08 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_cmd.h +@@ -0,0 +1,16 @@ ++#ifndef __SAA716x_FF_CMD_H ++#define __SAA716x_FF_CMD_H ++ ++extern int sti7109_cmd_init(struct sti7109_dev *sti7109); ++extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_data(struct sti7109_dev * sti7109, ++ osd_raw_data_t * data); ++extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, ++ u32 *fw_version); ++extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, ++ video_size_t *vs); ++ ++#endif /* __SAA716x_FF_CMD_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff_ir.c b/drivers/media/common/saa716x/saa716x_ff_ir.c +new file mode 100644 +index 0000000..3562478 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_ir.c +@@ -0,0 +1,265 @@ ++/* ++ * Driver for the remote control of the TT6400 DVB-S2 card ++ * ++ * Copyright (C) 2010 Oliver Endriss ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++ ++ ++/* infrared remote control */ ++struct infrared { ++ u16 key_map[128]; ++ struct input_dev *input_dev; ++ char input_phys[32]; ++ struct timer_list keyup_timer; ++ struct tasklet_struct tasklet; ++ u32 command; ++ u32 device_mask; ++ u8 protocol; ++ u16 last_key; ++ u16 last_toggle; ++ bool delay_timer_finished; ++}; ++ ++#define IR_RC5 0 ++#define UP_TIMEOUT (HZ*7/25) ++ ++ ++/* key-up timer */ ++static void ir_emit_keyup(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) ++ return; ++ ++ input_report_key(ir->input_dev, ir->last_key, 0); ++ input_sync(ir->input_dev); ++} ++ ++ ++/* tasklet */ ++static void ir_emit_key(unsigned long parm) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; ++ struct infrared *ir = saa716x->ir_priv; ++ u32 ircom = ir->command; ++ u8 data; ++ u8 addr; ++ u16 toggle; ++ u16 keycode; ++ ++ /* extract device address and data */ ++ if (ircom & 0x80000000) { /* CEC remote command */ ++ addr = 0; ++ data = ircom & 0x7F; ++ toggle = 0; ++ } else { ++ switch (ir->protocol) { ++ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ ++ addr = (ircom >> 6) & 0x1f; ++ /* data bits 1..6 */ ++ data = ircom & 0x3f; ++ /* data bit 7 (inverted) */ ++ if (!(ircom & 0x1000)) ++ data |= 0x40; ++ toggle = ircom & 0x0800; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: invalid protocol %x\n", ++ __func__, ir->protocol); ++ return; ++ } ++ } ++ ++ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); ++ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); ++ ++ keycode = ir->key_map[data]; ++ ++ dprintk(SAA716x_DEBUG, 0, ++ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", ++ __func__, ircom, addr, data, keycode); ++ ++ /* check device address */ ++ if (!(ir->device_mask & (1 << addr))) ++ return; ++ ++ if (!keycode) { ++ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", ++ __func__, ircom, addr, data); ++ return; ++ } ++ ++ if (timer_pending(&ir->keyup_timer)) { ++ del_timer(&ir->keyup_timer); ++ if (ir->last_key != keycode || toggle != ir->last_toggle) { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } else if (ir->delay_timer_finished) { ++ input_event(ir->input_dev, EV_KEY, keycode, 2); ++ input_sync(ir->input_dev); ++ } ++ } else { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } ++ ++ ir->last_key = keycode; ++ ir->last_toggle = toggle; ++ ++ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; ++ add_timer(&ir->keyup_timer); ++ ++} ++ ++ ++/* register with input layer */ ++static void ir_register_keys(struct infrared *ir) ++{ ++ int i; ++ ++ set_bit(EV_KEY, ir->input_dev->evbit); ++ set_bit(EV_REP, ir->input_dev->evbit); ++ set_bit(EV_MSC, ir->input_dev->evbit); ++ ++ set_bit(MSC_RAW, ir->input_dev->mscbit); ++ set_bit(MSC_SCAN, ir->input_dev->mscbit); ++ ++ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); ++ ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { ++ if (ir->key_map[i] > KEY_MAX) ++ ir->key_map[i] = 0; ++ else if (ir->key_map[i] > KEY_RESERVED) ++ set_bit(ir->key_map[i], ir->input_dev->keybit); ++ } ++ ++ ir->input_dev->keycode = ir->key_map; ++ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); ++ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); ++} ++ ++ ++/* called by the input driver after rep[REP_DELAY] ms */ ++static void ir_repeat_key(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ ir->delay_timer_finished = true; ++} ++ ++ ++/* interrupt handler */ ++void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ if (!ir) ++ return; ++ ++ ir->command = ir_cmd; ++ tasklet_schedule(&ir->tasklet); ++} ++ ++ ++int saa716x_ir_init(struct saa716x_dev *saa716x) ++{ ++ struct input_dev *input_dev; ++ struct infrared *ir; ++ int rc; ++ int i; ++ ++ if (!saa716x) ++ return -ENOMEM; ++ ++ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); ++ if (!ir) ++ return -ENOMEM; ++ ++ init_timer(&ir->keyup_timer); ++ ir->keyup_timer.function = ir_emit_keyup; ++ ir->keyup_timer.data = (unsigned long) ir; ++ ++ input_dev = input_allocate_device(); ++ if (!input_dev) ++ goto err; ++ ++ ir->input_dev = input_dev; ++ input_dev->name = "TT6400 DVB IR receiver"; ++ snprintf(ir->input_phys, sizeof(ir->input_phys), ++ "pci-%s/ir0", pci_name(saa716x->pdev)); ++ input_dev->phys = ir->input_phys; ++ input_dev->id.bustype = BUS_PCI; ++ input_dev->id.version = 1; ++ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; ++ input_dev->id.product = saa716x->pdev->subsystem_device; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ input_dev->dev.parent = &saa716x->pdev->dev; ++#else ++ input_dev->cdev.dev = &saa716x->pdev->dev; ++#endif ++ rc = input_register_device(input_dev); ++ if (rc) ++ goto err; ++ ++ /* TODO: fix setup/keymap */ ++ ir->protocol = IR_RC5; ++ ir->device_mask = 0xffffffff; ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) ++ ir->key_map[i] = i+1; ++ ir_register_keys(ir); ++ ++ /* override repeat timer */ ++ input_dev->timer.function = ir_repeat_key; ++ input_dev->timer.data = (unsigned long) ir; ++ ++ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); ++ saa716x->ir_priv = ir; ++ ++ return 0; ++ ++err: ++ if (ir->input_dev) ++ input_free_device(ir->input_dev); ++ kfree(ir); ++ return -ENOMEM; ++} ++ ++ ++void saa716x_ir_exit(struct saa716x_dev *saa716x) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ saa716x->ir_priv = NULL; ++ tasklet_kill(&ir->tasklet); ++ del_timer_sync(&ir->keyup_timer); ++ input_unregister_device(ir->input_dev); ++ kfree(ir); ++} +diff --git a/drivers/media/common/saa716x/saa716x_ff_main.c b/drivers/media/common/saa716x/saa716x_ff_main.c +new file mode 100644 +index 0000000..34093c2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_main.c +@@ -0,0 +1,1535 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_dma_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_phi_reg.h" ++#include "saa716x_spi_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_vip.h" ++#include "saa716x_aip.h" ++#include "saa716x_msi.h" ++#include "saa716x_adap.h" ++#include "saa716x_gpio.h" ++#include "saa716x_phi.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "isl6423.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++unsigned int int_count_enable; ++module_param(int_count_enable, int, 0644); ++MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); ++ ++#define DRIVER_NAME "SAA716x FF" ++ ++static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ int fpgaInit; ++ int fpgaDone; ++ int rounds; ++ int ret; ++ const struct firmware *fw; ++ ++ /* request the FPGA firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," ++ " file not found: dvb-ttpremium-fpga-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ /* set FPGA PROGRAMN high */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN low to set it into configuration mode */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN high to start configuration process */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ ++ rounds = 0; ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ while (fpgaInit == 0 && rounds < 5000) { ++ //msleep(1); ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ rounds++; ++ } ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", ++ fpgaInit, rounds); ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); ++ ++ msleep(10); ++ ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); ++ saa716x_spi_write(saa716x, fw->data, fw->size); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ if (!fpgaDone) { ++ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " ++ "connect the power supply?\n"); ++ return -EINVAL; ++ } ++ ++ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); ++ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", ++ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); ++ ++ return 0; ++} ++ ++static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) ++{ ++ int i; ++ int length; ++ u32 requestedBlock; ++ u32 writtenBlock; ++ u32 numBlocks; ++ u32 blockSize; ++ u32 lastBlockSize; ++ u64 startTime; ++ u64 currentTime; ++ u64 waitTime; ++ int ret; ++ const struct firmware *fw; ++ u32 loaderVersion; ++ ++ /* request the st7109 loader, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," ++ " file not found: dvb-ttpremium-loader-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; ++ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", ++ loaderVersion >> 8, loaderVersion & 0xFF); ++ ++ saa716x_phi_write(saa716x, 0, fw->data, fw->size); ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ /* take ST out of reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); ++ ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == 1) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ return -1; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); ++ ++ /* request the st7109 firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," ++ " file not found: dvb-ttpremium-st7109-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); ++ writtenBlock = 0; ++ blockSize = 0x3c00; ++ length = fw->size; ++ numBlocks = length / blockSize; ++ lastBlockSize = length % blockSize; ++ for (i = 0; i < length; i += blockSize) { ++ writtenBlock++; ++ /* write one block (last may differ from blockSize) */ ++ if (lastBlockSize && writtenBlock == (numBlocks + 1)) ++ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); ++ else ++ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); ++ ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == (writtenBlock + 1)) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ release_firmware(fw); ++ return -1; ++ } ++ } ++ ++ /* disable frontend support through ST firmware */ ++ SAA716x_EPWR(PHI_1, 0x3ff4, 1); ++ ++ /* indicate end of transfer */ ++ writtenBlock++; ++ writtenBlock |= 0x80000000; ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); ++ ++ release_firmware(fw); ++ ++ return 0; ++} ++ ++static int saa716x_usercopy(struct dvb_device *dvbdev, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct dvb_device *dvbdev, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *) arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) ++ { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_osd_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_osd_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ int err = -EINVAL; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ if (cmd == OSD_RAW_CMD) { ++ osd_raw_cmd_t raw_cmd; ++ u8 hdr[4]; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_cmd, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) ++ goto out; ++ ++ if (hdr[3] == 4) ++ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); ++ else ++ err = sti7109_raw_cmd(sti7109, &raw_cmd); ++ ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ else if (cmd == OSD_RAW_DATA) { ++ osd_raw_data_t raw_data; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_data, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ err = sti7109_raw_data(sti7109, &raw_data); ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ ++out: ++ return err; ++} ++ ++static struct file_operations dvb_osd_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_osd_ioctl, ++#else ++ .unlocked_ioctl = dvb_osd_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_osd = { ++ .priv = NULL, ++ .users = 2, ++ .writers = 2, ++ .fops = &dvb_osd_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->osd_dev); ++ return 0; ++} ++ ++static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->osd_dev, ++ &dvbdev_osd, ++ sti7109, ++ DVB_DEVICE_OSD); ++ ++ return 0; ++} ++ ++static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ //struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case AUDIO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->audio_pts; ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_audio_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_audio_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); ++} ++ ++static struct file_operations dvb_audio_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_audio_ioctl, ++#else ++ .unlocked_ioctl = dvb_audio_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_audio_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->audio_dev); ++ return 0; ++} ++ ++static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->audio_dev, ++ &dvbdev_audio, ++ sti7109, ++ DVB_DEVICE_AUDIO); ++ ++ return 0; ++} ++ ++static void fifo_worker(unsigned long data) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ u32 fifoCtrl; ++ u32 fifoStat; ++ u16 fifoSize; ++ u16 fifoUsage; ++ u16 fifoFree; ++ int len; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); ++ fifoSize = (u16) (fifoStat >> 16); ++ fifoUsage = (u16) fifoStat; ++ fifoFree = fifoSize - fifoUsage; ++ spin_lock(&sti7109->tsout.lock); ++ len = dvb_ringbuffer_avail(&sti7109->tsout); ++ if (len > fifoFree) ++ len = fifoFree; ++ if (len >= TS_SIZE) ++ { ++ while (len >= TS_SIZE) ++ { ++ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); ++ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); ++ len -= TS_SIZE; ++ } ++ wake_up(&sti7109->tsout.queue); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ spin_unlock(&sti7109->tsout.lock); ++} ++ ++#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) ++ ++static ssize_t dvb_video_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ unsigned long todo = count; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ return -EPERM; ++/* ++ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) ++ return -EPERM; ++*/ ++ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) ++ return -EWOULDBLOCK; ++ ++ while (todo >= TS_SIZE) { ++ if (!FREE_COND_TS) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) ++ break; ++ } ++ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); ++ todo -= TS_SIZE; ++ buf += TS_SIZE; ++ } ++ ++ if (count > todo) { ++ u32 fifoCtrl; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ ++ return count - todo; ++} ++ ++static unsigned int dvb_video_poll(struct file *file, poll_table *wait) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ unsigned int mask = 0; ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) ++ poll_wait(file, &sti7109->tsout.queue, wait); ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { ++ if (1/*sti7109->playing*/) { ++ if (FREE_COND_TS) ++ mask |= (POLLOUT | POLLWRNORM); ++ } else /* if not playing: may play if asked for */ ++ mask |= (POLLOUT | POLLWRNORM); ++ } ++ ++ return mask; ++} ++ ++static int do_dvb_video_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case VIDEO_SELECT_SOURCE: ++ { ++ video_stream_source_t stream_source; ++ ++ stream_source = (video_stream_source_t) parg; ++ if (stream_source == VIDEO_SOURCE_DEMUX) { ++ /* stop and reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ } ++ else { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ /* reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ /* start FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); ++ } ++ break; ++ } ++ case VIDEO_CLEAR_BUFFER: ++ { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ break; ++ } ++ case VIDEO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->video_pts; ++ break; ++ } ++ case VIDEO_GET_SIZE: ++ { ++ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_video_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_video_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); ++} ++ ++static struct file_operations dvb_video_fops = { ++ .owner = THIS_MODULE, ++ .write = dvb_video_write, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_video_ioctl, ++#else ++ .unlocked_ioctl = dvb_video_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++ .poll = dvb_video_poll, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_video_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ tasklet_kill(&sti7109->fifo_tasklet); ++ dvb_unregister_device(sti7109->video_dev); ++ return 0; ++} ++ ++static int saa716x_ff_video_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); ++ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->video_dev, ++ &dvbdev_video, ++ sti7109, ++ DVB_DEVICE_VIDEO); ++ ++ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, ++ (unsigned long)saa716x); ++ ++ return 0; ++} ++ ++static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ struct sti7109_dev *sti7109; ++ int err = 0; ++ u32 value; ++ unsigned long timeout; ++ u32 fw_version; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ err = saa716x_phi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ /* prepare the sti7109 device struct */ ++ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); ++ if (!sti7109) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); ++ goto fail3; ++ } ++ ++ sti7109->dev = saa716x; ++ ++ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); ++ if (!sti7109->iobuf) ++ goto fail4; ++ ++ sti7109_cmd_init(sti7109); ++ ++ sti7109->int_count_enable = int_count_enable; ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ ++ saa716x->priv = sti7109; ++ ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ ++ /* hold ST in reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); ++ ++ /* enable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); ++ msleep(100); ++ ++ err = saa716x_ff_fpga_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); ++ goto fail5; ++ } ++ ++ /* configure TS muxer */ ++ if (sti7109->fpga_version < 0x110) { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); ++ } else { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); ++ } ++ ++ /* enable interrupts from ST7109 -> PC */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); ++ ++ value = SAA716x_EPRD(MSI, MSI_CONFIG33); ++ value &= 0xFCFFFFFF; ++ value |= MSI_INT_POL_EDGE_FALL; ++ SAA716x_EPWR(MSI, MSI_CONFIG33, value); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); ++ ++ /* enable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); ++ msleep(50); ++ /* disable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); ++ ++ err = saa716x_ff_st7109_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); ++ goto fail5; ++ } ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable FGPI2 and FGPI3 for TS inputs */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail6; ++ } ++ ++ /* wait a maximum of 10 seconds for the STi7109 to boot */ ++ timeout = 10 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, ++ sti7109->boot_finished == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ goto fail6; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); ++ err = -1; ++ goto fail6; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); ++ ++ err = saa716x_ff_video_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); ++ goto fail7; ++ } ++ ++ err = saa716x_ff_audio_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); ++ goto fail8; ++ } ++ ++ err = saa716x_ff_osd_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); ++ goto fail9; ++ } ++ ++ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); ++ if (!err) { ++ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", ++ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, ++ fw_version & 0xFF); ++ } ++ ++ err = saa716x_ir_init(saa716x); ++ if (err) ++ goto fail9; ++ ++ return 0; ++ ++fail9: ++ saa716x_ff_osd_exit(saa716x); ++fail8: ++ saa716x_ff_audio_exit(saa716x); ++fail7: ++ saa716x_ff_video_exit(saa716x); ++fail6: ++ saa716x_dvb_exit(saa716x); ++fail5: ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++fail4: ++ kfree(sti7109); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_ff_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ saa716x_ir_exit(saa716x); ++ ++ saa716x_ff_osd_exit(saa716x); ++ ++ saa716x_ff_audio_exit(saa716x); ++ ++ saa716x_ff_video_exit(saa716x); ++ ++ saa716x_dvb_exit(saa716x); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++ ++ saa716x->priv = NULL; ++ kfree(sti7109); ++ ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ struct sti7109_dev *sti7109; ++ u32 msiStatusL; ++ u32 msiStatusH; ++ u32 phiISR; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ sti7109 = saa716x->priv; ++ if (unlikely(sti7109 == NULL)) { ++ printk("%s: sti7109=NULL", __func__); ++ return IRQ_NONE; ++ } ++ if (sti7109->int_count_enable) ++ sti7109->total_int_count++; ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); ++ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); ++ ++ if (msiStatusL) { ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[0]++; ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[1]++; ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ if (msiStatusH) { ++ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); ++ } ++ ++ if (msiStatusH & MSI_INT_I2CINT_0) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[0]++; ++ saa716x->i2c[0].i2c_op = 0; ++ wake_up(&saa716x->i2c[0].i2c_wq); ++ } ++ if (msiStatusH & MSI_INT_I2CINT_1) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[1]++; ++ saa716x->i2c[1].i2c_op = 0; ++ wake_up(&saa716x->i2c[1].i2c_wq); ++ } ++ ++ if (msiStatusH & MSI_INT_EXTINT_0) { ++ ++ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); ++ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); ++ ++ if (sti7109->int_count_enable) { ++ int i; ++ sti7109->ext_int_total_count++; ++ for (i = 0; i < 16; i++) ++ if (phiISR & (1 << i)) ++ sti7109->ext_int_source_count[i]++; ++ } ++ ++ if (phiISR & ISR_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); ++ sti7109->result_len = length; ++ sti7109->result_avail = 1; ++ wake_up(&sti7109->result_avail_wq); ++ ++ phiISR &= ~ISR_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ ++ sti7109->cmd_ready = 1; ++ wake_up(&sti7109->cmd_ready_wq); ++ phiISR &= ~ISR_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); ++ sti7109->osd_result_len = length; ++ sti7109->osd_result_avail = 1; ++ wake_up(&sti7109->osd_result_avail_wq); ++ ++ phiISR &= ~ISR_OSD_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ ++ sti7109->osd_cmd_ready = 1; ++ wake_up(&sti7109->osd_cmd_ready_wq); ++ phiISR &= ~ISR_OSD_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); ++ } ++ ++ if (phiISR & ISR_BLOCK_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ ++ sti7109->block_done = 1; ++ wake_up(&sti7109->block_done_wq); ++ phiISR &= ~ISR_BLOCK_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); ++ } ++ ++ if (phiISR & ISR_DATA_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ ++ sti7109->data_ready = 1; ++ wake_up(&sti7109->data_ready_wq); ++ phiISR &= ~ISR_DATA_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); ++ } ++ ++ if (phiISR & ISR_BOOT_FINISH_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ ++ sti7109->boot_finished = 1; ++ wake_up(&sti7109->boot_finish_wq); ++ phiISR &= ~ISR_BOOT_FINISH_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); ++ } ++ ++ if (phiISR & ISR_AUDIO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); ++ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_AUDIO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ ++ } ++ ++ if (phiISR & ISR_VIDEO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); ++ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_VIDEO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ ++ } ++ ++ if (phiISR & ISR_CURRENT_STC_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); ++ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_CURRENT_STC_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ ++ } ++ ++ if (phiISR & ISR_REMOTE_EVENT_MASK) { ++ u8 data[4]; ++ u32 remote_event; ++ ++ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ remote_event = (data[3] << 24) ++ | (data[2] << 16) ++ | (data[1] << 8) ++ | (data[0]); ++ memset(data, 0, sizeof(data)); ++ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ ++ phiISR &= ~ISR_REMOTE_EVENT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); ++ ++ if (remote_event == 0) { ++ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); ++ } else { ++ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); ++ saa716x_ir_handler(saa716x, remote_event); ++ } ++ } ++ ++ if (phiISR & ISR_DVO_FORMAT_MASK) { ++ u8 data[4]; ++ u32 format; ++ ++ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); ++ format = (data[0] << 24) ++ | (data[1] << 16) ++ | (data[2] << 8) ++ | (data[3]); ++ ++ phiISR &= ~ISR_DVO_FORMAT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); ++ } ++ ++ if (phiISR & ISR_LOG_MESSAGE_MASK) { ++ char message[SIZE_LOG_MESSAGE_DATA]; ++ ++ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, ++ SIZE_LOG_MESSAGE_DATA); ++ ++ phiISR &= ~ISR_LOG_MESSAGE_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", ++ SIZE_LOG_MESSAGE_DATA, message); ++ } ++ ++ if (phiISR & ISR_FIFO1_EMPTY_MASK) { ++ u32 fifoCtrl; ++ ++ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl &= ~0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ tasklet_schedule(&sti7109->fifo_tasklet); ++ phiISR &= ~ISR_FIFO1_EMPTY_MASK; ++ } ++ ++ if (phiISR) { ++ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); ++ } ++ } ++ ++ if (sti7109->int_count_enable) { ++ if (jiffies - sti7109->last_int_ticks >= HZ) { ++ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," ++ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", ++ sti7109->total_int_count, ++ sti7109->fgpi_int_count[0], ++ sti7109->fgpi_int_count[1], ++ sti7109->i2c_int_count[0], ++ sti7109->i2c_int_count[1], ++ sti7109->ext_int_total_count, ++ sti7109->ext_int_source_count[0], ++ sti7109->ext_int_source_count[1], ++ sti7109->ext_int_source_count[2], ++ sti7109->ext_int_source_count[3], ++ sti7109->ext_int_source_count[4], ++ sti7109->ext_int_source_count[5], ++ sti7109->ext_int_source_count[6], ++ sti7109->ext_int_source_count[7], ++ sti7109->ext_int_source_count[8], ++ sti7109->ext_int_source_count[9], ++ sti7109->ext_int_source_count[10], ++ sti7109->ext_int_source_count[11], ++ sti7109->ext_int_source_count[12], ++ sti7109->ext_int_source_count[13], ++ sti7109->ext_int_source_count[14], ++ sti7109->ext_int_source_count[15]); ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" ++#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" ++ ++static struct stv090x_config tt6400_stv090x_config = { ++ .device = STV0900, ++ .demod_mode = STV090x_DUAL, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 13500000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts1_clk = 135000000, ++ .ts2_clk = 135000000, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static struct stv6110x_config tt6400_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 27000000, ++ .clk_div = 2, ++}; ++ ++static struct isl6423_config tt6400_isl6423_config[2] = { ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x09, ++ }, ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ } ++}; ++ ++ ++static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ if (count == 0 || count == 1) { ++ adapter->fe = dvb_attach(stv090x_attach, ++ &tt6400_stv090x_config, ++ i2c_adapter, ++ STV090x_DEMODULATOR_0 + count); ++ ++ if (adapter->fe) { ++ struct stv6110x_devctl *ctl; ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &tt6400_stv6110x_config, ++ i2c_adapter); ++ ++ tt6400_stv090x_config.tuner_init = ctl->tuner_init; ++ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ if (count == 1) { ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ /* The second tuner drives the STV0900 so ++ call it only for adapter 1 */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } ++ ++ dvb_attach(isl6423_attach, ++ adapter->fe, ++ i2c_adapter, ++ &tt6400_isl6423_config[count]); ++ ++ } ++ } ++ return 0; ++} ++ ++static struct saa716x_config saa716x_s26400_config = { ++ .model_name = SAA716x_MODEL_S2_6400_DUAL, ++ .dev_type = SAA716x_DEV_S2_6400_DUAL, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_s26400_frontend_attach, ++ .irq_handler = saa716x_ff_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ },{ ++ /* Adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++static struct pci_device_id saa716x_ff_pci_table[] = { ++ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); ++ ++static struct pci_driver saa716x_ff_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_ff_pci_table, ++ .probe = saa716x_ff_pci_probe, ++ .remove = saa716x_ff_pci_remove, ++}; ++ ++static int saa716x_ff_init(void) ++{ ++ return pci_register_driver(&saa716x_ff_pci_driver); ++} ++ ++static void saa716x_ff_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_ff_pci_driver); ++} ++ ++module_init(saa716x_ff_init); ++module_exit(saa716x_ff_exit); ++ ++MODULE_DESCRIPTION("SAA716x FF driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_fgpi.c b/drivers/media/common/saa716x/saa716x_fgpi.c +new file mode 100644 +index 0000000..8bdb13d +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi.c +@@ -0,0 +1,389 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static const u32 mmu_pta_base[] = { ++ MMU_PTA_BASE0, ++ MMU_PTA_BASE1, ++ MMU_PTA_BASE2, ++ MMU_PTA_BASE3, ++ MMU_PTA_BASE4, ++ MMU_PTA_BASE5, ++ MMU_PTA_BASE6, ++ MMU_PTA_BASE7, ++ MMU_PTA_BASE8, ++ MMU_PTA_BASE9, ++ MMU_PTA_BASE10, ++ MMU_PTA_BASE11, ++ MMU_PTA_BASE12, ++ MMU_PTA_BASE13, ++ MMU_PTA_BASE14, ++ MMU_PTA_BASE15, ++}; ++ ++static const u32 mmu_dma_cfg[] = { ++ MMU_DMA_CONFIG0, ++ MMU_DMA_CONFIG1, ++ MMU_DMA_CONFIG2, ++ MMU_DMA_CONFIG3, ++ MMU_DMA_CONFIG4, ++ MMU_DMA_CONFIG5, ++ MMU_DMA_CONFIG6, ++ MMU_DMA_CONFIG7, ++ MMU_DMA_CONFIG8, ++ MMU_DMA_CONFIG9, ++ MMU_DMA_CONFIG10, ++ MMU_DMA_CONFIG11, ++ MMU_DMA_CONFIG12, ++ MMU_DMA_CONFIG13, ++ MMU_DMA_CONFIG14, ++ MMU_DMA_CONFIG15, ++}; ++ ++static const u32 fgpi_ch[] = { ++ FGPI0, ++ FGPI1, ++ FGPI2, ++ FGPI3 ++}; ++ ++static const u32 bamdma_bufmode[] = { ++ BAM_FGPI0_DMA_BUF_MODE, ++ BAM_FGPI1_DMA_BUF_MODE, ++ BAM_FGPI2_DMA_BUF_MODE, ++ BAM_FGPI3_DMA_BUF_MODE ++}; ++ ++static const u32 msi_int_tagack[] = { ++ MSI_INT_TAGACK_FGPI_0, ++ MSI_INT_TAGACK_FGPI_1, ++ MSI_INT_TAGACK_FGPI_2, ++ MSI_INT_TAGACK_FGPI_3 ++}; ++ ++static const u32 msi_int_ovrflw[] = { ++ MSI_INT_OVRFLW_FGPI_0, ++ MSI_INT_OVRFLW_FGPI_1, ++ MSI_INT_OVRFLW_FGPI_2, ++ MSI_INT_OVRFLW_FGPI_3 ++}; ++ ++static const u32 msi_int_avint[] = { ++ MSI_INT_AVINT_FGPI_0, ++ MSI_INT_AVINT_FGPI_1, ++ MSI_INT_AVINT_FGPI_2, ++ MSI_INT_AVINT_FGPI_3 ++}; ++ ++void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port; ++ ++ fgpi_port = fgpi_ch[channel]; ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ ++ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); ++ ++int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) ++{ ++ u32 fgpi_base; ++ u32 buf_mode_reg; ++ u32 buf_mode; ++ ++ switch (fgpi_index) { ++ case 0: /* FGPI_0 */ ++ fgpi_base = FGPI0; ++ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; ++ break; ++ ++ case 1: /* FGPI_1 */ ++ fgpi_base = FGPI1; ++ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; ++ break; ++ ++ case 2: /* FGPI_2 */ ++ fgpi_base = FGPI2; ++ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; ++ break; ++ ++ case 3: /* FGPI_3 */ ++ fgpi_base = FGPI3; ++ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: unexpected fgpi %u\n", ++ __func__, fgpi_index); ++ return -1; ++ } ++ ++ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); ++ if (saa716x->revision < 2) { ++ /* workaround for revision 1: restore buffer numbers on BAM */ ++ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); ++ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); ++ } ++ return (buf_mode >> 3) & 0x7; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); ++ ++static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 config, i; ++ ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); ++ ++ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ ++ ++ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ ++ ++ return 0; ++} ++ ++int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, ++ struct fgpi_stream_params *stream_params, ++ int port) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port, buf_mode, val, mid; ++ u32 D1_XY_END, offst_1, offst_2; ++ int i = 0; ++ ++ fgpi_port = fgpi_ch[port]; ++ buf_mode = bamdma_bufmode[port]; ++ ++ /* Reset FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* Reset DMA channel */ ++ SAA716x_EPWR(BAM, buf_mode, 0x00000040); ++ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); ++ ++ ++ /* monitor BAM reset */ ++ val = SAA716x_EPRD(BAM, buf_mode); ++ while (val && (i < 100)) { ++ msleep(30); ++ val = SAA716x_EPRD(BAM, buf_mode); ++ i++; ++ } ++ ++ if (val) { ++ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); ++ return -EIO; ++ } ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); ++ ++ /* initialize all available address offsets */ ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); ++ ++ /* get module ID */ ++ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); ++ if (mid != 0x14b0100) ++ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); ++ ++ /* Initialize FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); ++ ++ offst_1 = 0; ++ offst_2 = 0; ++ switch (stream_params->stream_type) { ++ case FGPI_TRANSPORT_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_PROGRAM_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_VIDEO_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); ++ ++ if ((stream_params->stream_flags & FGPI_INTERLACED) && ++ (stream_params->stream_flags & FGPI_ODD_FIELD) && ++ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { ++ ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ ++ ++ D1_XY_END = (stream_params->samples << 16); ++ D1_XY_END |= (stream_params->lines / 2) + 2; ++ ++ if (stream_params->stream_flags & FGPI_PAL) ++ offst_1 = 768 * 2; ++ else ++ offst_2 = 768 * 2; ++ ++ } else { ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ ++ ++ D1_XY_END = stream_params->samples << 16; ++ D1_XY_END |= stream_params->lines + 2; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); ++ break; ++ ++ default: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ break; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params) ++{ ++ u32 fgpi_port; ++ u32 config; ++ u32 val; ++ u32 i; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); ++ msleep(10); ++ ++ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { ++ return -EIO; ++ } ++ ++ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ ++ ++ val = SAA716x_EPRD(MMU, config); ++ SAA716x_EPWR(MMU, config, val & ~0x40); ++ SAA716x_EPWR(MMU, config, val | 0x40); ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); ++ ++ val = SAA716x_EPRD(MMU, config); ++ i = 0; ++ while (i < 500) { ++ if (val & 0x80) ++ break; ++ msleep(10); ++ val = SAA716x_EPRD(MMU, config); ++ i++; ++ } ++ ++ if (!(val & 0x80)) { ++ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); ++ return -EIO; ++ } ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val |= 0x3000; ++ ++ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) ++{ ++ u32 fgpi_port; ++ u32 val; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val &= ~0x3000; ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)) ++{ ++ int i; ++ int ret; ++ ++ saa716x->fgpi[port].dma_channel = port + 6; ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ /* TODO: what is a good size for TS DMA buffer? */ ++ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ saa716x->fgpi[port].saa716x = saa716x; ++ tasklet_init(&saa716x->fgpi[port].tasklet, worker, ++ (unsigned long)&saa716x->fgpi[port]); ++ saa716x->fgpi[port].read_index = 0; ++ ++ return 0; ++} ++ ++int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) ++{ ++ int i; ++ ++ tasklet_kill(&saa716x->fgpi[port].tasklet); ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); ++ } ++ ++ return 0; ++} +diff --git a/drivers/media/common/saa716x/saa716x_fgpi.h b/drivers/media/common/saa716x/saa716x_fgpi.h +new file mode 100644 +index 0000000..225aff0 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi.h +@@ -0,0 +1,112 @@ ++#ifndef __SAA716x_FGPI_H ++#define __SAA716x_FGPI_H ++ ++#include ++ ++#define FGPI_BUFFERS 8 ++#define PTA_LSB(__mem) ((u32 ) (__mem)) ++#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) ++ ++#define BAM_DMA_BUF_MODE_BASE 0x0d8 ++#define BAM_DMA_BUF_MODE_OFFSET 0x24 ++ ++#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc ++#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 ++ ++#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 ++#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 ++#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 ++#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c ++#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 ++#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 ++#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 ++#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c ++ ++struct saa716x_dmabuf; ++ ++/* ++ * Port supported streams ++ * ++ * FGPI_AUDIO_STREAM ++ * FGPI_VIDEO_STREAM ++ * FGPI_VBI_STREAM ++ * FGPI_TRANSPORT_STREAM ++ * FGPI_PROGRAM_STREAM ++ */ ++enum fgpi_stream_type { ++ FGPI_AUDIO_STREAM = 0x01, ++ FGPI_VIDEO_STREAM = 0x02, ++ FGPI_VBI_STREAM = 0x04, ++ FGPI_TRANSPORT_STREAM = 0x08, ++ FGPI_PROGRAM_STREAM = 0x10 ++}; ++ ++/* ++ * Stream port flags ++ * ++ * FGPI_ODD_FIELD ++ * FGPI_EVEN_FIELD ++ * FGPI_HD_0 ++ * FGPI_HD_1 ++ * FGPI_PAL ++ * FGPI_NTSC ++ */ ++enum fgpi_stream_flags { ++ FGPI_ODD_FIELD = 0x0001, ++ FGPI_EVEN_FIELD = 0x0002, ++ FGPI_INTERLACED = 0x0004, ++ FGPI_HD0 = 0x0010, ++ FGPI_HD1 = 0x0020, ++ FGPI_PAL = 0x0040, ++ FGPI_NTSC = 0x0080, ++ FGPI_NO_SCALER = 0x0100, ++}; ++ ++/* ++ * Stream port parameters ++ * bits: Bits per sample ++ * samples: samples perline ++ * lines: number of lines ++ * pitch: stream pitch in bytes ++ * offset: offset to first valid line ++ */ ++struct fgpi_stream_params { ++ u32 bits; ++ u32 samples; ++ u32 lines; ++ ++ s32 pitch; ++ ++ u32 offset; ++ u32 page_tables; ++ ++ enum fgpi_stream_flags stream_flags; ++ enum fgpi_stream_type stream_type; ++}; ++ ++struct saa716x_dmabuf; ++ ++struct saa716x_fgpi_stream_port { ++ u8 dma_channel; ++ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; ++ struct saa716x_dev *saa716x; ++ struct tasklet_struct tasklet; ++ u8 read_index; ++}; ++ ++extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); ++extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, ++ u32 fgpi_index); ++extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params); ++extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); ++ ++extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)); ++extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); ++ ++#endif /* __SAA716x_FGPI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_fgpi_reg.h b/drivers/media/common/saa716x/saa716x_fgpi_reg.h +new file mode 100644 +index 0000000..1193016 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi_reg.h +@@ -0,0 +1,74 @@ ++#ifndef __SAA716x_FGPI_REG_H ++#define __SAA716x_FGPI_REG_H ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++#endif /* __SAA716x_FGPI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_gpio.c b/drivers/media/common/saa716x/saa716x_gpio.c +new file mode 100644 +index 0000000..62b6112 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio.c +@@ -0,0 +1,140 @@ ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++ ++#include "saa716x_gpio.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_gpio_init(struct saa716x_dev *saa716x) ++{ ++ spin_lock_init(&saa716x->gpio_lock); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_init); ++ ++int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) ++{ ++ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ ++ return 0; ++} ++ ++int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ reg &= ~mask; ++ reg |= (config & mask); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) ++{ ++ return SAA716x_EPRD(GPIO, GPIO_RD); ++} ++ ++void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) ++{ ++ SAA716x_EPWR(GPIO, GPIO_WR, data); ++} ++ ++void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_OEN); ++ reg &= mask; ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_OEN, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_WR); ++ reg &= ~bits; ++ /* TODO ! add maskable config bits in here */ ++ /* reg |= (config->mask & bits) */ ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_WR, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); ++ ++void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value |= 1 << gpio; ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); ++ ++void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ if (mode) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); ++ ++void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) ++{ ++ uint32_t value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ value = SAA716x_EPRD(GPIO, GPIO_WR); ++ if (set) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR, value); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_write); ++ ++int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_RD); ++ if (value & (1 << gpio)) ++ return 1; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_read); +diff --git a/drivers/media/common/saa716x/saa716x_gpio.h b/drivers/media/common/saa716x/saa716x_gpio.h +new file mode 100644 +index 0000000..a82580b +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio.h +@@ -0,0 +1,26 @@ ++#ifndef __SAA716x_GPIO_H ++#define __SAA716x_GPIO_H ++ ++#define BOOT_MODE GPIO_31 | GPIO_30 ++#define AV_UNIT_B GPIO_25 ++#define AV_UNIT_A GPIO_24 ++#define AV_INTR_B GPIO_01 ++#define AV_INTR_A GPIO_00 ++ ++struct saa716x_dev; ++ ++extern void saa716x_gpio_init(struct saa716x_dev *saa716x); ++ ++extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); ++extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); ++extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); ++ ++extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); ++ ++extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); ++extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); ++extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); ++ ++#endif /* __SAA716x_GPIO_H */ +diff --git a/drivers/media/common/saa716x/saa716x_gpio_reg.h b/drivers/media/common/saa716x/saa716x_gpio_reg.h +new file mode 100644 +index 0000000..f36184a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio_reg.h +@@ -0,0 +1,47 @@ ++#ifndef __SAA716x_GPIO_REG_H ++#define __SAA716x_GPIO_REG_H ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++#endif /* __SAA716x_GPIO_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_greg.c b/drivers/media/common/saa716x/saa716x_greg.c +new file mode 100644 +index 0000000..d93a3b8 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg.c +@@ -0,0 +1,42 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_greg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static u32 g_save[12]; ++ ++void saa716x_greg_save(struct saa716x_dev *saa716x) ++{ ++ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); ++ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); ++ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); ++ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); ++ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); ++ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); ++ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); ++ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); ++ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); ++ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); ++ ++ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); ++} ++ ++void saa716x_greg_restore(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); ++ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); ++ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); ++ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); ++ ++ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); ++} +diff --git a/drivers/media/common/saa716x/saa716x_greg.h b/drivers/media/common/saa716x/saa716x_greg.h +new file mode 100644 +index 0000000..487595e +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_GREG_H ++#define __SAA716x_GREG_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_greg_save(struct saa716x_dev *saa716x); ++extern void saa716x_greg_restore(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_GREG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_greg_reg.h b/drivers/media/common/saa716x/saa716x_greg_reg.h +new file mode 100644 +index 0000000..052e8cd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg_reg.h +@@ -0,0 +1,91 @@ ++#ifndef __SAA716x_GREG_REG_H ++#define __SAA716x_GREG_REG_H ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_GREG_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_hybrid.c b/drivers/media/common/saa716x/saa716x_hybrid.c +new file mode 100644 +index 0000000..27e5e71 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_hybrid.c +@@ -0,0 +1,726 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_hybrid.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "zl10353.h" ++#include "mb86a16.h" ++#include "tda1004x.h" ++#include "tda827x.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Hybrid" ++ ++static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable decoders on 7162 */ ++ if (pdev->device == SAA7162) { ++ saa716x_gpio_set_output(saa716x, 24); ++ saa716x_gpio_set_output(saa716x, 25); ++ ++ saa716x_gpio_write(saa716x, 24, 0); ++ saa716x_gpio_write(saa716x, 25, 0); ++ ++ msleep(10); ++ ++ saa716x_gpio_write(saa716x, 24, 1); ++ saa716x_gpio_write(saa716x, 25, 1); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); ++ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++/* ++ * Twinhan/Azurewave VP-6090 ++ * DVB-S Frontend: 2x MB86A16 ++ * DVB-T Frontend: 2x TDA10046 + TDA8275 ++ */ ++#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" ++#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" ++ ++static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_vp6090_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_4M, ++ .agc_config = TDA10046_AGC_DEFAULT, ++ .if_freq = TDA10046_FREQ_3617, ++ .request_firmware = tda1004x_vp6090_request_firmware, ++}; ++ ++static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp6090_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp6090_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[count]; ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ saa716x_gpio_set_output(saa716x, 11); ++ saa716x_gpio_set_output(saa716x, 10); ++ saa716x_gpio_write(saa716x, 11, 1); ++ saa716x_gpio_write(saa716x, 10, 1); ++ msleep(100); ++#if 0 ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp6090_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++#endif ++ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_vp6090_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6090, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6090, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6090_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++/* ++ * NXP Reference design (Atlantis) ++ * 2x DVB-T Frontend: 2x TDA10046 ++ * Analog Decoder: 2x Internal ++ */ ++#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" ++#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" ++ ++static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_atlantis_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_atlantis_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_atlantis_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c; ++ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ ++ struct i2c_msg msg = { ++ .addr = 0x42 >> 1, ++ .flags = 0, ++ .buf = i2c_buf, ++ .len = sizeof(i2c_buf) ++ }; ++ ++ if (count < saa716x->config->adapters) { ++ u32 reset_gpio; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ if (count == 0) { ++ reset_gpio = 14; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ } else { ++ reset_gpio = 15; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ } ++ ++ /* activate the silent I2C bus */ ++ i2c_transfer(&i2c->i2c_adapter, &msg, 1); ++ ++ saa716x_gpio_set_output(saa716x, reset_gpio); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) ++ goto exit; ++ ++ dprintk(SAA716x_ERROR, 1, ++ "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_atlantis_config.demod_address); ++ ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_atlantis_config.tuner_address, ++ &i2c->i2c_adapter, &tda827x_atlantis_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_atlantis_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_atlantis_config = { ++ .model_name = SAA716x_MODEL_NXP_ATLANTIS, ++ .dev_type = SAA716x_DEV_NXP_ATLANTIS, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_atlantis_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* Adapter 1 */ ++ .ts_port = 0, /* using FGPI 0 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++/* ++ * NXP Reference design (NEMO) ++ * DVB-T Frontend: 1x TDA10046 + TDA8275 ++ * Analog Decoder: External SAA7136 ++ */ ++#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" ++#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" ++ ++static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_nemo_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_nemo_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_nemo_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ ++ ++ if (count == 0) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ /* GPIO 26 controls a +15dB gain */ ++ saa716x_gpio_set_output(saa716x, 26); ++ saa716x_gpio_write(saa716x, 26, 0); ++ ++ saa716x_gpio_set_output(saa716x, 14); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_nemo_config, ++ &demod_i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_nemo_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_nemo_config.tuner_address, ++ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_nemo_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_nemo_config = { ++ .model_name = SAA716x_MODEL_NXP_NEMO, ++ .dev_type = SAA716x_DEV_NXP_NEMO, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_nemo_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" ++#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" ++ ++#if 0 ++static struct zl10353_config saa716x_averhc82_zl10353_config = { ++ .demod_address = 0x1f, ++ .adc_clock = 450560, ++ .if2 = 361667, ++ .no_tuner = 1, ++ .parallel_ts = 1, ++}; ++#endif ++ ++static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); ++ ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_averhc82_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, ++ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averhc82_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" ++#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" ++ ++static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_averh788_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_H788, ++ .dev_type = SAA716x_DEV_AVERMEDIA_H788, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averh88_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++static struct pci_device_id saa716x_hybrid_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), ++ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); ++ ++static struct pci_driver saa716x_hybrid_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_hybrid_pci_table, ++ .probe = saa716x_hybrid_pci_probe, ++ .remove = saa716x_hybrid_pci_remove, ++}; ++ ++static int saa716x_hybrid_init(void) ++{ ++ return pci_register_driver(&saa716x_hybrid_pci_driver); ++} ++ ++static void saa716x_hybrid_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_hybrid_pci_driver); ++} ++ ++module_init(saa716x_hybrid_init); ++module_exit(saa716x_hybrid_exit); ++ ++MODULE_DESCRIPTION("SAA716x Hybrid driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_hybrid.h b/drivers/media/common/saa716x/saa716x_hybrid.h +new file mode 100644 +index 0000000..df34a59 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_hybrid.h +@@ -0,0 +1,13 @@ ++#ifndef __SAA716x_HYBRID_H ++#define __SAA716x_HYBRID_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define AVERMEDIA 0x1461 ++#define KWORLD 0x17DE ++ ++#define TWINHAN_VP_6090 0x0027 ++#define AVERMEDIA_HC82 0x2355 ++#define AVERMEDIA_H788 0x1455 ++#define KWORLD_DVB_T_PE310 0x7521 ++ ++#endif /* __SAA716x_HYBRID_H */ +diff --git a/drivers/media/common/saa716x/saa716x_i2c.c b/drivers/media/common/saa716x/saa716x_i2c.c +new file mode 100644 +index 0000000..91a091d +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c.c +@@ -0,0 +1,734 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_i2c_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_cgu_reg.h" ++ ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ ++ I2C_ACK_INTER_MTNA | \ ++ I2C_FAILURE_INTER_MAF) ++ ++#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ ++ I2C_TRANSMIT_PROG) ++ ++#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ ++ I2C_RECEIVE_CLEAR) ++ ++static const char* state[] = { ++ "Idle", ++ "DoneStop", ++ "Busy", ++ "TOscl", ++ "TOarb", ++ "DoneWrite", ++ "DoneRead", ++ "DoneWriteTO", ++ "DoneReadTO", ++ "NoDevice", ++ "NoACK", ++ "BUSErr", ++ "ArbLost", ++ "SEQErr", ++ "STErr" ++}; ++ ++int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) ++{ ++ u32 stat, mask; ++ u32 *I2C_DEV; ++ ++ BUG_ON(saa716x == NULL); ++ I2C_DEV = saa716x->I2C_DEV; ++ ++ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); ++ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); ++ saa716x->i2c[bus].i2c_stat = stat; ++ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", ++ bus, state[stat], stat, mask); ++ ++ if (!(stat & mask)) ++ return -1; ++ ++ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); ++ ++ if (stat & I2C_INTERRUPT_STFNF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTFNF) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_INTERRUPT_RFDA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPTE_RFF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_INTERRUPT_STDR) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MASTER_INTERRUPT_MTDR) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_ERROR_IBE) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MODE_CHANGE_INTER_MSMC) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_ACK_INTER_MTNA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_FAILURE_INTER_MAF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++ ++static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), ++ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); ++ ++ return IRQ_HANDLED; ++} ++ ++static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); ++ ++ return; ++} ++ ++static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ struct i2c_adapter *adapter = &i2c->i2c_adapter; ++ ++ int i, err = 0; ++ u32 reg; ++ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", ++ I2C_DEV, adapter->name); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Flush queue */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ /* Reset I2C Core and generate a delay */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); ++ ++ for (i = 0; i < 100; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); ++ if (reg == 0xc0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", ++ I2C_DEV, adapter->name); ++ break; ++ } ++ msleep(1); ++ ++ if (i == 99) ++ err = -EIO; ++ } ++ ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", ++ I2C_DEV, adapter->name); ++ ++ saa716x_term_xfer(i2c, I2C_DEV); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* I2C Rate Setup */ ++ switch (i2c->i2c_rate) { ++ case SAA716x_I2C_RATE_400: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); ++ break; ++ ++ case SAA716x_I2C_RATE_100: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); ++ break; ++ ++ default: ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", ++ adapter->name, ++ i2c->i2c_rate); ++ ++ break; ++ } ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Enabled interrupts: ++ * Master Transaction Done, ++ * Master Transaction Data Request ++ * (0x81) ++ */ ++ msleep(5); ++ ++ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, ++ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); ++ ++ /* Check interrupt enable status */ ++ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); ++ if (reg != 0x81) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%d) %s Interrupt enable failed, Exiting !", ++ i, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++ } ++ ++ /* Check status */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%02x) %s has bad state, Exiting !", ++ I2C_DEV, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++#if 0 ++ saa716x_add_irqvector(saa716x, ++ i2c_vec[i].vector, ++ i2c_vec[i].edge, ++ i2c_vec[i].handler, ++ SAA716x_I2C_ADAPTER(i)); ++#endif ++ reg = SAA716x_EPRD(CGU, CGU_SCR_3); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", ++ I2C_DEV, ++ (reg >> 1) & 0x01, ++ reg & 0x01); ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ return 0; ++ } ++ ++ /* Check FIFO status before TX */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ i2c->stat_tx_prior = reg; ++ if (reg & SAA716x_I2C_TXBUSY) { ++ for (i = 0; i < 100; i++) { ++ /* TODO! check for hotplug devices */ ++ msleep(10); ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ ++ if (reg & SAA716x_I2C_TXBUSY) { ++ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); ++ ++ err = saa716x_i2c_hwinit(i2c, I2C_DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto exit; ++ } ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ ++ /* Check for data write */ ++ for (i = 0; i < 1000; i++) { ++ /* TODO! check for hotplug devices */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (reg & I2C_TRANSMIT_CLEAR) { ++ break; ++ } ++ } ++ i2c->stat_tx_done = reg; ++ ++ if (!(reg & I2C_TRANSMIT_CLEAR)) { ++ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); ++ err = -EIO; ++ goto exit; ++ } ++ ++ return err; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); ++ return err; ++} ++ ++static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ /* Check FIFO status before RX */ ++ for (i = 0; i < 1000; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & SAA716x_I2C_RXBUSY)) { ++ break; ++ } ++ } ++ if (reg & SAA716x_I2C_RXBUSY) { ++ dprintk(SAA716x_INFO, 1, "FIFO empty"); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Read from FIFO */ ++ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); ++ return err; ++} ++ ++static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return; ++ ++ i2c->i2c_op = 1; ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ unsigned long timeout; ++ int err = 0; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return 0; ++ ++ timeout = HZ/100 + 1; /* 10ms */ ++ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); ++ if (timeout == -ERESTARTSYS || i2c->i2c_op) { ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ err = -ERESTARTSYS; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); ++ err = -EIO; ++ } ++ } ++ return err; ++} ++ ++static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1); ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now write the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = buf[i]; ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1) | 1; ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now read the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = 0x00; /* dummy write for reading */ ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ for (i = 0; i < bytes; i++) { ++ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data receive failed"); ++ goto exit; ++ } ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); ++ buf[i] = data; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) ++{ ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); ++ int i, j, err = 0; ++ int t; ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); ++ mutex_lock(&i2c->i2c_lock); ++ ++ for (t = 0; t < 3; t++) { ++ for (i = 0; i < num; i++) { ++ if (msgs[i].flags & I2C_M_RD) ++ err = saa716x_i2c_read_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ else ++ err = saa716x_i2c_write_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ if (err < 0) { ++ err = -EIO; ++ goto retry; ++ } ++ } ++ break; ++retry: ++ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); ++ for (i = 0; i < num; i++) { ++ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", ++ i, msgs[i].addr, msgs[i].len, msgs[i].flags); ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ for (j = 0; j < msgs[i].len; j++) { ++ dprintk(SAA716x_INFO, 1, " 0x%02x", ++ j, msgs[i].buf[j]); ++ } ++ } ++ } ++ err = saa716x_i2c_hwinit(i2c, DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto bail_out; ++ } ++ } ++ ++ mutex_unlock(&i2c->i2c_lock); ++ return num; ++ ++bail_out: ++ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); ++ mutex_unlock(&i2c->i2c_lock); ++ return err; ++} ++ ++static u32 saa716x_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm saa716x_algo = { ++ .master_xfer = saa716x_i2c_xfer, ++ .functionality = saa716x_i2c_func, ++}; ++ ++struct saa716x_i2cvec { ++ u32 vector; ++ enum saa716x_edge edge; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++static const struct saa716x_i2cvec i2c_vec[] = { ++ { ++ .vector = I2CINT_0, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ }, { ++ .vector = I2CINT_1, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ } ++}; ++ ++int saa716x_i2c_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ mutex_init(&i2c->i2c_lock); ++ ++ init_waitqueue_head(&i2c->i2c_wq); ++ i2c->i2c_op = 0; ++ ++ i2c->i2c_dev = i; ++ i2c->i2c_rate = saa716x->config->i2c_rate; ++ i2c->i2c_mode = saa716x->config->i2c_mode; ++ adapter = &i2c->i2c_adapter; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) ++ i2c->block_size = 8; ++ else ++ i2c->block_size = 1; ++ ++ if (adapter != NULL) { ++ ++ i2c_set_adapdata(adapter, i2c); ++ ++ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); ++ ++ adapter->owner = THIS_MODULE; ++ adapter->algo = &saa716x_algo; ++ adapter->algo_data = NULL; ++ adapter->timeout = 500; /* FIXME ! */ ++ adapter->retries = 3; /* FIXME ! */ ++ adapter->dev.parent = &pdev->dev; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", ++ i, ++ adapter->name); ++ ++ err = i2c_add_adapter(adapter); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); ++ goto exit; ++ } ++ ++ i2c->saa716x = saa716x; ++ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); ++ } ++ i2c++; ++ } ++ ++ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", ++ saa716x->pdev->device); ++ ++ return 0; ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_init); ++ ++int saa716x_i2c_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ adapter = &i2c->i2c_adapter; ++#if 0 ++ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); ++#endif ++ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); ++ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); ++ ++ i2c_del_adapter(adapter); ++ i2c++; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); ++ ++ return 0; ++ ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_exit); +diff --git a/drivers/media/common/saa716x/saa716x_i2c.h b/drivers/media/common/saa716x/saa716x_i2c.h +new file mode 100644 +index 0000000..da767ac +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c.h +@@ -0,0 +1,52 @@ ++#ifndef __SAA716x_I2C_H ++#define __SAA716x_I2C_H ++ ++#define SAA716x_I2C_ADAPTERS 2 ++ ++#define SAA716x_I2C_ADAPTER(__dev) (( \ ++ (__dev == 1) ? \ ++ "SAA716x I2C Core 1" : \ ++ "SAA716x I2C Core 0")) ++ ++#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) ++ ++#define SAA716x_I2C_BUS_A 0x01 ++#define SAA716x_I2C_BUS_B 0x00 ++ ++struct saa716x_dev; ++ ++enum saa716x_i2c_rate { ++ SAA716x_I2C_RATE_400 = 1, ++ SAA716x_I2C_RATE_100, ++}; ++ ++enum saa716x_i2c_mode { ++ SAA716x_I2C_MODE_POLLING = 0, ++ SAA716x_I2C_MODE_IRQ, ++ SAA716x_I2C_MODE_IRQ_BUFFERED ++}; ++ ++struct saa716x_i2c { ++ struct i2c_adapter i2c_adapter; ++ struct mutex i2c_lock; ++ struct saa716x_dev *saa716x; ++ u8 i2c_dev; ++ ++ enum saa716x_i2c_rate i2c_rate; /* run time */ ++ enum saa716x_i2c_mode i2c_mode; ++ u32 block_size; /* block size for buffered ++ mode, 1 otherwise */ ++ u32 i2c_stat; ++ ++ u32 stat_tx_prior; ++ u32 stat_tx_done; ++ wait_queue_head_t i2c_wq; ++ int i2c_op; ++}; ++ ++extern int saa716x_i2c_init(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); ++extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); ++ ++#endif /* __SAA716x_I2C_H */ +diff --git a/drivers/media/common/saa716x/saa716x_i2c_reg.h b/drivers/media/common/saa716x/saa716x_i2c_reg.h +new file mode 100644 +index 0000000..8fa992c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c_reg.h +@@ -0,0 +1,145 @@ ++#ifndef __SAA716x_I2C_REG_H ++#define __SAA716x_I2C_REG_H ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_I2C_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_mod.h b/drivers/media/common/saa716x/saa716x_mod.h +new file mode 100644 +index 0000000..273efdd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_mod.h +@@ -0,0 +1,50 @@ ++#ifndef __SAA716x_MOD_H ++#define __SAA716x_MOD_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++#define BAM 0x00008000 ++#define MMU 0x00009000 ++#define MSI 0x0000a000 ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++#define SPI 0x0000d000 ++#define GPIO 0x0000e000 ++#define PHI_0 0x0000f000 ++#define GREG 0x00012000 ++#define CGU 0x00013000 ++#define DCS 0x00014000 ++#define PHI_1 0x00020000 ++ ++#endif /* __SAA716x_MOD_H */ +diff --git a/drivers/media/common/saa716x/saa716x_msi.c b/drivers/media/common/saa716x/saa716x_msi.c +new file mode 100644 +index 0000000..b0f05a2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi.c +@@ -0,0 +1,479 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_msi_reg.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++ ++#include "saa716x_priv.h" ++ ++#define SAA716x_MSI_VECTORS 50 ++ ++static const char *vector_name[] = { ++ "TAGACK_VI0_0", ++ "TAGACK_VI0_1", ++ "TAGACK_VI0_2", ++ "TAGACK_VI1_0", ++ "TAGACK_VI1_1", ++ "TAGACK_VI1_2", ++ "TAGACK_FGPI_0", ++ "TAGACK_FGPI_1", ++ "TAGACK_FGPI_2", ++ "TAGACK_FGPI_3", ++ "TAGACK_AI_0", ++ "TAGACK_AI_1", ++ "OVRFLW_VI0_0", ++ "OVRFLW_VI0_1", ++ "OVRFLW_VI0_2", ++ "OVRFLW_VI1_0", ++ "OVRFLW_VI1_1", ++ "OVRFLW_VI1_2", ++ "OVRFLW_FGPI_O", ++ "OVRFLW_FGPI_1", ++ "OVRFLW_FGPI_2", ++ "OVRFLW_FGPI_3", ++ "OVRFLW_AI_0", ++ "OVRFLW_AI_1", ++ "AVINT_VI0", ++ "AVINT_VI1", ++ "AVINT_FGPI_0", ++ "AVINT_FGPI_1", ++ "AVINT_FGPI_2", ++ "AVINT_FGPI_3", ++ "AVINT_AI_0", ++ "AVINT_AI_1", ++ "UNMAPD_TC_INT", ++ "EXTINT_0", ++ "EXTINT_1", ++ "EXTINT_2", ++ "EXTINT_3", ++ "EXTINT_4", ++ "EXTINT_5", ++ "EXTINT_6", ++ "EXTINT_7", ++ "EXTINT_8", ++ "EXTINT_9", ++ "EXTINT_10", ++ "EXTINT_11", ++ "EXTINT_12", ++ "EXTINT_13", ++ "EXTINT_14", ++ "EXTINT_15", ++ "I2CINT_0", ++ "I2CINT_1" ++}; ++ ++static u32 MSI_CONFIG_REG[51] = { ++ MSI_CONFIG0, ++ MSI_CONFIG1, ++ MSI_CONFIG2, ++ MSI_CONFIG3, ++ MSI_CONFIG4, ++ MSI_CONFIG5, ++ MSI_CONFIG6, ++ MSI_CONFIG7, ++ MSI_CONFIG8, ++ MSI_CONFIG9, ++ MSI_CONFIG10, ++ MSI_CONFIG11, ++ MSI_CONFIG12, ++ MSI_CONFIG13, ++ MSI_CONFIG14, ++ MSI_CONFIG15, ++ MSI_CONFIG16, ++ MSI_CONFIG17, ++ MSI_CONFIG18, ++ MSI_CONFIG19, ++ MSI_CONFIG20, ++ MSI_CONFIG21, ++ MSI_CONFIG22, ++ MSI_CONFIG23, ++ MSI_CONFIG24, ++ MSI_CONFIG25, ++ MSI_CONFIG26, ++ MSI_CONFIG27, ++ MSI_CONFIG28, ++ MSI_CONFIG29, ++ MSI_CONFIG30, ++ MSI_CONFIG31, ++ MSI_CONFIG32, ++ MSI_CONFIG33, ++ MSI_CONFIG34, ++ MSI_CONFIG35, ++ MSI_CONFIG36, ++ MSI_CONFIG37, ++ MSI_CONFIG38, ++ MSI_CONFIG39, ++ MSI_CONFIG40, ++ MSI_CONFIG41, ++ MSI_CONFIG42, ++ MSI_CONFIG43, ++ MSI_CONFIG44, ++ MSI_CONFIG45, ++ MSI_CONFIG46, ++ MSI_CONFIG47, ++ MSI_CONFIG48, ++ MSI_CONFIG49, ++ MSI_CONFIG50 ++}; ++ ++int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) ++{ ++ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); ++ ++ if (stat_l & MSI_INT_AVINT_VI0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); ++ ++ if (stat_l & MSI_INT_AVINT_VI1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); ++ ++ if (stat_h & MSI_INT_UNMAPD_TC_INT) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); ++ ++ if (stat_h & MSI_INT_EXTINT_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); ++ ++ if (stat_h & MSI_INT_EXTINT_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); ++ ++ if (stat_h & MSI_INT_EXTINT_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); ++ ++ if (stat_h & MSI_INT_EXTINT_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); ++ ++ if (stat_h & MSI_INT_EXTINT_4) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); ++ ++ if (stat_h & MSI_INT_EXTINT_5) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); ++ ++ if (stat_h & MSI_INT_EXTINT_6) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); ++ ++ if (stat_h & MSI_INT_EXTINT_7) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); ++ ++ if (stat_h & MSI_INT_EXTINT_8) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); ++ ++ if (stat_h & MSI_INT_EXTINT_9) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); ++ ++ if (stat_h & MSI_INT_EXTINT_10) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); ++ ++ if (stat_h & MSI_INT_EXTINT_11) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); ++ ++ if (stat_h & MSI_INT_EXTINT_12) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); ++ ++ if (stat_h & MSI_INT_EXTINT_13) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); ++ ++ if (stat_h & MSI_INT_EXTINT_14) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); ++ ++ if (stat_h & MSI_INT_EXTINT_15) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); ++ ++ if (stat_h & MSI_INT_I2CINT_0) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); ++ saa716x_i2c_irqevent(saa716x, 0); ++ } ++ ++ if (stat_h & MSI_INT_I2CINT_1) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); ++ saa716x_i2c_irqevent(saa716x, 1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_event); ++ ++int saa716x_msi_init(struct saa716x_dev *saa716x) ++{ ++ u32 ena_l, ena_h, sta_l, sta_h, mid; ++ int i; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); ++ saa716x->handlers = 0; ++ ++ /* get module id & version */ ++ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); ++ if (mid != 0x30100) ++ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); ++ ++ /* let HW take care of MSI race */ ++ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); ++ ++ /* INTA Polarity: Active High */ ++ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); ++ ++ /* ++ * IRQ Edge Rising: 25:24 = 0x01 ++ * Traffic Class: 18:16 = 0x00 ++ * MSI ID: 4:0 = 0x00 ++ */ ++ for (i = 0; i < SAA716x_MSI_VECTORS; i++) ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); ++ ++ /* get Status */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ /* disable and clear enabled and asserted IRQ's */ ++ if (sta_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); ++ ++ if (sta_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); ++ ++ if (ena_l) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); ++ ++ if (ena_h) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); ++ ++ msleep(5); ++ ++ /* Check IRQ's really disabled */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", ++ ena_l, ena_h, sta_l, sta_h); ++ ++ return 0; ++ } else { ++ dprintk(SAA716x_DEBUG, 1, "I/O error"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_init); ++ ++void saa716x_msiint_disable(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); ++} ++EXPORT_SYMBOL_GPL(saa716x_msiint_disable); ++ ++ ++/* Map the given vector Id to the hardware bitmask. */ ++static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) ++{ ++ u32 tmp = 1; ++ ++ if (vector < 32) { ++ /* Bits 0 - 31 */ ++ tmp <<= vector; ++ *mask_l = tmp; ++ *mask_h = 0; ++ } else { ++ /* Bits 32 - 48 */ ++ tmp <<= vector - 32; ++ *mask_l = 0; ++ *mask_h = tmp; ++ } ++} ++ ++int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc) ++{ ++ struct saa716x_msix_entry *msix_handler = NULL; ++ ++ u32 config, mask_l, mask_h, ena_l, ena_h; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(vector > SAA716x_MSI_VECTORS); ++ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); ++ ++ if ((vector > 32) && (vector < 49)) { ++ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); ++ config &= 0xfcffffff; /* clear polarity */ ++ ++ switch (edge) { ++ default: ++ case SAA716x_EDGE_RISING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); ++ break; ++ ++ case SAA716x_EDGE_FALLING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); ++ break; ++ ++ case SAA716x_EDGE_ANY: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); ++ break; ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* add callback */ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ strcpy(msix_handler->desc, desc); ++ msix_handler->vector = vector; ++ msix_handler->handler = handler; ++ saa716x->handlers++; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); ++ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); ++ ++ return 0; ++} ++ ++int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) ++{ ++ struct saa716x_msix_entry *msix_handler; ++ int i; ++ u32 mask_l, mask_h; ++ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ BUG_ON(msix_handler == NULL); ++ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); ++ ++ /* loop through the registered handlers */ ++ for (i = 0; i < saa716x->handlers; i++) { ++ ++ /* we found our vector */ ++ if (msix_handler->vector == vector) { ++ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ ++ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", ++ msix_handler->vector, ++ msix_handler->desc); ++ ++ /* check whether it is already released */ ++ if (msix_handler->handler) { ++ msix_handler->vector = 0; ++ msix_handler->handler = NULL; ++ saa716x->handlers--; ++ } ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* disable vector */ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); ++ ++ return 0; ++} +diff --git a/drivers/media/common/saa716x/saa716x_msi.h b/drivers/media/common/saa716x/saa716x_msi.h +new file mode 100644 +index 0000000..8eb72d7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi.h +@@ -0,0 +1,87 @@ ++#ifndef __SAA716x_MSI_H ++#define __SAA716x_MSI_H ++ ++#define TAGACK_VI0_0 0x000 ++#define TAGACK_VI0_1 0x001 ++#define TAGACK_VI0_2 0x002 ++#define TAGACK_VI1_0 0x003 ++#define TAGACK_VI1_1 0x004 ++#define TAGACK_VI1_2 0x005 ++#define TAGACK_FGPI_0 0x006 ++#define TAGACK_FGPI_1 0x007 ++#define TAGACK_FGPI_2 0x008 ++#define TAGACK_FGPI_3 0x009 ++#define TAGACK_AI_0 0x00a ++#define TAGACK_AI_1 0x00b ++#define OVRFLW_VI0_0 0x00c ++#define OVRFLW_VI0_1 0x00d ++#define OVRFLW_VI0_2 0x00e ++#define OVRFLW_VI1_0 0x00f ++#define OVRFLW_VI1_1 0x010 ++#define OVRFLW_VI1_2 0x011 ++#define OVRFLW_FGPI_O 0x012 ++#define OVRFLW_FGPI_1 0x013 ++#define OVRFLW_FGPI_2 0x014 ++#define OVRFLW_FGPI_3 0x015 ++#define OVRFLW_AI_0 0x016 ++#define OVRFLW_AI_1 0x017 ++#define AVINT_VI0 0x018 ++#define AVINT_VI1 0x019 ++#define AVINT_FGPI_0 0x01a ++#define AVINT_FGPI_1 0x01b ++#define AVINT_FGPI_2 0x01c ++#define AVINT_FGPI_3 0x01d ++#define AVINT_AI_0 0x01e ++#define AVINT_AI_1 0x01f ++#define UNMAPD_TC_INT 0x020 ++#define EXTINT_0 0x021 ++#define EXTINT_1 0x022 ++#define EXTINT_2 0x023 ++#define EXTINT_3 0x024 ++#define EXTINT_4 0x025 ++#define EXTINT_5 0x026 ++#define EXTINT_6 0x027 ++#define EXTINT_7 0x028 ++#define EXTINT_8 0x029 ++#define EXTINT_9 0x02a ++#define EXTINT_10 0x02b ++#define EXTINT_11 0x02c ++#define EXTINT_12 0x02d ++#define EXTINT_13 0x02e ++#define EXTINT_14 0x02f ++#define EXTINT_15 0x030 ++#define I2CINT_0 0x031 ++#define I2CINT_1 0x032 ++ ++#define SAA716x_TC0 0x000 ++#define SAA716x_TC1 0x001 ++#define SAA716x_TC2 0x002 ++#define SAA716x_TC3 0x003 ++#define SAA716x_TC4 0x004 ++#define SAA716x_TC5 0x005 ++#define SAA716x_TC6 0x006 ++#define SAA716x_TC7 0x007 ++ ++ ++enum saa716x_edge { ++ SAA716x_EDGE_RISING = 1, ++ SAA716x_EDGE_FALLING = 2, ++ SAA716x_EDGE_ANY = 3 ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); ++ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc); ++ ++extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); ++ ++#endif /* __SAA716x_MSI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_msi_reg.h b/drivers/media/common/saa716x/saa716x_msi_reg.h +new file mode 100644 +index 0000000..d9a12c7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi_reg.h +@@ -0,0 +1,143 @@ ++#ifndef __SAA716x_MSI_REG_H ++#define __SAA716x_MSI_REG_H ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++#endif /* __SAA716x_MSI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_pci.c b/drivers/media/common/saa716x/saa716x_pci.c +new file mode 100644 +index 0000000..7fa6bad +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_pci.c +@@ -0,0 +1,275 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_msi.h" ++#include "saa716x_priv.h" ++ ++#define DRIVER_NAME "SAA716x Core" ++ ++static irqreturn_t saa716x_msi_handler(int irq, void *dev_id) ++{ ++ return IRQ_HANDLED; ++} ++ ++static int saa716x_enable_msi(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err; ++ ++ err = pci_enable_msi(pdev); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static int saa716x_enable_msix(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, ret = 0; ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); ++ if (ret < 0) ++ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); ++ if (ret > 0) ++ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); ++ ++ return ret; ++} ++ ++static int saa716x_request_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_config *config = saa716x->config; ++ int i, ret = 0; ++ ++ if (saa716x->int_type == MODE_MSI) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); ++ ret = saa716x_enable_msi(saa716x); ++ } else if (saa716x->int_type == MODE_MSI_X) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); ++ ret = saa716x_enable_msix(saa716x); ++ } ++ ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); ++ saa716x->int_type = MODE_INTA; ++ } ++ ++ if (saa716x->int_type == MODE_MSI) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ 0, ++ DRIVER_NAME, ++ saa716x); ++ ++ if (ret) { ++ pci_disable_msi(pdev); ++ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); ++ ret = -EIO; ++ } ++ } ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { ++ ret = request_irq(saa716x->msix_entries[i].vector, ++ saa716x->saa716x_msix_handler[i].handler, ++ IRQF_SHARED, ++ saa716x->saa716x_msix_handler[i].desc, ++ saa716x); ++ ++ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); ++ return -1; ++ } ++ } ++ } ++ ++ if (saa716x->int_type == MODE_INTA) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ IRQF_SHARED, ++ DRIVER_NAME, ++ saa716x); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); ++ ret = -ENODEV; ++ } ++ } ++ ++ return ret; ++} ++ ++static void saa716x_free_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, vector; ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { ++ vector = saa716x->msix_entries[i].vector; ++ free_irq(vector, saa716x); ++ } ++ ++ pci_disable_msix(pdev); ++ ++ } else { ++ free_irq(pdev->irq, saa716x); ++ if (saa716x->int_type == MODE_MSI) ++ pci_disable_msi(pdev); ++ } ++} ++ ++int saa716x_pci_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; ++ u32 msi_cap; ++ u8 revision; ++ ++ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); ++ ++ err = pci_enable_device(pdev); ++ if (err != 0) { ++ ret = -ENODEV; ++ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); ++ goto fail0; ++ } ++ ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { ++ use_dac = 1; ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); ++ goto fail1; ++ } ++ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); ++ goto fail1; ++ } ++ ++ pci_set_master(pdev); ++ ++ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); ++ if (pm_cap == 0) { ++ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); ++ err = -EIO; ++ goto fail1; ++ } ++ ++ if (!request_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0), ++ DRIVER_NAME)) { ++ ++ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); ++ ret = -ENODEV; ++ goto fail1; ++ } ++ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++ if (!saa716x->mmio) { ++ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); ++ ret = -ENODEV; ++ goto fail2; ++ } ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ err = saa716x_request_irq(saa716x); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); ++ ret = -ENODEV; ++ goto fail3; ++ } ++ ++ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); ++ pci_read_config_dword(pdev, 0x40, &msi_cap); ++ ++ saa716x->revision = revision; ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", ++ saa716x->pdev->device, ++ revision, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 0, ++ "irq: %d,\n mmio: 0x%p\n", ++ saa716x->pdev->irq, ++ saa716x->mmio); ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", ++ saa716x->pdev->device, ++ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), ++ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), ++ (1 << ((msi_cap >> 17) & 0x07))); ++ ++ dprintk(SAA716x_ERROR, 0, "\n"); ++ ++ pci_set_drvdata(pdev, saa716x); ++ ++ return 0; ++ ++fail3: ++ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); ++ if (saa716x->mmio) ++ iounmap(saa716x->mmio); ++fail2: ++ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++fail1: ++ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); ++ pci_disable_device(pdev); ++ ++fail0: ++ pci_set_drvdata(pdev, NULL); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_init); ++ ++void saa716x_pci_exit(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ saa716x_free_irq(saa716x); ++ ++ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", ++ saa716x->pdev->device, ++ saa716x->mmio); ++ ++ if (saa716x->mmio) { ++ iounmap(saa716x->mmio); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ } ++ ++ pci_disable_device(pdev); ++ pci_set_drvdata(pdev, NULL); ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_exit); ++ ++MODULE_DESCRIPTION("SAA716x bridge driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_phi.c b/drivers/media/common/saa716x/saa716x_phi.c +new file mode 100644 +index 0000000..7df9a98 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi.c +@@ -0,0 +1,152 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_spi.h" ++#include "saa716x_phi.h" ++#include "saa716x_priv.h" ++ ++u32 PHI_0_REGS[] = { ++ PHI_0_MODE, ++ PHI_0_0_CONFIG, ++ PHI_0_1_CONFIG, ++ PHI_0_2_CONFIG, ++ PHI_0_3_CONFIG ++}; ++ ++u32 PHI_1_REGS[] = { ++ PHI_1_MODE, ++ PHI_1_0_CONFIG, ++ PHI_1_1_CONFIG, ++ PHI_1_2_CONFIG, ++ PHI_1_3_CONFIG, ++ PHI_1_4_CONFIG, ++ PHI_1_5_CONFIG, ++ PHI_1_6_CONFIG, ++ PHI_1_7_CONFIG ++}; ++ ++#define PHI_BASE(__port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_BASE : \ ++ PHI_0_BASE \ ++)) ++ ++#define PHI_APERTURE(_port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_APERTURE: \ ++ PHI_0_APERTURE \ ++)) ++ ++#define PHI_REG(__port, __reg) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_REGS[__reg] : \ ++ PHI_0_REGS[__reg] \ ++)) ++ ++#define PHI_SLAVE(__port, __slave) (( \ ++ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ ++)) ++ ++/* // Read SAA716x registers ++ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) ++ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) ++ * ++ * // Read slave registers ++ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) ++ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) ++ */ ++ ++int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) ++{ ++ int i; ++ ++ /* Reset */ ++ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); ++ ++ for (i = 0; i < 20; i++) { ++ msleep(1); ++ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_phi_init(struct saa716x_dev *saa716x) ++{ ++ uint32_t value; ++ ++ /* init PHI 0 to FIFO mode */ ++ value = 0; ++ value |= PHI_FIFO_MODE; ++ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); ++ ++ value = 0; ++ value |= 0x02; /* chip select 1 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x06 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); ++ ++ /* init PHI 1 to SRAM mode, auto increment on */ ++ value = 0; ++ value |= PHI_AUTO_INCREMENT; ++ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); ++ ++ value = 0; ++ value |= 0x01; /* chip select 0 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x05 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); ++ ++ value = 0; ++ value |= PHI_ALE_POL; /* ALE is active high */ ++ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); ++ ++ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_init); ++ ++int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write); ++ ++int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_read); ++ ++int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); +diff --git a/drivers/media/common/saa716x/saa716x_phi.h b/drivers/media/common/saa716x/saa716x_phi.h +new file mode 100644 +index 0000000..ff5cda2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi.h +@@ -0,0 +1,39 @@ ++#ifndef __SAA716x_PHI_H ++#define __SAA716x_PHI_H ++ ++/* PHI SLAVE */ ++#define PHI_SLAVE_0 0 ++#define PHI_SLAVE_1 1 ++#define PHI_SLAVE_2 2 ++#define PHI_SLAVE_3 3 ++#define PHI_SLAVE_4 4 ++#define PHI_SLAVE_5 5 ++#define PHI_SLAVE_6 6 ++#define PHI_SLAVE_7 7 ++ ++/* PHI_REG */ ++#define PHI_MODE 0 ++#define PHI_CONFIG_0 1 ++#define PHI_CONFIG_1 2 ++#define PHI_CONFIG_2 3 ++#define PHI_CONFIG_3 4 ++#define PHI_CONFIG_4 5 ++#define PHI_CONFIG_5 6 ++#define PHI_CONFIG_6 7 ++#define PHI_CONFIG_7 8 ++ ++#define PHI_0_BASE 0x1000 ++#define PHI_0_APERTURE 0x0800 ++ ++#define PHI_1_BASE 0x0000 ++#define PHI_1_APERTURE 0xfffc ++ ++struct saa716x_dev; ++ ++extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); ++extern int saa716x_phi_init(struct saa716x_dev *saa716x); ++extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); ++extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); ++extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); ++ ++#endif /* __SAA716x_PHI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_phi_reg.h b/drivers/media/common/saa716x/saa716x_phi_reg.h +new file mode 100644 +index 0000000..08f0aa7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi_reg.h +@@ -0,0 +1,100 @@ ++#ifndef __SAA716x_PHI_REG_H ++#define __SAA716x_PHI_REG_H ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++ ++/* BAR = 20 bits */ ++/* -------------- PHI1 Registers -------------- */ ++ ++ ++#endif /* __SAA716x_PHI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_priv.h b/drivers/media/common/saa716x/saa716x_priv.h +new file mode 100644 +index 0000000..1ad1d9c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_priv.h +@@ -0,0 +1,194 @@ ++#ifndef __SAA716x_PRIV_H ++#define __SAA716x_PRIV_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "saa716x_i2c.h" ++#include "saa716x_boot.h" ++#include "saa716x_cgu.h" ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++ ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dmxdev.h" ++#include "dvb_frontend.h" ++#include "dvb_net.h" ++ ++#define SAA716x_ERROR 0 ++#define SAA716x_NOTICE 1 ++#define SAA716x_INFO 2 ++#define SAA716x_DEBUG 3 ++ ++#define SAA716x_DEV (saa716x)->num ++#define SAA716x_VERBOSE (saa716x)->verbose ++#define SAA716x_MAX_ADAPTERS 4 ++ ++#define dprintk(__x, __y, __fmt, __arg...) do { \ ++ if (__y) { \ ++ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ } else { \ ++ if (SAA716x_VERBOSE > __x) \ ++ printk(__fmt , ##__arg); \ ++ } \ ++} while(0) ++ ++ ++#define NXP_SEMICONDUCTOR 0x1131 ++#define SAA7160 0x7160 ++#define SAA7161 0x7161 ++#define SAA7162 0x7162 ++ ++#define NXP_REFERENCE_BOARD 0x1131 ++ ++#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ ++ .vendor = NXP_SEMICONDUCTOR, \ ++ .device = (__chip), \ ++ .subvendor = (__subven), \ ++ .subdevice = (__subdev), \ ++ .driver_data = (unsigned long) (__configptr) \ ++} ++ ++#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++ ++#define SAA716x_MSI_MAX_VECTORS 16 ++ ++struct saa716x_msix_entry { ++ int vector; ++ u8 desc[32]; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++struct saa716x_dev; ++struct saa716x_adapter; ++struct saa716x_spi_config; ++ ++struct saa716x_adap_config { ++ u32 ts_port; ++ void (*worker)(unsigned long); ++}; ++ ++struct saa716x_config { ++ char *model_name; ++ char *dev_type; ++ ++ enum saa716x_boot_mode boot_mode; ++ ++ int adapters; ++ int frontends; ++ ++ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); ++ irqreturn_t (*irq_handler)(int irq, void *dev_id); ++ ++ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; ++ enum saa716x_i2c_rate i2c_rate; ++ enum saa716x_i2c_mode i2c_mode; ++}; ++ ++struct saa716x_adapter { ++ struct dvb_adapter dvb_adapter; ++ struct dvb_frontend *fe; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ struct dvb_net dvb_net; ++ ++ struct saa716x_dev *saa716x; ++ ++ u8 feeds; ++ u8 count; ++}; ++ ++struct saa716x_dev { ++ struct saa716x_config *config; ++ struct pci_dev *pdev; ++ ++ int num; /* device count */ ++ int verbose; ++ ++ u8 revision; ++ ++ /* PCI */ ++ void __iomem *mmio; ++ ++#define MODE_INTA 0 ++#define MODE_MSI 1 ++#define MODE_MSI_X 2 ++ u8 int_type; ++ ++ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; ++ struct saa716x_msix_entry saa716x_msix_handler[56]; ++ u8 handlers; /* no. of active handlers */ ++ ++ /* I2C */ ++ struct saa716x_i2c i2c[2]; ++ u32 i2c_rate; /* init time */ ++ u32 I2C_DEV[2]; ++ ++ struct saa716x_spi_state *saa716x_spi; ++ struct saa716x_spi_config spi_config; ++ ++ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; ++ struct mutex adap_lock; ++ struct saa716x_cgu cgu; ++ ++ spinlock_t gpio_lock; ++ /* DMA */ ++ ++ struct saa716x_fgpi_stream_port fgpi[4]; ++ ++ u32 id_offst; ++ u32 id_len; ++ void *priv; ++ ++ /* remote control */ ++ void *ir_priv; ++}; ++ ++/* PCI */ ++extern int saa716x_pci_init(struct saa716x_dev *saa716x); ++extern void saa716x_pci_exit(struct saa716x_dev *saa716x); ++ ++/* MSI */ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msi_exit(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++/* DMA */ ++extern int saa716x_dma_init(struct saa716x_dev *saa716x); ++extern void saa716x_dma_exit(struct saa716x_dev *saa716x); ++ ++/* AUDIO */ ++extern int saa716x_audio_init(struct saa716x_dev *saa716x); ++extern void saa716x_audio_exit(struct saa716x_dev *saa716x); ++ ++/* Boot */ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++ ++/* Remote control */ ++extern int saa716x_ir_init(struct saa716x_dev *saa716x); ++extern void saa716x_ir_exit(struct saa716x_dev *saa716x); ++extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); ++ ++#endif /* __SAA716x_PRIV_H */ +diff --git a/drivers/media/common/saa716x/saa716x_reg.h b/drivers/media/common/saa716x/saa716x_reg.h +new file mode 100644 +index 0000000..effd966 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_reg.h +@@ -0,0 +1,1279 @@ ++#ifndef __SAA716x_REG_H ++#define __SAA716x_REG_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++ ++ ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM 0x00008000 ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU 0x00009000 ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI 0x0000a000 ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI 0x0000d000 ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO 0x0000e000 ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0 0x0000f000 ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU 0x00013000 ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCS 0x00014000 ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG 0x00012000 ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++/* BAR = 20 bits */ ++ ++/* -------------- PHI1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++ ++ ++#endif /* __SAA716x_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_rom.c b/drivers/media/common/saa716x/saa716x_rom.c +new file mode 100644 +index 0000000..7f8dbe1 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_rom.c +@@ -0,0 +1,1071 @@ ++#include ++#include ++ ++#include "saa716x_rom.h" ++#include "saa716x_adap.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++int i; ++ ++static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ ++ u8 b0[] = { MSB(reg), LSB(reg) }; ++ int ret; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, ++ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } ++ }; ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ struct i2c_msg msg[2]; ++ ++ u8 b0[2]; ++ int ret, count; ++ ++ count = len / DUMP_BYTES; ++ if (len % DUMP_BYTES) ++ count++; ++ ++ count *= 2; ++ ++ for (i = 0; i < count; i += 2) { ++ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", ++ len, ++ count, ++ reg); ++ ++ b0[0] = MSB(reg); ++ b0[1] = LSB(reg); ++ ++ /* Write */ ++ msg[0].addr = 0x50; ++ msg[0].flags = 0; ++ msg[0].buf = b0; ++ msg[0].len = 2; ++ ++ /* Read */ ++ msg[1].addr = 0x50; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ ++ if (i == (count - 2)) { ++ /* last message */ ++ if (len % DUMP_BYTES) { ++ msg[1].len = len % DUMP_BYTES; ++ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ reg += DUMP_BYTES; ++ val += DUMP_BYTES; ++ } ++ ++ return 0; ++} ++ ++static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) ++{ ++ int i; ++ ++ *offset = 0; ++ for (i = 0; i < 256; i++) { ++ if (!(strncmp("START", buf + i, 5))) ++ break; ++ } ++ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); ++ *offset = i; ++ ++ return 0; ++} ++ ++static int saa716x_eeprom_header(struct saa716x_dev *saa716x, ++ struct saa716x_romhdr *rom_header, ++ u8 *buf, ++ u32 *offset) ++{ ++ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); ++ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ (int)sizeof (struct saa716x_romhdr), ++ rom_header->header_size); ++ ++ return -1; ++ } ++ *offset += sizeof (struct saa716x_romhdr); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", ++ saa716x->pdev->device, ++ rom_header->data_size); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", ++ saa716x->pdev->device, ++ rom_header->version); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", ++ saa716x->pdev->device, ++ rom_header->devices); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", ++ saa716x->pdev->device, ++ rom_header->compression); ++ ++ return 0; ++} ++ ++int saa716x_dump_eeprom(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ u8 buf[DUMP_BYTES]; ++ int i, err = 0; ++ u32 offset = 0; ++ ++ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); ++ return err; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", ++ saa716x->config->model_name); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", ++ saa716x->pdev->device, ++ DUMP_OFFST); ++ ++ for (i = 0; i < DUMP_BYTES; i++) { ++ if ((i % 16) == 0) { ++ dprintk(SAA716x_NOTICE, 0, "\n "); ++ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); ++ } ++ ++ if ((i % 8) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); ++ } ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", ++ saa716x->pdev->device); ++ ++ err = saa716x_get_offset(saa716x, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); ++ return err; ++ } ++ offset += 5; ++ saa716x->id_offst = offset; ++ /* Get header */ ++ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); ++ return -1; ++ } ++ saa716x->id_len = rom_header.data_size; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); ++ ++static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++static int saa716x_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext Data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_gpio_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_gpio_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_gpio_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_gpio_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pins=%d\n", ++ saa716x->pdev->device, ++ header.pins); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ ++ return 0; ++} ++ ++static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_video_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_video_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 0=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port0); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 1=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port1); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 2=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port2); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT ID=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_id); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_audio_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_audio_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_event_source_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_evsrc_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_evsrc_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_crossbar_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_xbar_hdr header; ++ struct saa716x_xbar_pair_info pair_info; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_xbar_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_xbar_hdr)); ++ ++ return -1; ++ } ++ ++ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pairs=%d\n", ++ saa716x->pdev->device, ++ header.pair_inputs); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); ++ return 0; ++} ++ ++static int saa716x_tuner_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_tuner_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_tuner_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_tuner_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_pll_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_pll_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_pll_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_pll_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_channel_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_channel_decoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_encoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_encoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_encoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_encoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_ir_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_ir_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_ir_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_ir_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_eeprom_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_eeprom_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_eeprom_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_filter_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_filter_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_filter_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_filter_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_streamdev_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_streamdev_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_streamdev_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 size; ++ u8 ext_size = 0; ++ ++ size = buf[*offset]; ++ if (size > 1) ++ ext_size = buf[*offset + size -1]; ++ ++ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ ext_size); ++ ++ *offset += size + ext_size; ++ return 0; ++} ++ ++ ++static void saa716x_device_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size, ++ u8 addr_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size + addr_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++ ++static int saa716x_device_info(struct saa716x_dev *saa716x, ++ struct saa716x_devinfo *device, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 address = 0; ++ ++ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); ++ if (device->struct_size != sizeof(struct saa716x_devinfo)) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", ++ device->struct_size, ++ (int)sizeof(struct saa716x_devinfo)); ++ ++ return -1; ++ } ++ ++ saa716x_device_dbg(saa716x, ++ buf, ++ offset, ++ device->struct_size, ++ device->extd_data_size, ++ device->addr_size); ++ ++ *offset += device->struct_size; ++ ++ if (device->addr_size) { ++ address = buf[*offset]; ++ address >>= 1; ++ *offset += device->addr_size; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", ++ saa716x->pdev->device, ++ address); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ device->struct_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_devid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_busid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_type); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->implem_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->path_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->gpio_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", ++ saa716x->pdev->device, ++ device->addr_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", ++ saa716x->pdev->device, ++ device->extd_data_size); ++ ++ if (device->extd_data_size) { ++ u32 mask; ++ ++ mask = 0x00000001; ++ while (mask) { ++ if (device->device_type & mask) { ++ switch (mask) { ++ case DECODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case GPIO_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found GPIO device\n", ++ saa716x->pdev->device); ++ ++ saa716x_gpio_info(saa716x, buf, offset); ++ break; ++ ++ case VIDEO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Video Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_video_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case AUDIO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Audio Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_audio_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case EVENT_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Event source\n", ++ saa716x->pdev->device); ++ ++ saa716x_event_source_info(saa716x, buf, offset); ++ break; ++ ++ case CROSSBAR: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Crossbar device\n", ++ saa716x->pdev->device); ++ ++ saa716x_crossbar_info(saa716x, buf, offset); ++ break; ++ ++ case TUNER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Tuner device\n", ++ saa716x->pdev->device); ++ ++ saa716x_tuner_info(saa716x, buf, offset); ++ break; ++ ++ case PLL_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found PLL device\n", ++ saa716x->pdev->device); ++ ++ saa716x_pll_info(saa716x, buf, offset); ++ break; ++ ++ case CHANNEL_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Channel Demodulator device\n", ++ saa716x->pdev->device); ++ ++ saa716x_channel_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case RDS_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found RDS Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case ENCODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Encoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_encoder_info(saa716x, buf, offset); ++ break; ++ ++ case IR_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found IR device\n", ++ saa716x->pdev->device); ++ ++ saa716x_ir_info(saa716x, buf, offset); ++ break; ++ ++ case EEPROM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found EEPROM device\n", ++ saa716x->pdev->device); ++ ++ saa716x_eeprom_info(saa716x, buf, offset); ++ break; ++ ++ case NOISE_FILTER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Noise filter device\n", ++ saa716x->pdev->device); ++ ++ saa716x_filter_info(saa716x, buf, offset); ++ break; ++ ++ case LNx_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found LNx device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case STREAM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found streaming device\n", ++ saa716x->pdev->device); ++ ++ saa716x_streamdev_info(saa716x, buf, offset); ++ break; ++ ++ case CONFIGSPACE_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Configspace device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ default: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found unknown device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ } ++ } ++ mask <<= 1; ++ } ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ ++ return 0; ++} ++ ++int saa716x_eeprom_data(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ struct saa716x_devinfo *device; ++ ++ u8 buf[1024]; ++ int i, ret = 0; ++ u32 offset = 0; ++ ++ /* dump */ ++ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); ++ goto err0; ++ } ++ ++ /* Get header */ ++ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); ++ goto err0; ++ } ++ ++ /* allocate for device info */ ++ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); ++ if (device == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); ++ goto err0; ++ } ++ ++ for (i = 0; i < rom_header.devices; i++) { ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", ++ saa716x->pdev->device, ++ i); ++ ++ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); ++ goto err1; ++ } ++ } ++ ++ kfree(device); ++ ++ return 0; ++ ++err1: ++ kfree(device); ++ ++err0: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_eeprom_data); +diff --git a/drivers/media/common/saa716x/saa716x_rom.h b/drivers/media/common/saa716x/saa716x_rom.h +new file mode 100644 +index 0000000..6bb317f +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_rom.h +@@ -0,0 +1,253 @@ ++#ifndef __SAA716x_ROM_H ++#define __SAA716x_ROM_H ++ ++ ++#define MSB(__x) ((__x >> 8) & 0xff) ++#define LSB(__x) (__x & 0xff) ++ ++#define DUMP_BYTES 0xf0 ++#define DUMP_OFFST 0x000 ++ ++struct saa716x_dev; ++ ++struct saa716x_romhdr { ++ u16 header_size; ++ u8 compression; ++ u8 version; ++ u16 data_size; ++ u8 devices; ++ u8 checksum; ++} __attribute__((packed)); ++ ++struct saa716x_devinfo { ++ u8 struct_size; ++ u8 device_id; ++ u8 master_devid; ++ u8 master_busid; ++ u32 device_type; ++ u16 implem_id; ++ u8 path_id; ++ u8 gpio_id; ++ u16 addr_size; ++ u16 extd_data_size; ++} __attribute__((packed)); ++ ++enum saa716x_device_types { ++ DECODER_DEVICE = 0x00000001, ++ GPIO_SOURCE = 0x00000002, ++ VIDEO_DECODER = 0x00000004, ++ AUDIO_DECODER = 0x00000008, ++ EVENT_SOURCE = 0x00000010, ++ CROSSBAR = 0x00000020, ++ TUNER_DEVICE = 0x00000040, ++ PLL_DEVICE = 0x00000080, ++ CHANNEL_DECODER = 0x00000100, ++ RDS_DECODER = 0x00000200, ++ ENCODER_DEVICE = 0x00000400, ++ IR_DEVICE = 0x00000800, ++ EEPROM_DEVICE = 0x00001000, ++ NOISE_FILTER = 0x00002000, ++ LNx_DEVICE = 0x00004000, ++ STREAM_DEVICE = 0x00010000, ++ CONFIGSPACE_DEVICE = 0x80000000 ++}; ++ ++struct saa716x_decoder_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_decoder_info { ++ struct saa716x_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_gpio_hdr { ++ u8 size; ++ u8 pins; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_gpio_info { ++ struct saa716x_gpio_hdr gpio_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_video_decoder_hdr { ++ u8 size; ++ u8 video_port0; ++ u8 video_port1; ++ u8 video_port2; ++ u8 vbi_port_id; ++ u8 video_port_type; ++ u8 vbi_port_type; ++ u8 encoder_port_type; ++ u8 video_output; ++ u8 vbi_output; ++ u8 encoder_output; ++ u8 ext_data; ++}; ++ ++struct saa716x_video_decoder_info { ++ struct saa716x_video_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_audio_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 output; ++ u8 ext_data; ++}; ++ ++struct saa716x_audio_decoder_info { ++ struct saa716x_audio_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_evsrc_hdr { ++ u8 size; ++ u8 master_devid; ++ u16 condition_id; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_evsrc_info { ++ struct saa716x_evsrc_hdr evsrc_hdr; ++ u8 *ext_data; ++}; ++ ++enum saa716x_input_pair_type { ++ TUNER_SIF = 0x00, ++ TUNER_LINE = 0x01, ++ TUNER_SPDIF = 0x02, ++ TUNER_NONE = 0x03, ++ CVBS_LINE = 0x04, ++ CVBS_SPDIF = 0x05, ++ CVBS_NONE = 0x06, ++ YC_LINE = 0x07, ++ YC_SPDIF = 0x08, ++ YC_NONE = 0x09, ++ YPbPr_LINE = 0x0a, ++ YPbPr_SPDIF = 0x0b, ++ YPbPr_NONE = 0x0c, ++ NO_LINE = 0x0d, ++ NO_SPDIF = 0x0e, ++ RGB_LINE = 0x0f, ++ RGB_SPDIF = 0x10, ++ RGB_NONE = 0x11 ++}; ++ ++struct saa716x_xbar_pair_info { ++ u8 pair_input_type; ++ u8 video_input_id; ++ u8 audio_input_id; ++}; ++ ++struct saa716x_xbar_hdr { ++ u8 size; ++ u8 pair_inputs; ++ u8 pair_route_default; ++ u8 ext_data; ++}; ++ ++struct saa716x_xbar_info { ++ struct saa716x_xbar_hdr xbar_hdr; ++ struct saa716x_xbar_pair_info *pair_info; ++ u8 *ext_data; ++}; ++ ++struct saa716x_tuner_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_tuner_info { ++ struct saa716x_tuner_hdr tuner_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_pll_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_pll_info { ++ struct saa716x_pll_hdr pll_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_channel_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 ext_data; ++}; ++ ++struct saa716x_channel_decoder_info { ++ struct saa716x_channel_decoder_hdr channel_dec_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_encoder_hdr { ++ u8 size; ++ u8 stream_port0; ++ u8 stream_port1; ++ u8 ext_data; ++}; ++ ++struct saa716x_encoder_info { ++ struct saa716x_encoder_hdr encoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_ir_hdr { ++ u8 size; ++ u8 ir_caps; ++ u8 ext_data; ++}; ++ ++struct saa716x_ir_info { ++ struct saa716x_ir_hdr ir_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_eeprom_hdr { ++ u8 size; ++ u8 rel_device; ++ u8 ext_data; ++}; ++ ++struct saa716x_eeprom_info { ++ struct saa716x_eeprom_hdr eeprom_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_filter_hdr { ++ u8 size; ++ u8 video_decoder; ++ u8 audio_decoder; ++ u8 event_source; ++ u8 ext_data; ++}; ++ ++struct saa716x_filter_info { ++ struct saa716x_filter_hdr filter_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_streamdev_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_streamdev_info { ++ struct saa716x_streamdev_hdr streamdev_hdr; ++ u8 *ext_data; ++}; ++ ++extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); ++extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ROM_H */ +diff --git a/drivers/media/common/saa716x/saa716x_spi.c b/drivers/media/common/saa716x/saa716x_spi.c +new file mode 100644 +index 0000000..8859454 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi.c +@@ -0,0 +1,313 @@ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_spi_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#if 0 // not needed atm ++int saa716x_spi_irqevent(struct saa716x_dev *saa716x) ++{ ++ u32 stat, mask; ++ ++ BUG_ON(saa716x == NULL); ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; ++ if ((!stat && !mask)) ++ return -1; ++ ++ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++#endif ++ ++void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ int i; ++ u32 value; ++ int rounds; ++ ++ for (i = 0; i < length; i++) { ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ rounds = 0; ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ rounds++; ++ } ++ } ++} ++EXPORT_SYMBOL_GPL(saa716x_spi_write); ++ ++#if 0 // not needed atm ++static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) ++{ ++ u32 stat; ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); ++ ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); ++ ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); ++ ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); ++ ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); ++ ++ *status = stat; ++ ++ return 0; ++} ++ ++#define SPI_CYCLE_TIMEOUT 100 ++ ++static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) ++{ ++ u32 i, status = 0; ++ ++ /* write data and wait for completion */ ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { ++ msleep(10); ++ saa716x_spi_status(saa716x, &status); ++#if 0 ++ if (status & SPI_TRANSFER_FLAG) { ++ data = SAA716x_EPRD(SPI, SPI_DATA); ++ return 0; ++ } ++#endif ++ if (status & (SPI_WRITE_COLLISSION | ++ SPI_READ_OVERRUN | ++ SPI_MODE_FAULT | ++ SPI_SLAVE_ABORT)) ++ ++ return -EIO; ++ } ++ ++ return -EIO; ++} ++ ++#if 0 ++static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ struct saa716x_spi_config *config = saa716x->spi_config; ++ u32 gpio_mask; ++ int ret = 0; ++ ++ // protect against multiple access ++ spin_lock(&saa716x->gpio_lock); ++ ++ // configure the module ++ saa716x_spi_config(saa716x); ++ ++ // check input ++ ++ // change polarity of GPIO if active high ++ if (config->active_hi) { ++ select = 1; ++ release = 0; ++ } ++ ++ // configure GPIO, first set output register to low selected level ++ saa716x_gpio_write(saa716x, gpio, select); ++ ++ // set mode register to register controlled (0) ++ gpio_mask = (1 << gpio); ++ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); ++ ++ // configure bit as output (0) ++ saa716x_gpio_ctl(saa716x, gpio_mask, 0); ++ ++ // wait at least 500ns before sending a byte ++ msleep(1); ++ ++ // send command ++ for (i = 0; i < dwCommandSize; i++) { ++ ucData = 0; ++// dwStatus = TransferData(pucCommand[i], &ucData); ++ ret = saa716x_spi_xfer(saa716x); ++ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); ++ ++ /* If command length > 1, disable CS at the end of each command. ++ * But after the last command byte CS must be left active! ++ */ ++ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { ++ ++ saa716x_gpio_write(saa716x, gpio, release); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, select); ++ } ++ ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ ++ spin_unlock(&saa716x->spi_lock); ++ return ret; ++ } ++ ++ if (config->LSB_first) ++ dwTransferByte++; ++ else ++ dwTransferByte--; ++ } ++ ++// assume that the byte order is the same as the bit order ++ ++// send read address ++ ++// send data ++ ++// wait at least 500ns before releasing slave ++ ++// release GPIO pin ++ ++ // release spinlock ++ spin_unlock(&saa716x->gpio_lock); ++} ++#endif ++ ++#define MODEBITS (SPI_CPOL | SPI_CPHA) ++ ++static int saa716x_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ struct saa716x_spi_config *config = &saa716x->spi_config; ++ ++ u8 control = 0; ++ ++ if (spi->mode & ~MODEBITS) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", ++ spi->mode & ~MODEBITS); ++ ++ return -EINVAL; ++ } ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); ++ ++ control |= SPI_MODE_SELECT; /* SPI Master */ ++ ++ if (config->LSB_first) ++ control |= SPI_LSB_FIRST_ENABLE; ++ ++ if (config->clk_pol) ++ control |= SPI_CLOCK_POLARITY; ++ ++ if (config->clk_pha) ++ control |= SPI_CLOCK_PHASE; ++ ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); ++ ++ return 0; ++} ++ ++static void saa716x_spi_cleanup(struct spi_device *spi) ++{ ++ ++} ++ ++static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++#if 0 ++ if (saa716x_spi->run == QUEUE_STOPPED) { ++ spin_unlock_irqrestore(&saa716x_spi->lock, flags); ++ return -ESHUTDOWN; ++ } ++ ++ msg->actual_length = 0; ++ msg->status = -EINPROGRESS; ++ msg->state = START_STATE; ++ ++ list_add_tail(&msg->queue, &saa716x_spi->queue); ++ ++ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) ++ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); ++#endif ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++int saa716x_spi_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct spi_master *master; ++ struct saa716x_spi_state *saa716x_spi; ++ int ret; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); ++ if (master == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); ++ return -ENOMEM; ++ } ++ ++ saa716x_spi = spi_master_get_devdata(master); ++ saa716x_spi->master = master; ++ saa716x_spi->saa716x = saa716x; ++ saa716x->saa716x_spi = saa716x_spi; ++ ++ master->bus_num = pdev->bus->number; ++ master->num_chipselect = 1; /* TODO! use config */ ++ master->cleanup = saa716x_spi_cleanup; ++ master->setup = saa716x_spi_setup; ++ master->transfer = saa716x_spi_transfer; ++ ++ ret = spi_register_master(master); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); ++ goto err; ++ } ++err: ++ spi_master_put(master); ++ return ret; ++} ++EXPORT_SYMBOL(saa716x_spi_init); ++ ++void saa716x_spi_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; ++ ++ spi_unregister_master(saa716x_spi->master); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); ++} ++EXPORT_SYMBOL(saa716x_spi_exit); ++#endif ++ +diff --git a/drivers/media/common/saa716x/saa716x_spi.h b/drivers/media/common/saa716x/saa716x_spi.h +new file mode 100644 +index 0000000..0060c22 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi.h +@@ -0,0 +1,23 @@ ++#ifndef __SAA716x_SPI_H ++#define __SAA716x_SPI_H ++ ++struct saa716x_dev; ++ ++struct saa716x_spi_config { ++ u8 clk_count; ++ u8 clk_pol:1; ++ u8 clk_pha:1; ++ u8 LSB_first:1; ++}; ++ ++struct saa716x_spi_state { ++ struct spi_master *master; ++ struct saa716x_dev *saa716x; ++}; ++ ++extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); ++ ++extern int saa716x_spi_init(struct saa716x_dev *saa716x); ++extern void saa716x_spi_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_SPI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_spi_reg.h b/drivers/media/common/saa716x/saa716x_spi_reg.h +new file mode 100644 +index 0000000..c51abce +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi_reg.h +@@ -0,0 +1,27 @@ ++#ifndef __SAA716x_SPI_REG_H ++#define __SAA716x_SPI_REG_H ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_SPI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_vip.c b/drivers/media/common/saa716x/saa716x_vip.c +new file mode 100644 +index 0000000..4cd4c81 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip.c +@@ -0,0 +1,23 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_vip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_vipint_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ ++ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++} ++EXPORT_SYMBOL_GPL(saa716x_vipint_disable); ++ ++void saa716x_vip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); ++ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_disable); +diff --git a/drivers/media/common/saa716x/saa716x_vip.h b/drivers/media/common/saa716x/saa716x_vip.h +new file mode 100644 +index 0000000..55c6a1a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_VIP_H ++#define __SAA716x_VIP_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); ++extern void saa716x_vip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_VIP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_vip_reg.h b/drivers/media/common/saa716x/saa716x_vip_reg.h +new file mode 100644 +index 0000000..2d773bd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip_reg.h +@@ -0,0 +1,127 @@ ++#ifndef __SAA716x_VIP_REG_H ++#define __SAA716x_VIP_REG_H ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++#endif /* __SAA716x_VIP_REG_H */ +diff --git a/drivers/media/dvb-frontends/ds3103.h b/drivers/media/dvb-frontends/ds3103.h +new file mode 100644 +index 0000000..e52740c +--- /dev/null ++++ b/drivers/media/dvb-frontends/ds3103.h +@@ -0,0 +1,47 @@ ++/* ++ Montage Technology DS3103 - DVBS/S2 Demodulator driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef DS3103_H ++#define DS3103_H ++ ++#include ++ ++struct ds3103_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++ u8 ci_mode; ++ /* Set device param to start dma */ ++ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); ++}; ++ ++#if defined(CONFIG_DVB_DS3103) || \ ++ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline ++struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_DS3103 */ ++#endif /* DS3103_H */ +diff --git a/drivers/media/dvb-frontends/ts2022.h b/drivers/media/dvb-frontends/ts2022.h +new file mode 100644 +index 0000000..c894edb +--- /dev/null ++++ b/drivers/media/dvb-frontends/ts2022.h +@@ -0,0 +1,51 @@ ++ /* ++ Driver for Montage TS2022 DVBS/S2 Silicon tuner ++ ++ Copyright (C) 2012 Tomazzo Muzumici ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++ */ ++ ++#ifndef __DVB_TS2022_H__ ++#define __DVB_TS2022_H__ ++ ++#include ++#include "dvb_frontend.h" ++ ++/** ++ * Attach a ts2022 tuner to the supplied frontend structure. ++ * ++ * @param fe Frontend to attach to. ++ * @param addr i2c address of the tuner. ++ * @param i2c i2c adapter to use. ++ * @return FE pointer on success, NULL on failure. ++ */ ++#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ ++ && defined(MODULE)) ++extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, ++ int addr, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_TS2022 */ ++ ++#endif /* __DVB_TS2022_H__ */ +diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h +index 880e684..edd728c 100644 +--- a/include/uapi/linux/dvb/osd.h ++++ b/include/uapi/linux/dvb/osd.h +@@ -141,4 +141,20 @@ typedef struct osd_cap_s { + #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) + #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) + ++typedef struct osd_raw_cmd_s { ++ const void __user *cmd_data; ++ int cmd_len; ++ void __user *result_data; ++ int result_len; ++} osd_raw_cmd_t; ++ ++typedef struct osd_raw_data_s { ++ const void __user *data_buffer; ++ int data_length; ++ int data_handle; ++} osd_raw_data_t; ++ ++#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) ++#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) ++ + #endif diff --git a/packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch b/packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch new file mode 100644 index 0000000000..4fe58e69b3 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch @@ -0,0 +1,83 @@ +From 56ca3555ed8e0f5fd741477fd23497f5455c3f53 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 22 Apr 2014 15:58:50 +0300 +Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and after close() + +adapted to 3.15 + +From a6024295fd3290a8c9c5519a03316081ee82378a Mon Sep 17 00:00:00 2001 +From: Anssi Hannula +Date: Sat, 16 Feb 2013 17:42:46 +0200 +Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and + after close() + +Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) start +transmitting an empty audio stream as soon as PIN_OUT and AC_DIG1_ENABLE +are enabled. + +Since commit 6169b673618bf0b2518ce413b54925782a603f06 ("ALSA: hda - +Always turn on pins for HDMI/DP") this happens at first open() time, and +will continue even after close(). + +Additionally, some codecs (at least Intel PantherPoint HDMI) currently +continue transmitting HDMI audio even after close() in case some actual +audio was output after open() (this happens regardless of PIN_OUT). + +Empty HDMI audio transmission when not intended has the effect that a +possible HDMI audio sink/receiver may prefer the empty HDMI audio stream +over an actual audio stream on its S/PDIF inputs. + +To avoid the issue before first prepare(), set stream format to 0 on +codec initialization. 0 is not a valid format value for HDMI and will +prevent the audio stream from being output. + +Additionally, at close() time, make sure that the stream is cleaned up. +This will ensure that the format is reset to 0 at that time, preventing +audio from being output in that case. + +Thanks to OpenELEC developers and users for their help in investigating +this issue on the affected NVIDIA "ION2" hardware. Testing of the final +version on NVIDIA ION2 was done by OpenELEC user "MrXIII". Testing on +Intel PantherPoint was done by myself. + +Signed-off-by: Anssi Hannula +Cc: stable@vger.kernel.org +--- + sound/pci/hda/patch_hdmi.c | 14 ++++++++++++++ + 1 files changed, 14 insertions(+), 0 deletions(-) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 0cb5b89..e92f24f 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1698,6 +1698,14 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + if (err < 0) + return err; + ++ /* ++ * Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) ++ * start transmitting an empty audio stream as soon as PIN_OUT and ++ * AC_DIG1_ENABLE are enabled, which happens at open() time. ++ * To avoid that, set format to 0, which is not valid for HDMI. ++ */ ++ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); ++ + if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) + spec->cvt_nids[spec->num_cvts] = cvt_nid; + spec->num_cvts++; +@@ -1823,6 +1831,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, + int pinctl; + + if (hinfo->nid) { ++ /* ++ * Make sure no empty audio is output after this point by ++ * setting stream format to 0, which is not valid for HDMI. ++ */ ++ __snd_hda_codec_cleanup_stream(codec, hinfo->nid, 1); ++ + cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); + if (snd_BUG_ON(cvt_idx < 0)) + return -EINVAL; +-- +1.7.2.5 + diff --git a/packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch new file mode 100644 index 0000000000..41d0f1d9d2 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch @@ -0,0 +1,1577 @@ +http://patchwork.linuxtv.org/patch/10575/ +modified for 3.7.10 + +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400 +@@ -91,6 +91,8 @@ + int feedcount; + int pid_filtering; + int fullts_streaming_state; ++ /* the stream will be activated by an externally (by the fe for example) */ ++ int need_external_stream_control; + + /* bus specific callbacks */ + flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, +@@ -177,6 +179,8 @@ + struct dvb_demux_feed *dvbdmxfeed, int onoff); + void flexcop_hw_filter_init(struct flexcop_device *fc); + ++extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff); ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); + + void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400 +@@ -12,6 +12,7 @@ + #include "cx24113.h" + #include "cx24123.h" + #include "isl6421.h" ++#include "cx24120.h" + #include "mt352.h" + #include "bcm3510.h" + #include "nxt200x.h" +@@ -26,6 +27,15 @@ + #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ + (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) + ++#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120) ++static int flexcop_fe_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, char* name) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ return request_firmware(fw, name, fc->dev); ++} ++#endif ++ + /* lnb control */ + #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) + static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +@@ -445,13 +455,6 @@ + + /* AirStar ATSC 1st generation */ + #if FE_SUPPORTED(BCM3510) +-static int flexcop_fe_request_firmware(struct dvb_frontend *fe, +- const struct firmware **fw, char* name) +-{ +- struct flexcop_device *fc = fe->dvb->priv; +- return request_firmware(fw, name, fc->dev); +-} +- + static struct bcm3510_config air2pc_atsc_first_gen_config = { + .demod_address = 0x0f, + .request_firmware = flexcop_fe_request_firmware, +@@ -619,10 +622,40 @@ + #define cablestar2_attach NULL + #endif + ++/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */ ++#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421) ++static const struct cx24120_config skystar2_rev3_3_cx24120_config = { ++ .i2c_addr = 0x55, ++ .request_firmware = flexcop_fe_request_firmware, ++}; ++ ++static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) ++{ ++// struct dvb_frontend_ops *ops; ++ ++ fc->fe = dvb_attach(cx24120_attach, ++ &skystar2_rev3_3_cx24120_config, i2c); ++ if (fc->fe == NULL) return 0; ++ fc->dev_type = FC_SKYS2_REV33; ++ fc->fc_i2c_adap[2].no_base_addr = 1; ++ if ( (dvb_attach(isl6421_attach, fc->fe, ++ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0, false) == NULL) ) { ++ err("ISL6421 could NOT be attached!"); ++ return 0; ++ } ++ info("ISL6421 successfully attached."); ++// ops = &fc->fe->ops; ++ return 1; ++} ++#else ++#define skystarS2_rev33_attach NULL ++#endif ++ + static struct { + flexcop_device_type_t type; + int (*attach)(struct flexcop_device *, struct i2c_adapter *); + } flexcop_frontends[] = { ++ { FC_SKYS2_REV33, skystarS2_rev33_attach }, + { FC_SKY_REV27, skystar2_rev27_attach }, + { FC_SKY_REV28, skystar2_rev28_attach }, + { FC_SKY_REV26, skystar2_rev26_attach }, +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400 +@@ -11,6 +11,12 @@ + deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); + } + ++void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ flexcop_rcv_data_ctrl(fc, onoff); ++} ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) + { + flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); +@@ -199,6 +205,7 @@ + + /* if it was the first or last feed request change the stream-status */ + if (fc->feedcount == onoff) { ++ if (!fc->need_external_stream_control) + flexcop_rcv_data_ctrl(fc, onoff); + if (fc->stream_control) /* device specific stream control */ + fc->stream_control(fc, onoff); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400 +@@ -56,6 +56,7 @@ + [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", + [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", + [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", ++ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3", + }; + + static const char *flexcop_bus_names[] = { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400 +@@ -24,6 +24,7 @@ + FC_SKY_REV26, + FC_SKY_REV27, + FC_SKY_REV28, ++ FC_SKYS2_REV33, + } flexcop_device_type_t; + + typedef enum { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig +--- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -3,6 +3,7 @@ + depends on DVB_CORE && I2C + depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB + default y ++ select DVB_CX24120 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400 +@@ -0,0 +1,1053 @@ ++/* ++ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver ++ Version 0.0.4a 03.04.2012 ++ ++ Copyright (C) 2009 Sergey Tyurin ++ Updated 2012 by Jannis Achstetter ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "cx24120.h" ++#include "cx24120_const.h" ++ ++//========================== ++#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \ ++ printk(args); } } while (0) ++#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \ ++ printk(args); } while (0) ++#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \ ++ printk(args); } while (0) ++//========================== ++ ++static int cx24120_debug=0; ++static int reg_debug=0; ++MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware"); ++module_param(cx24120_debug, int, 0644); ++MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)"); ++ ++// ############################## ++struct cx24120_state { ++ struct i2c_adapter *i2c; ++ const struct cx24120_config *config; ++ struct dvb_frontend frontend; ++ u8 need_set_mpeg_out; ++ u8 attached; ++ u8 dvb_s2_mode; ++ u8 cold_init; ++}; ++// ##################################### ++// #### Command message to firmware #### ++struct cx24120_cmd { // total size = 36 ++ u8 id; // [00] - message id ++ u8 arg[30]; // [04] - message first byte ++ u8 len; // [34] - message lengh or first registers to read ++ u8 reg; // [35] - number of registers to read ++}; ++ ++//=================================================================== ++static int cx24120_readreg(struct cx24120_state *state, u8 reg) ++{ ++ int ret; ++ u8 buf = 0; ++ struct i2c_msg msg[] = { ++ { .addr = state->config->i2c_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = ® }, ++ ++ { .addr = state->config->i2c_addr, ++ .flags = I2C_M_RD, ++ .len = 1, ++ .buf = &buf } ++ }; ++ ret = i2c_transfer(state->i2c, msg, 2); ++ if (ret != 2) { ++ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf); ++ return buf; ++} // end cx24120_readreg ++//=================================================================== ++static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = 2 }; ++ int ret; ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data); ++ return 0; ++} // end cx24120_writereg ++//=================================================================== ++static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr) ++{ ++ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */ ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = len }; ++ int ret; ++ ++ do { ++ buf[0] = reg; ++ msg.len = len > 4 ? 4 : len; ++ memcpy(&buf[1], values, msg.len); ++ len -= msg.len; // data length revers counter ++ values += msg.len; // incr data pointer ++ if (incr) reg += msg.len; ++ msg.len++; /* don't forget the addr byte */ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); ++ return ret; ++ } ++ if (reg_debug) { ++ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages ++ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug ++ reg, buf[1], buf[2], buf[3], buf[4]); ++ } ++ } ++ } while (len); ++ return 0; ++} // end cx24120_writeregN ++//=================================================================== ++static struct dvb_frontend_ops cx24120_ops; ++//=================================================================== ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c) ++{ ++ struct cx24120_state *state = NULL; ++ int demod_rev; ++ ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n"); ++ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n"); ++ state = kzalloc(sizeof(struct cx24120_state), ++ GFP_KERNEL); ++ if (state == NULL) { ++ err("### Unable to allocate memory for cx24120_state structure. :(\n"); ++ goto error; ++ } ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ /* check if the demod is present and has proper type */ ++ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION); ++ switch (demod_rev) { ++ case 0x07: ++ info("Demod CX24120 rev. 0x07 detected.\n"); ++ break; ++ case 0x05: ++ info("Demod CX24120 rev. 0x05 detected.\n"); ++ break; ++ default: ++ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev); ++ goto error; ++ } ++ /* create dvb_frontend */ ++ state->attached = 0x10; // set attached flag ++ state->cold_init=0; ++ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n"); ++ return &state->frontend; ++ ++error: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach ++//=================================================================== ++static int cx24120_test_rom(struct cx24120_state *state) ++{ ++ int err, ret; ++ err = cx24120_readreg(state, 0xFD); ++ if (err & 4 ) ++ { ++ ret = cx24120_readreg(state, 0xDF) & 0xFE; ++ err = cx24120_writereg(state, 0xDF, ret); ++ } ++ return err; ++} // end cx24120_test_rom ++//=================================================================== ++static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) | ++ (cx24120_readreg(state, CX24120_REG_QUALITY_L)); ++ dbginfo("read SNR index = %d\n", *snr); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr ++//=================================================================== ++static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word ++ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word ++ dbginfo("read BER index = %d\n", *ber); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd); ++//=================================================================== ++static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag) ++{ ++ u8 tristate; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ??? ++ cmd.arg[0] = 1; ++ cmd.arg[1] = 0; ++ tristate = flag ? 0 : (u8)(-1); ++ cmd.arg[2] = tristate; ++ cmd.arg[3] = 1; ++ cmd.len = 4; ++ ++ if(flag) dbginfo("MPEG output DISABLED\n"); ++ else dbginfo("MPEG output ENABLED\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_global_config ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd) ++{ ++ u8 xxzz; ++ u32 msg_cmd_mask; ++ int ret, ficus; ++ ++ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled? ++ // if yes: ++ xxzz = cmd->id - 0x11; // look for specific message id ++ if ( xxzz <= 0x13 ) { ++ msg_cmd_mask = 1 << xxzz; ++ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output ++ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b ++ cx24120_msg_mpeg_output_global_config(state, 0); ++ msleep(100); ++ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag ++ } ++ } ++ } ++ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target ++ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data ++ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end ++ ++ ficus = 1000; ++ while ( cx24120_readreg(state, 0x1F)) { // is command done??? ++ msleep(1); ++ if( !(--ficus)) { ++ err("Too long waiting 'done' state from reg(0x1F). :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ dbginfo("Successfully send message 0x%02x\n", cmd->id); ++ ++ if ( cmd->reg > 30 ) { ++ err("Too much registers to read. cmd->reg = %d", cmd->reg); ++ return -EREMOTEIO; ++ } ++ ficus = 0; ++ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read ++ while ( ficus < cmd->reg ){ // starts from reg No cmd->len ++ // number of registers to read is cmd->reg ++ // and write results starts from cmd->arg[0]. ++ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1)); ++ ++ficus; ++ } ++ } ++ return 0; ++} // end cx24120_message_send ++//=================================================================== ++static int cx24120_set_frontend(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u32 srate, freq; ++ fe_code_rate_t fec; ++ fe_spectral_inversion_t inversion; ++ u8 smbr1, smbr2; ++ int ret; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs ++ cmd.len = 15; ++ ++ freq = p->frequency; ++ srate = p->symbol_rate; ++ fec = p->fec_inner; ++ inversion = p->inversion; ++ ++ // check symbol rate ++ if ( srate > 31000000 ) { // if symbol rate > 31 000 ++ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp ++ smbr2 = (-(srate < 31000001) & 6) + 4; // edi ++ } else { ++ smbr1 = 3; ++ smbr2 = 6; ++ } ++ ++ ret = cx24120_writereg(state, 0xE6, smbr1); ++ ret = cx24120_readreg(state, 0xF0); ++ ret &= 0xFFFFFFF0; ++ ret |= smbr2; ++ ret = cx24120_writereg(state, 0xF0, ret); ++ ++ cmd.arg[0] = 0; // CMD_TUNER_REQUEST ++ ++ // Frequency ++ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */ ++ cmd.arg[2] = (freq & 0x00FF00) >> 8; ++ cmd.arg[3] = (freq & 0x0000FF); ++ ++ // Symbol Rate ++ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8; ++ cmd.arg[5] = ((srate/1000) & 0x00FF); ++ ++ // Inversion ++ if ( inversion ) { ++ if ( inversion == 1 ) cmd.arg[6] = 4; ++ else cmd.arg[6] = 0x0C; ++ } else { ++ cmd.arg[6] = 0; ++ } ++ ++ // FEC ++ switch ( fec ) // fec = p->u.qpsk.fec_inner ++ { ++ case 1: // FEC_1_2 ++ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset ++ case 2: // FEC_2_3 ++ cmd.arg[7] = 0x2F; break; ++ case 3: // FEC_3_4 ++ cmd.arg[7] = 0x30; break; ++ case 5: // FEC_5_6 ++ cmd.arg[7] = 0x31; break; ++ case 7: // FEC_7_8 ++ cmd.arg[7] = 0x32; break; ++ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9, ++ // FEC_AUTO, FEC_3_5, FEC_9_10 ++ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode ++ cmd.arg[7] = 0; ++ cmd.arg[11] = 0; ++ } else { ++ cmd.arg[7] = 0x2E; ++ cmd.arg[11] = 0xAC; ++ } ++ break; ++ } ++ cmd.arg[8] = 0x13; ++ cmd.arg[9] = 0x88; ++ cmd.arg[10] = 0; ++ cmd.arg[12] = smbr2; ++ cmd.arg[13] = smbr1; ++ cmd.arg[14] = 0; ++ ++ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ????? ++ ++ return cx24120_message_send(state, &cmd); ++ ++} ++EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend ++//=================================================================== ++void cx24120_message_fill(struct cx24120_cmd *cmd, ++ u8 msg_id, ++ u8 *msg_addr, ++ u8 msg_len, ++ u8 num_regs) ++{ ++ cmd->id = msg_id; ++ memcpy(&cmd->arg[0], msg_addr, msg_len); ++ cmd->len = msg_len; ++ cmd->reg = num_regs; ++} // end cx24120_message_fill ++//=================================================================== ++static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int result, sigstr_h, sigstr_l; ++ ++ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/); ++ ++ if( !(cx24120_message_send(state, &cmd)) ) { ++ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8; ++ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L ); ++ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l)); ++ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF; ++ dbginfo("Signal strength= 0x%x\n", *signal_strength); ++ result = 0; ++ } else { ++ err("error reading signal strength\n"); ++ result = -EREMOTEIO; ++ } ++ return result; ++} ++EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength ++//=================================================================== ++static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num, ++ struct cx24120_skystar2_mpeg_config *config_msg) ++{ ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id ++ cmd.len = 7; ++ cmd.arg[0] = num; // sequental number - can be 0,1,2 ++ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) | ++ ((config_msg->x1 >> 1) & 0x01); ++ cmd.arg[2] = 0x05; ++ cmd.arg[3] = 0x02; ++ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01); ++ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F); ++ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */ ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_config ++//=================================================================== ++static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_BURST; ++ cmd.arg[0] = 0x00; ++ if (burst) ++ cmd.arg[1] = 0x01; ++ dbginfo("burst sent.\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst ++//=================================================================== ++static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ dbginfo("cmd(0x23,4) - tone = %d\n", tone); ++ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { ++ err("Invalid tone=%d\n", tone); ++ return -EINVAL; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETTONE; // 0x23 ++ cmd.len = 4; ++ if (!tone) ++ cmd.arg[3] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone ++//=================================================================== ++static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETVOLTAGE; // ++ cmd.len = 2; ++ if (!(voltage - 1)) ++ cmd.arg[1] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage ++//=================================================================== ++static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int back_count; ++ ++ dbginfo("Start sending diseqc sequence===============\n"); ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_MSG1; // 0x20 ++ cmd.len = 11; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x03; ++ cmd.arg[3] = 0x16; ++ cmd.arg[4] = 0x28; ++ cmd.arg[5] = 0x01; ++ cmd.arg[6] = 0x01; ++ cmd.arg[7] = 0x14; ++ cmd.arg[8] = 0x19; ++ cmd.arg[9] = 0x14; ++ cmd.arg[10] = 0x1E; ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 1st message(0x%x) filed==========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ cmd.id = CMD_DISEQC_MSG2; // 0x21 ++ cmd.len = d->msg_len + 6; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x01; ++ cmd.arg[2] = 0x02; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x00; ++ cmd.arg[5] = d->msg_len; ++ ++ memcpy(&cmd.arg[6], &d->msg, d->msg_len); ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 2d message(0x%x) filed========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ back_count = 100; ++ do { ++ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) { ++ dbginfo("diseqc sequence sent success==========.\n"); ++ return 0; ++ } ++ msleep(5); ++ --back_count; ++ } while ( back_count ); ++ err("Too long waiting for diseqc.=============\n"); ++ return -ETIMEDOUT; ++} ++EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg ++//=================================================================== ++static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int ret, clock_seq_num, GettedFEC; ++ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id; ++ ++ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A ++ dbginfo("status = 0x%x\n", ret); ++ *status = 0; ++ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL; ++ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER; ++ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC); ++ ++ if ( ret & CX24120_HAS_LOCK ) { // 0x08 ++ *status |= FE_HAS_LOCK; ++ if ( state->need_set_mpeg_out & 1 ) { // just tuned??? ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_CLOCK_READ; ++ cmd.arg[0] = 0x00; ++ cmd.len = 1; // cmd.reg != 0, so it is first register to read ++ cmd.reg = 6; // number of registers to read (0x01-0x06) ++ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result ++ // 0x02-0x07 ++ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14 ++ GettedFEC = ret; // 0x0d= 13 ++ dbginfo("Get FEC: %d\n", ret); ++ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2? ++ switch (ret-4) { ++ case 0: ++ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only ++ case 1: ++ case 8: ++ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only ++ case 2: ++ case 9: ++ mode_code = 0x02; goto mode_8PSK; // FEC_2_3 ++ case 3: ++ case 10: ++ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+ ++ case 4: ++ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only ++ case 5: ++ case 11: ++ mode_code = 0x05; goto mode_8PSK; // FEC_5_6 ++ case 6: ++ case 12: ++ mode_code = 0x08; goto mode_8PSK; // FEC_8_9 ++ case 7: ++ case 13: ++ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only ++ default: ++ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4); ++ mode_code = 0x01; // set like for mode 0 ++ mode_8PSK: ++ if ( ret > 11 ) { // 14 ++ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag ++ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code); ++ } else { ++ mode_QPSK: ++ mode_8PSK_flag = 0x00; ++ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4); ++ } ++ break; ++ } // end switch ++ } // end if dvb_s2_mode // dvb-s2 ++ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S ++ switch ( ret - 2 ) { ++ case 0: ++ mode_code = 2; break; // FEC_2_3 ++ case 1: ++ mode_code = 3; break; // FEC_3_4 ++ case 2: ++ mode_code = 4; break; // FEC_4_5 ++ case 3: ++ mode_code = 5; break; // FEC_5_6 ++ case 4: ++ mode_code = 6; break; // FEC_6_7 ++ case 5: ++ mode_code = 7; break; // FEC_7_8 ++ default: ++ mode_code = 1;break; // FEC_1_2 ++ } ++ mode_8PSK_flag = 0; ++ } // end of switch for dvb-s ++ ++ attached_flag = 0x10; ++ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner ++ attached_flag = 0; ++ ret = 0; ++ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2 ++ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ??? ++ // bit 4 bit 5 bit 0 bit 3 ++ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible, ++ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag ++ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5 ++ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n", ++ clock_id, mode_8PSK_flag, mode_code); ++ ++ clock_seq_num = 0; ++ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) || ++ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) || ++ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) ) ++ { ++ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num, ++ * clock_ratios_table[clock_seq_num].ratio_id, ++ * clock_ratios_table[clock_seq_num].mode_xPSK, ++ * clock_ratios_table[clock_seq_num].fec_mode); ++ */ ++ ++clock_seq_num; ++ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) { ++ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n"); ++ goto settings_end; ++ } ++ } ++ //############################### ++ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n", ++ GettedFEC, ++ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early ++ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16 ++ clock_seq_num, ++ clock_ratios_table[clock_seq_num].m_rat, ++ clock_ratios_table[clock_seq_num].n_rat, ++ clock_ratios_table[clock_seq_num].rate); ++ //############################### ++ cmd.id = CMD_CLOCK_SET; ++ cmd.len = 10; ++ cmd.reg = 0; ++ cmd.arg[0] = 0; ++ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner ++ ++ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF; ++ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF; ++ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF; ++ ++ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF; ++ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF; ++ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF; ++ ++ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF; ++ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF; ++ ++ cx24120_message_send(state, &cmd); ++ ++ settings_end: ++ msleep(200); ++ cx24120_msg_mpeg_output_global_config(state, 1); ++ state->dvb_s2_mode |= 0x02; // set mpeg flag ++ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag ++ } ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status ++//=================================================================== ++int cx24120_init(struct dvb_frontend *fe) ++{ ++ const struct firmware *fw; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u8 ret, ret_EA, reg1, fL, fH; ++ u32 vco, xtal_khz; ++ u64 inv_vco, res, xxyyzz; ++ int reset_result; ++ ++ if( state->cold_init ) return 0; ++ ++ ret = cx24120_writereg(state, 0xEA, 0x00); ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_readreg(state, 0xFC) & 0xFE; ++ ret = cx24120_writereg(state, 0xFC, ret); ++ ret = cx24120_writereg(state, 0xC3, 0x04); ++ ret = cx24120_writereg(state, 0xC4, 0x04); ++ ret = cx24120_writereg(state, 0xCE, 0x00); ++ ret = cx24120_writereg(state, 0xCF, 0x00); ++ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE; ++ ret = cx24120_writereg(state, 0xEA, ret_EA); ++ ret = cx24120_writereg(state, 0xEB, 0x0C); ++ ret = cx24120_writereg(state, 0xEC, 0x06); ++ ret = cx24120_writereg(state, 0xED, 0x05); ++ ret = cx24120_writereg(state, 0xEE, 0x03); ++ ret = cx24120_writereg(state, 0xEF, 0x05); ++ ret = cx24120_writereg(state, 0xF3, 0x03); ++ ret = cx24120_writereg(state, 0xF4, 0x44); ++ ++ reg1 = 0xF0; ++ do { ++ cx24120_writereg(state, reg1, 0x04); ++ cx24120_writereg(state, reg1 - 10, 0x02); ++ ++reg1; ++ } while ( reg1 != 0xF3 ); ++ ++ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01)); ++ reg1 = 0xC5; ++ do { ++ ret = cx24120_writereg(state, reg1, 0x00); ++ ret = cx24120_writereg(state, reg1 + 1, 0x00); ++ reg1 += 2; ++ } while ( reg1 != 0xCB ); ++ ++ ret = cx24120_writereg(state, 0xE4, 0x03); ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ ++ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE); ++ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE); ++ if (ret) { ++ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret); ++ return ret; ++ } ++ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n", ++ (int)fw->size, // firmware_size in bytes u32* ++ fw->data[0], // fw 1st byte ++ fw->data[1], // fw 2d byte ++ fw->data[fw->size - 2], // fw before last byte ++ fw->data[fw->size - 1]); // fw last byte ++ ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_writereg(state, 0xE0, 0x76); ++ ret = cx24120_writereg(state, 0xF7, 0x81); ++ ret = cx24120_writereg(state, 0xF8, 0x00); ++ ret = cx24120_writereg(state, 0xF9, 0x00); ++ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00); ++ ret = cx24120_writereg(state, 0xF7, 0xC0); ++ ret = cx24120_writereg(state, 0xE0, 0x00); ++ ret = (fw->size - 2) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a ++ ret = ((fw->size - 2) >> 8) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf ++ ret = cx24120_writereg(state, 0xF7, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x07); ++ msleep(500); ++ ++ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware ++ if ( ret == fw->data[fw->size - 1] ) { ++ dbginfo("Firmware uploaded successfully\n"); ++ reset_result = 0; ++ } else { ++ err("Firmware upload failed. Last byte returned=0x%x\n", ret ); ++ reset_result = -EREMOTEIO; ++ } ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ release_firmware(fw); ++ if (reset_result) ++ return reset_result; ++ ++ //================== Start tuner ++ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error tuner start! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_VCO_SET; // 0x10 ++ cmd.len = 12; ++ ++ // ###################### ++ // Calc VCO ++ xtal_khz = 10111; ++ xxyyzz = 0x400000000ULL; // 17179869184 ++ vco = xtal_khz * 10 * 4; // 404440 ++ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE ++ res = xxyyzz % vco; // 66864 = 0x010530 ++ ++ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco; ++ ++ fH = (inv_vco >> 8) & 0xFF; ++ fL = (inv_vco) & 0xFF; ++ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH); ++ // ###################### ++ ++ cmd.arg[0] = 0x06; ++ cmd.arg[1] = 0x2B; ++ cmd.arg[2] = 0xD8; ++ cmd.arg[3] = fH; // 0xA5 ++ cmd.arg[4] = fL; // 0xEE ++ cmd.arg[5] = 0x03; ++ cmd.arg[6] = 0x9D; ++ cmd.arg[7] = 0xFC; ++ cmd.arg[8] = 0x06; ++ cmd.arg[9] = 0x03; ++ cmd.arg[10] = 0x27; ++ cmd.arg[11] = 0x7F; ++ ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error set VCO! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ // set bandwidth ++ cmd.id = CMD_BANDWIDTH; // 0x15 ++ cmd.len = 12; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x00; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x05; ++ cmd.arg[5] = 0x02; ++ cmd.arg[6] = 0x02; ++ cmd.arg[7] = 0x00; ++ cmd.arg[8] = 0x05; ++ cmd.arg[9] = 0x02; ++ cmd.arg[10] = 0x02; ++ cmd.arg[11] = 0x00; ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("Error set bandwidth! :(\n"); ++ return -EREMOTEIO; ++ } ++ ret = cx24120_readreg(state, 0xBA); ++ if ( ret > 3) { ++ dbginfo("Reset-readreg 0xBA: %x\n", ret); ++ err("Error intitilizing tuner! :(\n"); ++ return -EREMOTEIO; ++ } ++ dbginfo("Tuner initialized correctly.\n"); ++ ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ if (cx24120_msg_mpeg_output_global_config(state, 0) || ++ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) ) ++ { ++ err("Error initilizing mpeg output. :(\n"); ++ return -EREMOTEIO; ++ } else { ++ cmd.id = 0x3C; // 60 ++ cmd.len = 0x03; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x10; ++ cmd.arg[2] = 0x10; ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error sending final init message. :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ state->cold_init=1; ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_init); // end cx24120_reset ++//=================================================================== ++static int cx24120_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ int delay_cnt, sd_idx = 0; ++ fe_status_t status; ++ ++ if (re_tune) { ++ ++// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n", ++// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate); ++ ++ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) { ++ ++sd_idx; ++ } ++ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay); ++ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2 ++ dbginfo("trying DVB-S =================\n"); ++ cx24120_set_frontend(fe); ++ ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S =================\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S LOCKED================\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S =================\n"); ++ ++ cx24120_read_status(fe, &status); ++ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S ++ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n"); ++ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ? ++ p->fec_inner = FEC_AUTO; ++ cx24120_set_frontend(fe); ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S2 LOCKED++++++++++++++++\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n"); ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune ++//=================================================================== ++static int cx24120_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++EXPORT_SYMBOL(cx24120_get_algo); ++//=================================================================== ++static int cx24120_sleep(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_sleep); ++//=================================================================== ++/*static int cx24120_wakeup(struct dvb_frontend *fe) ++ * { ++ * return 0; ++ * } ++ * EXPORT_SYMBOL(cx24120_wakeup); ++ */ ++//=================================================================== ++static int cx24120_get_frontend(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_get_frontend); ++//=================================================================== ++static void cx24120_release(struct dvb_frontend *fe) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ dbginfo("Clear state structure\n"); ++ kfree(state); ++} ++EXPORT_SYMBOL(cx24120_release); ++//=================================================================== ++static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) | ++ cx24120_readreg(state, CX24120_REG_UCB_L); ++ dbginfo("Blocks = %d\n", *ucblocks); ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ucblocks); ++// ######################################################################################## ++static struct dvb_frontend_ops cx24120_ops = { ++ ++ .delsys = { SYS_DVBS2 }, ++ .info = { ++ .name = "Conexant CX24120/CX24118", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = // 0x500006ff ++ FE_CAN_INVERSION_AUTO | //0x00 000 001 ++ FE_CAN_FEC_1_2 | //0x00 000 002 ++ FE_CAN_FEC_2_3 | //0x00 000 004 ++ FE_CAN_FEC_3_4 | //0x00 000 008 ++ FE_CAN_FEC_4_5 | //0x00 000 010 ++ FE_CAN_FEC_5_6 | //0x00 000 020 ++ FE_CAN_FEC_6_7 | //0x00 000 040 ++ FE_CAN_FEC_7_8 | //0x00 000 080 ++ FE_CAN_FEC_AUTO | //0x00 000 200 ++ FE_CAN_QPSK | //0x00 000 400 ++//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */ ++ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */ ++ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */ ++ }, //sum=50 000 6FF ++ .release = cx24120_release, ++ ++ .init = cx24120_init, ++ .sleep = cx24120_sleep, ++ ++ .tune = cx24120_tune, ++ .get_frontend_algo = cx24120_get_algo, ++ .set_frontend = cx24120_set_frontend, ++ ++ .get_frontend = cx24120_get_frontend, ++ .read_status = cx24120_read_status, ++ .read_ber = cx24120_read_ber, ++ .read_signal_strength = cx24120_read_signal_strength, ++ .read_snr = cx24120_read_snr, ++ .read_ucblocks = cx24120_read_ucblocks, ++ ++ .diseqc_send_master_cmd = cx24120_send_diseqc_msg, ++ ++ .diseqc_send_burst = cx24120_diseqc_send_burst, ++ .set_tone = cx24120_set_tone, ++ .set_voltage = cx24120_set_voltage, ++}; ++//=================================================================== ++MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)"); ++MODULE_AUTHOR("Sergey Tyurin"); ++MODULE_LICENSE("GPL"); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400 +@@ -0,0 +1,259 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * DVBS/S2 Satellite demod/tuner driver static definitins ++ * ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw" ++ ++// ############################## ++// ### cx24120 i2c registers ### ++#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register: ++#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc. ++#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result ++ ++#define CX24120_REG_FECMODE (0x39) // FEC status ++#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ... ++#define CX24120_REG_QUALITY_H (0x40) // SNR high byte ++#define CX24120_REG_QUALITY_L (0x41) // SNR low byte ++ ++#define CX24120_REG_BER_HH (0x47) // BER high byte of high word ++#define CX24120_REG_BER_HL (0x48) // BER low byte of high word ++#define CX24120_REG_BER_LH (0x49) // BER high byte of low word ++#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word ++ ++#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ??? ++#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte ++ ++#define CX24120_REG_UCB_H (0x50) // UCB high byte ++#define CX24120_REG_UCB_L (0x51) // UCB low byte ++ ++#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5 ++ ++// ############################## ++/* Command messages */ ++enum command_message_id { ++ CMD_VCO_SET = 0x10, // cmdlen = 12; ++ CMD_TUNEREQUEST = 0x11, // cmd.len = 15; ++ ++ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4; ++ CMD_MPEG_INIT = 0x14, // cmd.len = 7; ++ CMD_BANDWIDTH = 0x15, // cmd.len = 12; ++ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06 ++ CMD_CLOCK_SET = 0x17, // cmd.len = 10; ++ ++ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11; ++ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6; ++ CMD_SETVOLTAGE = 0x22, // cmd.len = 2; ++ CMD_SETTONE = 0x23, // cmd.len = 4; ++ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!! ++ ++ CMD_READ_SNR = 0x1A, // Read signal strength ++ CMD_START_TUNER = 0x1B, // ??? ++ ++ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03; ++}; ++// ############################## ++/* signal status */ ++#define CX24120_HAS_SIGNAL (0x01) ++#define CX24120_HAS_CARRIER (0x02) ++#define CX24120_HAS_VITERBI (0x04) ++#define CX24120_HAS_LOCK (0x08) ++#define CX24120_HAS_UNK1 (0x10) ++#define CX24120_HAS_UNK2 (0x20) ++#define CX24120_STATUS_MASK (0x0f) ++#define CX24120_SIGNAL_MASK (0xc0) ++ ++static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 }; ++static u8 cx24120_msg_read_sigstr[] = {0,0}; ++ ++static struct cx24120_skystar2_mpeg_config { ++ u8 x1; ++ u8 x2; ++ u8 x3; ++} initial_mpeg_config = { ++ 0xA1, // 10100001 ++ 0x76, // 01110110 ++ 0x07, // 00000111 ++}; ++ ++static struct cx24120_symrate_delay { ++ u32 symrate; ++ u32 delay; ++} symrates_pairs[] = { ++ { 3000000, 15000 }, ++ { 6000000, 10000 }, ++ { 8000000, 5000 }, ++ { 10000000, 2000 }, ++ {0x0FFFFFFFF, 400 }, ++}; ++ ++static struct cx24120_clock_ratios_table { ++ u32 ratio_id; ++ u32 mode_xPSK; ++ u32 fec_mode; ++ u32 m_rat; ++ u32 n_rat; ++ u32 rate; ++} clock_ratios_table[] = { ++{ 21 , 0 , 1 , 770068 , 763515 , 258 }, ++{ 21 , 0 , 100 , 97409 , 80370 , 310 }, ++{ 21 , 0 , 2 , 137293 , 101802 , 345 }, ++{ 21 , 0 , 3 , 4633447 , 3054060 , 388 }, ++{ 21 , 0 , 4 , 2472041 , 1527030 , 414 }, ++{ 21 , 0 , 5 , 85904 , 50901 , 432 }, ++{ 21 , 0 , 8 , 2751229 , 1527030 , 461 }, ++{ 21 , 0 , 101 , 1392872 , 763515 , 467 }, ++{ 21 , 99 , 100 , 1850771 , 1019430 , 464 }, ++{ 21 , 99 , 2 , 137293 , 67962 , 517 }, ++{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 21 , 99 , 5 , 85904 , 33981 , 647 }, ++{ 21 , 99 , 8 , 2751229 , 1019430 , 690 }, ++{ 21 , 99 , 101 , 1392872 , 509715 , 699 }, ++{ 29 , 0 , 1 , 770068 , 782127 , 252 }, ++{ 29 , 0 , 100 , 1850771 , 1564254 , 302 }, ++{ 29 , 0 , 2 , 686465 , 521418 , 337 }, ++{ 29 , 0 , 3 , 4633447 , 3128508 , 379 }, ++{ 29 , 0 , 4 , 2472041 , 1564254 , 404 }, ++{ 29 , 0 , 5 , 429520 , 260709 , 421 }, ++{ 29 , 0 , 8 , 2751229 , 1564254 , 450 }, ++{ 29 , 0 , 101 , 1392872 , 782127 , 455 }, ++{ 29 , 99 , 100 , 1850771 , 1043118 , 454 }, ++{ 29 , 99 , 2 , 686465 , 347706 , 505 }, ++{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 29 , 99 , 5 , 429520 , 173853 , 632 }, ++{ 29 , 99 , 8 , 2751229 , 1043118 , 675 }, ++{ 29 , 99 , 101 , 1392872 , 521559 , 683 }, ++{ 17 , 0 , 1 , 766052 , 763515 , 256 }, ++{ 17 , 0 , 100 , 96901 , 80370 , 308 }, ++{ 17 , 0 , 2 , 136577 , 101802 , 343 }, ++{ 17 , 0 , 3 , 4609283 , 3054060 , 386 }, ++{ 17 , 0 , 4 , 2459149 , 1527030 , 412 }, ++{ 17 , 0 , 5 , 85456 , 50901 , 429 }, ++{ 17 , 0 , 8 , 2736881 , 1527030 , 458 }, ++{ 17 , 0 , 101 , 1385608 , 763515 , 464 }, ++{ 17 , 99 , 100 , 1841119 , 1019430 , 462 }, ++{ 17 , 99 , 2 , 136577 , 67962 , 514 }, ++{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 17 , 99 , 5 , 85456 , 33981 , 643 }, ++{ 17 , 99 , 8 , 2736881 , 1019430 , 687 }, ++{ 17 , 99 , 101 , 1385608 , 509715 , 695 }, ++{ 25 , 0 , 1 , 766052 , 782127 , 250 }, ++{ 25 , 0 , 100 , 1841119 , 1564254 , 301 }, ++{ 25 , 0 , 2 , 682885 , 521418 , 335 }, ++{ 25 , 0 , 3 , 4609283 , 3128508 , 377 }, ++{ 25 , 0 , 4 , 2459149 , 1564254 , 402 }, ++{ 25 , 0 , 5 , 427280 , 260709 , 419 }, ++{ 25 , 0 , 8 , 2736881 , 1564254 , 447 }, ++{ 25 , 0 , 101 , 1385608 , 782127 , 453 }, ++{ 25 , 99 , 100 , 1841119 , 1043118 , 451 }, ++{ 25 , 99 , 2 , 682885 , 347706 , 502 }, ++{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 25 , 99 , 5 , 427280 , 173853 , 629 }, ++{ 25 , 99 , 8 , 2736881 , 1043118 , 671 }, ++{ 25 , 99 , 101 , 1385608 , 521559 , 680 }, ++{ 5 , 0 , 1 , 273088 , 254505 , 274 }, ++{ 5 , 0 , 100 , 17272 , 13395 , 330 }, ++{ 5 , 0 , 2 , 24344 , 16967 , 367 }, ++{ 5 , 0 , 3 , 410788 , 254505 , 413 }, ++{ 5 , 0 , 4 , 438328 , 254505 , 440 }, ++{ 5 , 0 , 5 , 30464 , 16967 , 459 }, ++{ 5 , 0 , 8 , 487832 , 254505 , 490 }, ++{ 5 , 0 , 101 , 493952 , 254505 , 496 }, ++{ 5 , 99 , 100 , 328168 , 169905 , 494 }, ++{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD ++{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 5 , 99 , 5 , 30464 , 11327 , 688 }, ++{ 5 , 99 , 8 , 487832 , 169905 , 735 }, ++{ 5 , 99 , 101 , 493952 , 169905 , 744 }, ++{ 13 , 0 , 1 , 273088 , 260709 , 268 }, ++{ 13 , 0 , 100 , 328168 , 260709 , 322 }, ++{ 13 , 0 , 2 , 121720 , 86903 , 358 }, ++{ 13 , 0 , 3 , 410788 , 260709 , 403 }, ++{ 13 , 0 , 4 , 438328 , 260709 , 430 }, ++{ 13 , 0 , 5 , 152320 , 86903 , 448 }, ++{ 13 , 0 , 8 , 487832 , 260709 , 479 }, ++{ 13 , 0 , 101 , 493952 , 260709 , 485 }, ++{ 13 , 99 , 100 , 328168 , 173853 , 483 }, ++{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk ++{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 13 , 99 , 5 , 152320 , 57951 , 672 }, ++{ 13 , 99 , 8 , 487832 , 173853 , 718 }, ++{ 13 , 99 , 101 , 493952 , 173853 , 727 }, ++{ 1 , 0 , 1 , 815248 , 763515 , 273 }, ++{ 1 , 0 , 100 , 51562 , 40185 , 328 }, ++{ 1 , 0 , 2 , 72674 , 50901 , 365 }, ++{ 1 , 0 , 3 , 1226323 , 763515 , 411 }, ++{ 1 , 0 , 4 , 1308538 , 763515 , 438 }, ++{ 1 , 0 , 5 , 90944 , 50901 , 457 }, ++{ 1 , 0 , 8 , 1456322 , 763515 , 488 }, ++{ 1 , 0 , 101 , 1474592 , 763515 , 494 }, ++{ 1 , 99 , 100 , 979678 , 509715 , 492 }, ++{ 1 , 99 , 2 , 72674 , 33981 , 547 }, ++{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2 ++{ 1 , 99 , 5 , 90944 , 33981 , 685 }, ++{ 1 , 99 , 8 , 1456322 , 509715 , 731 }, ++{ 1 , 99 , 101 , 1474592 , 509715 , 740 }, ++{ 9 , 0 , 1 , 815248 , 782127 , 266 }, ++{ 9 , 0 , 100 , 979678 , 782127 , 320 }, ++{ 9 , 0 , 2 , 363370 , 260709 , 356 }, ++{ 9 , 0 , 3 , 1226323 , 782127 , 401 }, ++{ 9 , 0 , 4 , 1308538 , 782127 , 428 }, ++{ 9 , 0 , 5 , 454720 , 260709 , 446 }, ++{ 9 , 0 , 8 , 1456322 , 782127 , 476 }, ++{ 9 , 0 , 101 , 1474592 , 782127 , 482 }, ++{ 9 , 99 , 100 , 979678 , 521559 , 480 }, ++{ 9 , 99 , 2 , 363370 , 173853 , 535 }, ++{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 9 , 99 , 5 , 454720 , 173853 , 669 }, ++{ 9 , 99 , 8 , 1456322 , 521559 , 714 }, ++{ 9 , 99 , 101 , 1474592 , 521559 , 723 }, ++{ 18 , 0 , 1 , 535 , 588 , 233 }, ++{ 18 , 0 , 2 , 1070 , 882 , 311 }, ++{ 18 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 16 , 0 , 1 , 763 , 816 , 239 }, ++{ 16 , 0 , 2 , 1526 , 1224 , 319 }, ++{ 16 , 0 , 3 , 2289 , 1632 , 359 }, ++{ 16 , 0 , 5 , 3815 , 2448 , 399 }, ++{ 16 , 0 , 7 , 5341 , 3264 , 419 }, ++{ 22 , 0 , 1 , 535 , 588 , 233 }, ++{ 22 , 0 , 2 , 1070 , 882 , 311 }, ++{ 22 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 20 , 0 , 1 , 143429 , 152592 , 241 }, ++{ 20 , 0 , 2 , 286858 , 228888 , 321 }, ++{ 20 , 0 , 3 , 430287 , 305184 , 361 }, ++{ 20 , 0 , 5 , 717145 , 457776 , 401 }, ++{ 20 , 0 , 7 , 1004003 , 610368 , 421 }, ++{ 2 , 0 , 1 , 584 , 588 , 254 }, ++{ 2 , 0 , 2 , 1169 , 882 , 339 }, ++{ 2 , 0 , 6 , 3507 , 2058 , 436 }, ++{ 0 , 0 , 1 , 812 , 816 , 255 }, ++{ 0 , 0 , 2 , 1624 , 1224 , 340 }, ++{ 0 , 0 , 3 , 2436 , 1632 , 382 }, ++{ 0 , 0 , 5 , 4060 , 2448 , 425 }, ++{ 0 , 0 , 7 , 5684 , 3264 , 446 }, ++{ 6 , 0 , 1 , 584 , 588 , 254 }, ++{ 6 , 0 , 2 , 1168 , 882 , 339 }, ++{ 6 , 0 , 6 , 3504 , 2058 , 436 }, ++{ 4 , 0 , 1 , 152592 , 152592 , 256 }, ++{ 4 , 0 , 2 , 305184 , 228888 , 341 }, ++{ 4 , 0 , 3 , 457776 , 305184 , 384 }, ++{ 4 , 0 , 5 , 762960 , 457776 , 427 }, ++{ 4 , 0 , 7 , 1068144 , 610368 , 448 }, ++}; +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400 +@@ -0,0 +1,59 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * ++ * Copyright (C) 2008 Patrick Boettcher ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef CX24120_H ++#define CX24120_H ++ ++#include ++ ++struct firmware; ++struct dvb_frontend; ++struct i2c_adapter; ++ ++struct cx24120_config ++{ ++ u8 i2c_addr; ++ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name); ++ void (*stream_control)(struct dvb_frontend *fe, u8 onoff); ++}; ++ ++#if defined(CONFIG_DVB_CX24120) || \ ++ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c); ++extern int cx24120_reset(struct dvb_frontend *fe); ++#else ++static inline ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++static inline int cx24120_reset(struct dvb_frontend *fe) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return -ENODEV; ++} ++#endif ++ ++#endif +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig +--- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -4,6 +4,13 @@ + comment "Multistandard (satellite) frontends" + depends on DVB_CORE + ++config DVB_CX24120 ++ tristate "Conexant CX24120 based" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend. ++ + config DVB_STB0899 + tristate "STB0899 based" + depends on DVB_CORE && I2C +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile +--- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400 +@@ -19,6 +19,10 @@ + obj-$(CONFIG_DVB_CX22700) += cx22700.o + obj-$(CONFIG_DVB_S5H1432) += s5h1432.o + obj-$(CONFIG_DVB_CX24110) += cx24110.o ++ ++# inserted by Custler ++obj-$(CONFIG_DVB_CX24120) += cx24120.o ++ + obj-$(CONFIG_DVB_TDA8083) += tda8083.o + obj-$(CONFIG_DVB_L64781) += l64781.o + obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o diff --git a/packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch b/packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch new file mode 100644 index 0000000000..ad413e55f6 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch @@ -0,0 +1,30 @@ +From 5a59cc60d323c3b50f3afa4b9949f97f2bd05ed0 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Thu, 11 Jun 2015 11:02:01 +0300 +Subject: [PATCH] i915_irq: enable legacy turbo + +--- + 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 6d49443..2367009 100644 +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -4235,12 +4235,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) && !IS_CHERRYVIEW(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); +-- +2.1.4 + diff --git a/packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch new file mode 100644 index 0000000000..16ac49bee6 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch @@ -0,0 +1,25 @@ +From c314d9af9d774c052bea324e1a140ccdba0ca070 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 8 Apr 2014 14:02:53 +0300 +Subject: [PATCH] pm: disable async suspend/resume by default + +--- + kernel/power/main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf63..361db93 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -46,7 +46,7 @@ int pm_notifier_call_chain(unsigned long val) + } + + /* If set, devices may be suspended and resumed asynchronously. */ +-int pm_async_enabled = 1; ++int pm_async_enabled = 0; + + static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +-- +1.7.2.5 + diff --git a/packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch b/packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch new file mode 100644 index 0000000000..b3eb8b34b0 --- /dev/null +++ b/packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch @@ -0,0 +1,26 @@ +From 57f0b99ca9a2db948fa70988c447553683368be1 Mon Sep 17 00:00:00 2001 +From: Nell Hardcastle +Date: Thu, 29 May 2014 22:06:50 -0700 +Subject: [PATCH] eMMC: Don't initialize partitions on RPMB flagged areas. + +Prevents a lot of pointless hanging at boot on some devices. +--- + drivers/mmc/card/block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 4409d79..56df902 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -2254,7 +2254,7 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) + return 0; + + for (idx = 0; idx < card->nr_parts; idx++) { +- if (card->part[idx].size) { ++ if (card->part[idx].size && !(card->part[idx].area_type & MMC_BLK_DATA_AREA_RPMB)) { + ret = mmc_blk_alloc_part(card, md, + card->part[idx].part_cfg, + card->part[idx].size >> 9, +-- +1.7.10.4 + diff --git a/projects/Generic/linux/linux.x86_64.conf b/projects/Generic/linux/linux.x86_64.conf index 0978b12977..aa94083d3a 100644 --- a/projects/Generic/linux/linux.x86_64.conf +++ b/projects/Generic/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.0.0-rc6 Kernel Configuration +# Linux/x86_64 4.1.0-rc8 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -40,6 +40,7 @@ CONFIG_X86_HT=y CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -93,7 +94,6 @@ CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CMOS_UPDATE=y @@ -139,6 +139,7 @@ CONFIG_RCU_NOCB_CPU=y # CONFIG_RCU_NOCB_CPU_NONE is not set # CONFIG_RCU_NOCB_CPU_ZERO is not set CONFIG_RCU_NOCB_CPU_ALL=y +# CONFIG_RCU_EXPEDITE_BOOT is not set CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y @@ -183,6 +184,7 @@ CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BPF=y CONFIG_EXPERT=y # CONFIG_UID16 is not set +CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set # CONFIG_SYSFS_SYSCALL is not set # CONFIG_SYSCTL_SYSCALL is not set @@ -264,9 +266,11 @@ CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y CONFIG_HAVE_ARCH_SOFT_DIRTY=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_COMPAT_OLD_SIGACTION=y @@ -357,7 +361,6 @@ CONFIG_IOSF_MBI=m CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y -# CONFIG_MEMTEST is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set # CONFIG_MCORE2 is not set @@ -388,7 +391,6 @@ CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set -CONFIG_X86_UP_APIC_MSI=y CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y # CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set @@ -408,7 +410,7 @@ CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_DIRECT_GBPAGES=y +CONFIG_X86_DIRECT_GBPAGES=y CONFIG_NUMA=y # CONFIG_AMD_NUMA is not set CONFIG_X86_64_ACPI_NUMA=y @@ -456,6 +458,7 @@ CONFIG_CLEANCACHE=y # CONFIG_ZBUD is not set # CONFIG_ZSMALLOC is not set CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_X86_PMEM_LEGACY is not set CONFIG_X86_CHECK_BIOS_CORRUPTION=y CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y CONFIG_X86_RESERVE_LOW=64 @@ -516,6 +519,7 @@ CONFIG_PM_CLK=y CONFIG_ACPI=y CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y CONFIG_ACPI_SLEEP=y # CONFIG_ACPI_PROCFS_POWER is not set # CONFIG_ACPI_EC_DEBUGFS is not set @@ -639,7 +643,6 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -926,7 +929,7 @@ CONFIG_DNS_RESOLVER=y # CONFIG_VSOCKETS is not set # CONFIG_NETLINK_MMAP is not set # CONFIG_NETLINK_DIAG is not set -# CONFIG_NET_MPLS_GSO is not set +# CONFIG_MPLS is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set CONFIG_RPS=y @@ -956,11 +959,15 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=m CONFIG_BT_LE=y # CONFIG_BT_SELFTEST is not set +# CONFIG_BT_DEBUGFS is not set # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set # CONFIG_BT_HCIBCM203X is not set @@ -985,6 +992,7 @@ CONFIG_CFG80211_DEFAULT_PS=y # CONFIG_CFG80211_DEBUGFS is not set CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_CFG80211_WEXT=y +CONFIG_CFG80211_WEXT_EXPORT=y CONFIG_LIB80211=m CONFIG_LIB80211_CRYPT_WEP=m CONFIG_LIB80211_CRYPT_CCMP=m @@ -1073,6 +1081,7 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_PMEM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set @@ -1366,13 +1375,7 @@ CONFIG_TUN=y # Distributed Switch Architecture drivers # # CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6060 is not set # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -# CONFIG_NET_DSA_MV88E6171 is not set -# CONFIG_NET_DSA_MV88E6352 is not set -# CONFIG_NET_DSA_BCM_SF2 is not set CONFIG_ETHERNET=y CONFIG_MDIO=y CONFIG_NET_VENDOR_3COM=y @@ -1385,8 +1388,6 @@ CONFIG_VORTEX=y CONFIG_NET_VENDOR_AMD=y # CONFIG_AMD8111_ETH is not set CONFIG_PCNET32=y -# CONFIG_AMD_XGBE is not set -# CONFIG_NET_XGENE is not set CONFIG_NET_VENDOR_ARC=y CONFIG_NET_VENDOR_ATHEROS=y CONFIG_ATL2=y @@ -1394,6 +1395,7 @@ CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y CONFIG_ALX=y +# CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y CONFIG_B44_PCI_AUTOSELECT=y @@ -1497,7 +1499,6 @@ CONFIG_PHYLIB=y # CONFIG_AT803X_PHY=y CONFIG_AMD_PHY=y -# CONFIG_AMD_XGBE_PHY is not set CONFIG_MARVELL_PHY=y # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -1610,13 +1611,7 @@ CONFIG_AR5523=m CONFIG_WCN36XX=m # CONFIG_WCN36XX_DEBUGFS is not set # CONFIG_B43 is not set -# CONFIG_B43_BUSES_BCMA_AND_SSB is not set -# CONFIG_B43_BUSES_BCMA is not set -# CONFIG_B43_BUSES_SSB is not set # CONFIG_B43LEGACY is not set -# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set CONFIG_BRCMUTIL=m # CONFIG_BRCMSMAC is not set CONFIG_BRCMFMAC=m @@ -1896,7 +1891,6 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # # Non-8250 serial port support # -# CONFIG_SERIAL_MFD_HSU is not set CONFIG_SERIAL_CORE=y # CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_SCCNXP is not set @@ -2032,6 +2026,7 @@ CONFIG_PINCTRL=y # # CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_CHERRYVIEW is not set +# CONFIG_PINCTRL_SUNRISEPOINT is not set CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -2138,6 +2133,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT21 is not set @@ -2225,6 +2221,7 @@ CONFIG_BCMA=m CONFIG_BCMA_HOST_PCI_POSSIBLE=y CONFIG_BCMA_HOST_PCI=y # CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMA_DRIVER_PCI=y CONFIG_BCMA_DRIVER_GMAC_CMN=y # CONFIG_BCMA_DEBUG is not set @@ -2245,6 +2242,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DLN2 is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_LPC_ICH is not set CONFIG_LPC_SCH=y # CONFIG_INTEL_SOC_PMIC is not set @@ -2255,10 +2253,12 @@ CONFIG_LPC_SCH=y # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_RETU is not set @@ -2272,6 +2272,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set # CONFIG_MFD_SYSCON is not set @@ -2290,7 +2291,6 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_TWL6040_CORE is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_MFD_LM3533 is not set -# CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set @@ -2643,7 +2643,6 @@ CONFIG_MEDIA_TUNER_FC0013=m CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88TS2022=m CONFIG_MEDIA_TUNER_M88RS6000T=m CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_SI2157=m @@ -2820,6 +2819,7 @@ CONFIG_DRM_TTM=y # CONFIG_DRM_TDFX is not set # CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y +# CONFIG_DRM_RADEON_USERPTR is not set # CONFIG_DRM_RADEON_UMS is not set # CONFIG_DRM_NOUVEAU is not set # CONFIG_DRM_I810 is not set @@ -2831,6 +2831,7 @@ CONFIG_DRM_I915_FBDEV=y # CONFIG_DRM_SIS is not set # CONFIG_DRM_VIA is not set # CONFIG_DRM_SAVAGE is not set +# CONFIG_DRM_VGEM is not set # CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_GMA500 is not set # CONFIG_DRM_UDL is not set @@ -3065,6 +3066,7 @@ CONFIG_SND_HDA_CODEC_CMEDIA=m CONFIG_SND_HDA_CODEC_SI3054=m CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_CORE=m CONFIG_SND_USB=y CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_UA101=m @@ -3122,7 +3124,6 @@ CONFIG_DRAGONRISE_FF=y CONFIG_HID_EZKEY=y # CONFIG_HID_HOLTEK is not set # CONFIG_HID_GT683R is not set -# CONFIG_HID_HUION is not set # CONFIG_HID_KEYTOUCH is not set CONFIG_HID_KYE=y # CONFIG_HID_UCLOGIC is not set @@ -3448,6 +3449,7 @@ CONFIG_LEDS_CLASS_FLASH=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers @@ -3488,6 +3490,7 @@ CONFIG_RTC_INTF_DEV=y # I2C RTC drivers # # CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set # CONFIG_RTC_DRV_DS1307 is not set # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set @@ -3578,6 +3581,7 @@ CONFIG_RTS5208=y # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_FB_SM7XX is not set +# CONFIG_FB_SM750 is not set # CONFIG_FB_XGI is not set # CONFIG_FT1000 is not set @@ -3715,6 +3719,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set @@ -3742,6 +3747,10 @@ CONFIG_BTRFS_FS=m # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set # CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +# CONFIG_F2FS_FS_XATTR is not set +CONFIG_F2FS_CHECK_FS=y # CONFIG_FS_DAX is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y @@ -3833,10 +3842,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_F2FS_FS=y -CONFIG_F2FS_STAT_FS=y -# CONFIG_F2FS_FS_XATTR is not set -CONFIG_F2FS_CHECK_FS=y CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -4005,6 +4010,7 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_TIMER_STATS is not set # @@ -4032,6 +4038,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # # RCU Debugging # +# CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set @@ -4078,6 +4085,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -4269,6 +4277,7 @@ CONFIG_KVM_COMPAT=y CONFIG_RAID6_PQ=m CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set +CONFIG_RATIONAL=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_NET_UTILS=y diff --git a/projects/Nvidia_Legacy/linux/linux.x86_64.conf b/projects/Nvidia_Legacy/linux/linux.x86_64.conf index 52e461ca8f..4917a75227 100644 --- a/projects/Nvidia_Legacy/linux/linux.x86_64.conf +++ b/projects/Nvidia_Legacy/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.0.1 Kernel Configuration +# Linux/x86_64 4.1.0-rc8 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -40,6 +40,7 @@ CONFIG_X86_HT=y CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -93,7 +94,6 @@ CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CMOS_UPDATE=y @@ -139,6 +139,7 @@ CONFIG_RCU_NOCB_CPU=y # CONFIG_RCU_NOCB_CPU_NONE is not set # CONFIG_RCU_NOCB_CPU_ZERO is not set CONFIG_RCU_NOCB_CPU_ALL=y +# CONFIG_RCU_EXPEDITE_BOOT is not set CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y @@ -183,6 +184,7 @@ CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BPF=y CONFIG_EXPERT=y # CONFIG_UID16 is not set +CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set # CONFIG_SYSFS_SYSCALL is not set # CONFIG_SYSCTL_SYSCALL is not set @@ -264,9 +266,11 @@ CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y CONFIG_HAVE_ARCH_SOFT_DIRTY=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_COMPAT_OLD_SIGACTION=y @@ -357,7 +361,6 @@ CONFIG_IOSF_MBI=m CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y -# CONFIG_MEMTEST is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set # CONFIG_MCORE2 is not set @@ -388,7 +391,6 @@ CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set -CONFIG_X86_UP_APIC_MSI=y CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y # CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set @@ -408,7 +410,7 @@ CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_DIRECT_GBPAGES=y +CONFIG_X86_DIRECT_GBPAGES=y CONFIG_NUMA=y # CONFIG_AMD_NUMA is not set CONFIG_X86_64_ACPI_NUMA=y @@ -456,6 +458,7 @@ CONFIG_CLEANCACHE=y # CONFIG_ZBUD is not set # CONFIG_ZSMALLOC is not set CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_X86_PMEM_LEGACY is not set CONFIG_X86_CHECK_BIOS_CORRUPTION=y CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y CONFIG_X86_RESERVE_LOW=64 @@ -516,6 +519,7 @@ CONFIG_PM_CLK=y CONFIG_ACPI=y CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y CONFIG_ACPI_SLEEP=y # CONFIG_ACPI_PROCFS_POWER is not set # CONFIG_ACPI_EC_DEBUGFS is not set @@ -639,7 +643,6 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -926,7 +929,7 @@ CONFIG_DNS_RESOLVER=y # CONFIG_VSOCKETS is not set # CONFIG_NETLINK_MMAP is not set # CONFIG_NETLINK_DIAG is not set -# CONFIG_NET_MPLS_GSO is not set +# CONFIG_MPLS is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set CONFIG_RPS=y @@ -956,11 +959,15 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=m CONFIG_BT_LE=y # CONFIG_BT_SELFTEST is not set +# CONFIG_BT_DEBUGFS is not set # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set # CONFIG_BT_HCIBCM203X is not set @@ -985,6 +992,7 @@ CONFIG_CFG80211_DEFAULT_PS=y # CONFIG_CFG80211_DEBUGFS is not set CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_CFG80211_WEXT=y +CONFIG_CFG80211_WEXT_EXPORT=y CONFIG_LIB80211=m CONFIG_LIB80211_CRYPT_WEP=m CONFIG_LIB80211_CRYPT_CCMP=m @@ -1073,6 +1081,7 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_PMEM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set @@ -1366,13 +1375,7 @@ CONFIG_TUN=y # Distributed Switch Architecture drivers # # CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6060 is not set # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -# CONFIG_NET_DSA_MV88E6171 is not set -# CONFIG_NET_DSA_MV88E6352 is not set -# CONFIG_NET_DSA_BCM_SF2 is not set CONFIG_ETHERNET=y CONFIG_MDIO=y CONFIG_NET_VENDOR_3COM=y @@ -1385,8 +1388,6 @@ CONFIG_VORTEX=y CONFIG_NET_VENDOR_AMD=y # CONFIG_AMD8111_ETH is not set CONFIG_PCNET32=y -# CONFIG_AMD_XGBE is not set -# CONFIG_NET_XGENE is not set CONFIG_NET_VENDOR_ARC=y CONFIG_NET_VENDOR_ATHEROS=y CONFIG_ATL2=y @@ -1394,6 +1395,7 @@ CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y CONFIG_ALX=y +# CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y CONFIG_B44_PCI_AUTOSELECT=y @@ -1497,7 +1499,6 @@ CONFIG_PHYLIB=y # CONFIG_AT803X_PHY=y CONFIG_AMD_PHY=y -# CONFIG_AMD_XGBE_PHY is not set CONFIG_MARVELL_PHY=y # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -1610,13 +1611,7 @@ CONFIG_AR5523=m CONFIG_WCN36XX=m # CONFIG_WCN36XX_DEBUGFS is not set # CONFIG_B43 is not set -# CONFIG_B43_BUSES_BCMA_AND_SSB is not set -# CONFIG_B43_BUSES_BCMA is not set -# CONFIG_B43_BUSES_SSB is not set # CONFIG_B43LEGACY is not set -# CONFIG_B43LEGACY_DMA_AND_PIO_MODE is not set -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set CONFIG_BRCMUTIL=m # CONFIG_BRCMSMAC is not set CONFIG_BRCMFMAC=m @@ -1896,7 +1891,6 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # # Non-8250 serial port support # -# CONFIG_SERIAL_MFD_HSU is not set CONFIG_SERIAL_CORE=y # CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_SCCNXP is not set @@ -2032,6 +2026,7 @@ CONFIG_PINCTRL=y # # CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_CHERRYVIEW is not set +# CONFIG_PINCTRL_SUNRISEPOINT is not set CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -2138,6 +2133,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT21 is not set @@ -2225,6 +2221,7 @@ CONFIG_BCMA=m CONFIG_BCMA_HOST_PCI_POSSIBLE=y CONFIG_BCMA_HOST_PCI=y # CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMA_DRIVER_PCI=y CONFIG_BCMA_DRIVER_GMAC_CMN=y # CONFIG_BCMA_DEBUG is not set @@ -2245,6 +2242,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DLN2 is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_LPC_ICH is not set CONFIG_LPC_SCH=y # CONFIG_INTEL_SOC_PMIC is not set @@ -2255,10 +2253,12 @@ CONFIG_LPC_SCH=y # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_RETU is not set @@ -2272,6 +2272,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set # CONFIG_MFD_SYSCON is not set @@ -2290,7 +2291,6 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_TWL6040_CORE is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_MFD_LM3533 is not set -# CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set @@ -2643,7 +2643,6 @@ CONFIG_MEDIA_TUNER_FC0013=m CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88TS2022=m CONFIG_MEDIA_TUNER_M88RS6000T=m CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_SI2157=m @@ -3018,6 +3017,7 @@ CONFIG_SND_HDA_CODEC_CMEDIA=m CONFIG_SND_HDA_CODEC_SI3054=m CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_CORE=m CONFIG_SND_USB=y CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_UA101=m @@ -3075,7 +3075,6 @@ CONFIG_DRAGONRISE_FF=y CONFIG_HID_EZKEY=y # CONFIG_HID_HOLTEK is not set # CONFIG_HID_GT683R is not set -# CONFIG_HID_HUION is not set # CONFIG_HID_KEYTOUCH is not set CONFIG_HID_KYE=y # CONFIG_HID_UCLOGIC is not set @@ -3401,6 +3400,7 @@ CONFIG_LEDS_CLASS_FLASH=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers @@ -3441,6 +3441,7 @@ CONFIG_RTC_INTF_DEV=y # I2C RTC drivers # # CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set # CONFIG_RTC_DRV_DS1307 is not set # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set @@ -3531,6 +3532,7 @@ CONFIG_RTS5208=y # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_FB_SM7XX is not set +# CONFIG_FB_SM750 is not set # CONFIG_FB_XGI is not set # CONFIG_FT1000 is not set @@ -3668,6 +3670,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set @@ -3695,6 +3698,10 @@ CONFIG_BTRFS_FS=m # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set # CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +# CONFIG_F2FS_FS_XATTR is not set +CONFIG_F2FS_CHECK_FS=y # CONFIG_FS_DAX is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y @@ -3786,10 +3793,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_F2FS_FS=y -CONFIG_F2FS_STAT_FS=y -# CONFIG_F2FS_FS_XATTR is not set -CONFIG_F2FS_CHECK_FS=y CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3958,6 +3961,7 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_TIMER_STATS is not set # @@ -3985,6 +3989,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # # RCU Debugging # +# CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set @@ -4031,6 +4036,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -4222,6 +4228,7 @@ CONFIG_KVM_COMPAT=y CONFIG_RAID6_PQ=m CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set +CONFIG_RATIONAL=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_NET_UTILS=y diff --git a/projects/RPi/options b/projects/RPi/options index ce23603dc8..ff8d9084ee 100644 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -57,7 +57,7 @@ # Kernel to use. values can be: # default: default mainline kernel - LINUX="default" + LINUX="4.0" # NOOBS supported hex versions NOOBS_HEX="2,3,4,5,6,7,8,9,d,e,f,10,11,12,14,19" diff --git a/projects/RPi2/options b/projects/RPi2/options index 28b3747c9d..e8df837a09 100644 --- a/projects/RPi2/options +++ b/projects/RPi2/options @@ -57,7 +57,7 @@ # Kernel to use. values can be: # default: default mainline kernel - LINUX="default" + LINUX="4.0" # NOOBS supported hex versions NOOBS_HEX="1040,1041" From 4158d43ba9b5d71de3bb94c4da65c8cf18f3ae44 Mon Sep 17 00:00:00 2001 From: kszaq Date: Mon, 15 Jun 2015 22:54:57 +0200 Subject: [PATCH 02/29] projects/WeTek_Play/patches/kodi: Make ugly IEC958 workaround less ulgy We need to report AE_DEVTYPE_IEC958 only for AML Dummy Codec. Let ALSA provide us with proper properties for other sound cards. This matches RPi implementation. --- .../patches/kodi/0017-enable-IEC958.patch | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/projects/WeTek_Play/patches/kodi/0017-enable-IEC958.patch b/projects/WeTek_Play/patches/kodi/0017-enable-IEC958.patch index c3f38fb26b..0d259f4756 100644 --- a/projects/WeTek_Play/patches/kodi/0017-enable-IEC958.patch +++ b/projects/WeTek_Play/patches/kodi/0017-enable-IEC958.patch @@ -2,17 +2,16 @@ diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngin index e22db7a..dcdaf2e 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -1291,6 +1291,12 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) +@@ -1342,6 +1342,12 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev + if (snd_card_get_name(cardNr, &cardName) == 0) + info.m_displayName = cardName; - AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) - { -+#ifdef HAS_LIBAMCODEC -+ // ugly workaround to show DTS / AC3 caps -+ // but don't run into multi channel issues -+ // as we can only open 2 pcm channels -+ return AE_DEVTYPE_IEC958; -+#endif - if (name.substr(0, 4) == "hdmi") - return AE_DEVTYPE_HDMI; - else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") - ++ // ugly workaround to show DTS / AC3 caps ++ // but don't run into multi channel issues ++ // as we can only open 2 pcm channels ++ if (info.m_displayName == "AML-DUMMY-CODEC") ++ info.m_deviceType = AE_DEVTYPE_IEC958; ++ + if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && + info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") + { From effad0ec41fbc95d343d2ff770b14e0f4a4e5e44 Mon Sep 17 00:00:00 2001 From: kszaq Date: Wed, 4 Feb 2015 11:39:58 +0100 Subject: [PATCH 03/29] projects/WeTek_Play/initramfs: Init framebuffer according to HDMI resolution from kernel command line --- projects/WeTek_Play/initramfs/platform_init | 41 +++++++++++++-------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/projects/WeTek_Play/initramfs/platform_init b/projects/WeTek_Play/initramfs/platform_init index 20d24df3a7..5f36b62914 100755 --- a/projects/WeTek_Play/initramfs/platform_init +++ b/projects/WeTek_Play/initramfs/platform_init @@ -18,25 +18,14 @@ # along with OpenELEC. If not, see . ################################################################################ -# Force 720p display mode at startup -echo 720p > /sys/class/display/mode - -# Enable framebuffer device -echo 0 > /sys/class/graphics/fb0/blank - -# Disable framebuffer scaling -echo 0 > /sys/class/graphics/fb0/free_scale - -# Set framebuffer geometry -fbset -fb /dev/fb0 -g 1280 720 1280 1440 32 - -# Include deinterlacer into default VFM map -echo rm default > /sys/class/vfm/map -echo add default decoder ppmgr deinterlace amvideo > /sys/class/vfm/map +hdmimode=720p # Parse command line arguments for arg in $(cat /proc/cmdline); do case $arg in + hdmimode=*) + hdmimode="${arg#*=}" + ;; scaling_governor=*) scaling_governor="${arg#*=}" ;; @@ -49,6 +38,28 @@ for arg in $(cat /proc/cmdline); do esac done +echo "$hdmimode" > /sys/class/display/mode + +# Enable framebuffer device +echo 0 > /sys/class/graphics/fb0/blank + +# Disable framebuffer scaling +echo 0 > /sys/class/graphics/fb0/free_scale + +# Set framebuffer geometry to match the resolution +case "$hdmimode" in + 720*) + fbset -fb /dev/fb0 -g 1280 720 1280 1440 32 + ;; + 1080*) + fbset -fb /dev/fb0 -g 1920 1080 1920 2160 32 + ;; +esac + +# Include deinterlacer into default VFM map +echo rm default > /sys/class/vfm/map +echo add default decoder ppmgr deinterlace amvideo > /sys/class/vfm/map + # Boot with performance governor, then switch to the governor specified in the kernel command line for cpufreq in /sys/devices/system/cpu/cpu[0-9]*/cpufreq; do if [ -n "$scaling_governor" ]; then From cf38742c1df65348e6c2c6bf05e0dec7da742a44 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Tue, 16 Jun 2015 10:58:26 +0300 Subject: [PATCH 04/29] xf86-video-nvidia: update to xf86-video-nvidia-352.21 --- packages/x11/driver/xf86-video-nvidia/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/driver/xf86-video-nvidia/package.mk b/packages/x11/driver/xf86-video-nvidia/package.mk index e2c1466e79..3dcdbdf252 100644 --- a/packages/x11/driver/xf86-video-nvidia/package.mk +++ b/packages/x11/driver/xf86-video-nvidia/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xf86-video-nvidia" -PKG_VERSION="346.72" +PKG_VERSION="352.21" PKG_REV="1" PKG_ARCH="x86_64" PKG_LICENSE="nonfree" From a0b711d341da479438fb68c04bef474ce7281aef Mon Sep 17 00:00:00 2001 From: MilhouseVH Date: Tue, 16 Jun 2015 15:59:46 +0100 Subject: [PATCH 05/29] Configure RPi/RPi2 platform with optimal CPU and IO settings --- projects/RPi/initramfs/platform_init | 28 +++++++++++++++++++++++++++ projects/RPi2/initramfs/platform_init | 28 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 projects/RPi/initramfs/platform_init create mode 100755 projects/RPi2/initramfs/platform_init diff --git a/projects/RPi/initramfs/platform_init b/projects/RPi/initramfs/platform_init new file mode 100755 index 0000000000..e3e2e7d50a --- /dev/null +++ b/projects/RPi/initramfs/platform_init @@ -0,0 +1,28 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2015 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# OpenELEC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC. If not, see . +################################################################################ + +# Enable io_is_busy for improved sdhost performance - essentially, equivalent of force_turbo=1 but for mmc +echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy + +# Configure frequency scaling properties - should improve performance a little (turbo, in most cases) +echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor +echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold +echo 100000 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate +echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor diff --git a/projects/RPi2/initramfs/platform_init b/projects/RPi2/initramfs/platform_init new file mode 100755 index 0000000000..e3e2e7d50a --- /dev/null +++ b/projects/RPi2/initramfs/platform_init @@ -0,0 +1,28 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2015 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# OpenELEC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC. If not, see . +################################################################################ + +# Enable io_is_busy for improved sdhost performance - essentially, equivalent of force_turbo=1 but for mmc +echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy + +# Configure frequency scaling properties - should improve performance a little (turbo, in most cases) +echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor +echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold +echo 100000 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate +echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor From fae869a306ed8e6bd07792f9fc299b4e0bce5a30 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 17 Jun 2015 00:08:04 +0200 Subject: [PATCH 06/29] xorg-server: update to xorg-server-1.17.2 Signed-off-by: Stephan Raue --- packages/x11/xserver/xorg-server/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/xserver/xorg-server/package.mk b/packages/x11/xserver/xorg-server/package.mk index b425a278f1..efb2d1ad1c 100644 --- a/packages/x11/xserver/xorg-server/package.mk +++ b/packages/x11/xserver/xorg-server/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xorg-server" -PKG_VERSION="1.17.1" +PKG_VERSION="1.17.2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" From b9adb2d9f9d1722d1b5b7cca5c56f9d512dae287 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Wed, 17 Jun 2015 10:46:11 +0300 Subject: [PATCH 07/29] move 'set ondemand threshold' to init --- packages/linux/package.mk | 2 -- packages/linux/system.d/cpufreq-threshold.service | 11 ----------- packages/sysutils/busybox/scripts/init | 5 +++++ 3 files changed, 5 insertions(+), 13 deletions(-) delete mode 100644 packages/linux/system.d/cpufreq-threshold.service diff --git a/packages/linux/package.mk b/packages/linux/package.mk index 84ee3eb5b9..38fac29265 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -195,6 +195,4 @@ makeinstall_init() { post_install() { mkdir -p $INSTALL/lib/firmware/ ln -sf /storage/.config/firmware/ $INSTALL/lib/firmware/updates - - enable_service cpufreq-threshold.service } diff --git a/packages/linux/system.d/cpufreq-threshold.service b/packages/linux/system.d/cpufreq-threshold.service deleted file mode 100644 index 3bebb4e262..0000000000 --- a/packages/linux/system.d/cpufreq-threshold.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Set ondemand threshold -DefaultDependencies=false - -[Service] -Type=oneshot -ExecStart=-/bin/sh -c 'echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold' -RemainAfterExit=yes - -[Install] -WantedBy=basic.target diff --git a/packages/sysutils/busybox/scripts/init b/packages/sysutils/busybox/scripts/init index 1b2a9b4e27..1afea77dfc 100755 --- a/packages/sysutils/busybox/scripts/init +++ b/packages/sysutils/busybox/scripts/init @@ -60,6 +60,11 @@ # hide kernel log messages on console echo '1 4 1 7' > /proc/sys/kernel/printk + # set ondemand up_threshold + if [ -e /sys/devices/system/cpu/cpufreq/ondemand/up_threshold ] ; then + echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold + fi + # run platform_init script if exists if [ -f "./platform_init" ]; then ./platform_init From 8b130e537a76d3c4bb027ebb0c38bc3bed332a26 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Wed, 17 Jun 2015 10:56:33 +0300 Subject: [PATCH 08/29] pvr.vbox: update to pvr.vbox-b8dff38 --- packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk b/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk index c9c5ffb02a..9c06ca67a6 100644 --- a/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk +++ b/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="pvr.vbox" -PKG_VERSION="63b8782" +PKG_VERSION="b8dff38" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From f62b24e2caa7d133456946baba92eb4d7c234fed Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Wed, 17 Jun 2015 10:56:51 +0300 Subject: [PATCH 09/29] kodi: update to kodi-15.0-rc1-a248db2 --- packages/mediacenter/kodi-theme-Confluence/package.mk | 2 +- packages/mediacenter/kodi/package.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mediacenter/kodi-theme-Confluence/package.mk b/packages/mediacenter/kodi-theme-Confluence/package.mk index 206233840f..dc13f3adda 100644 --- a/packages/mediacenter/kodi-theme-Confluence/package.mk +++ b/packages/mediacenter/kodi-theme-Confluence/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="kodi-theme-Confluence" -PKG_VERSION="15.0-beta2-daedd5f" +PKG_VERSION="15.0-rc1-a248db2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi/package.mk b/packages/mediacenter/kodi/package.mk index 151accc831..890874a28a 100644 --- a/packages/mediacenter/kodi/package.mk +++ b/packages/mediacenter/kodi/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="kodi" -PKG_VERSION="15.0-beta2-daedd5f" +PKG_VERSION="15.0-rc1-a248db2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 5b166e0ae318835945907c724af754ada0b08279 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 18 Jun 2015 20:04:46 +0300 Subject: [PATCH 10/29] kodi: remove unused splash images --- packages/mediacenter/kodi/splash/splash.png | Bin 72336 -> 0 bytes packages/mediacenter/kodi/splash/splash1.png | Bin 95223 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/mediacenter/kodi/splash/splash.png delete mode 100644 packages/mediacenter/kodi/splash/splash1.png diff --git a/packages/mediacenter/kodi/splash/splash.png b/packages/mediacenter/kodi/splash/splash.png deleted file mode 100644 index 6b2897b0a1f049ba9438384654b6d4f016a44a9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72336 zcmeEuhdY~n^mmLfHcTbYEDa{6Tl$Ku;S$KKaQ(7rmjJVR(4c+7|#| zI(PC*1xSB?o^q1j@0OtsJ&u}|>I@eEAPBgnt!WlSwK^G`;5-t%useX1LYwbkyv-CcK8#LC#C<6K@><;X zH9h~>IU`mU-AH>JS;F`sVg^&7a@zcQT6Vzj&bK zXfUYz=$wMdPmG`CNY=ux%EH9%R9$Jt@@w*hkz`(#sRzgaOWb`iAO+so5M<_T=_+y&EP8o0LLV$h1^qk7X)(OqOEL>N=O0&bvM_0&9F2&uFcthb5@cv-Sn&M$b6LfPv1tXP zJB81`F+eIFrSNj|L8*6znbJ9OKmo(nLBQ=t@@m~v9(GzUaN*6jlbxh%Z1s2KzeRU< zp!*HiT69%jz3fc+a3eT7Bh$d8C)04jxx2u3p}U~Q1$wB;Tj!RTt*-uNDrh!wd)xy- z+FM=q^uCmE@!v7g1UvQdyPd*ChRl=HGAw#cRW*}8_}8oLnHZMBs;a6FEjXGWWi2rE z_T1cG@oQV1K0u-&trstWb}5s=+ghfG+Zx_lRcZP`rVqUE(`jhMhJog& z6F<^a5%#tQbmkb3J#s$iPs1cng{;5}$$0qn7yojcN@?Itfamuk-7+?f8L?BMi>i-) zY9AmWBxG&ymNQEP*J^(dGvkXUEd|Dreqok8sCK;4H$e71nfx;nHYk(qW$}J(Nyn5? ze;T#PWI{4h$0;~@)35@J=pfP=+3YogX6D&RjY%<>Al4H?}49jA?8;6QNe?JTlZCN1Z3ya zYLv6bdn!e5-&MPDAnLK=-$5Kn^}h7g4FH|$EVF95s>b$>8j_#90A!sEE4J5^3598ph!V?}(*JV*C}vP^=-HvCcxq-n%A!a@G|~=W z8}X0?`jxpz%iPVv2P~u-Slk=`CoLjOu^c0$f=xB3CK_G#p}n6!2p7*dHnG=NCbd(u z&4adD7r-U@`w_8Mz4IH=?GUK4^c|i~3xuVA@bjP%;*Jr%&VcUlic#65d*i`_NfaC0 zZDkx5Qa@9qc2wfG{nZ4TNcG!9F-$K3qch4c=PyOJjMJ)-_j^c3$03{Owf#DeX%65* z&6+$s(#oWgg|Xoh=SV0+zvH7O&t$1@QFpy|1kuS7JLB@Q2Ca=#TlI-@=NP{mtYgbj zZ6AZ6hT08x@9vcJ+ZlQe7df7T+rX(_(VwqGjfRm-@_yY5Rl8AkK(ydKvBv+*J4ZDr zV@>(q?z|ETMEKMCi5z~<3_RfW0ybo*>?NHayF?J#le*|56(JcFOuK|?zRC;rh=yfs z*Ei8l*i2~m6-=G&#YMjzVmi)O8u|&+eammkc&tnnZi-0NW7=Mu#a9<}+o|29O|OKG z!umKehU-Q*)#UP}B(KHOXXA*-UYN>vdJ>!i~5 zT)U(wXurHU^i0gzTiX`HClrTr^y>8$GQ?S|{wTCVWY*N>)D5pc1NI46}f z5L4~bq`DRJcX#%QiU*>jml>7jLL@|6vECK6xriw%Ih#tMJ@28F9@R?!XL`E*S(8lz zkr1I7xvl8mAxw1=!Y!G)Zzv($LF?5p$C*^q$*}3Q4q1K?y2`;)_V8Q~>3&9^-N7{T zu>oNEGNVea5L9j9?3+Rwfgt~jUkL<$` zrO8)y!jweJnnpZR0+yjE5)!f1VoOnLi){jMUXP#^=m-Zp3E8Dy# z8-?+eWq|X)H30Gz0EWoKCW5OX^{H~rnXj)dxw$^PHoQH9HM>hqh<&1Zh_X`5cCE7- zo%eeU#54qPnbP!Vu~}7mIp^dEAPdihK3QUr7~~UG5zo zTBV<#y>)%E6hWNk@-QhX7s&^*eZbXQrgxTL>>_mF^0WOhu$BCS3aB-w1`EvuGSp?f z+NlQB^6!@rto$Py9H7)BBHqZ+aqe^gZC%{QOU5tituxA9ON9R^qKnn+2Jr@N z?(Q8~z)GaIp~!D7ht59$3V#%1F%Pfn@nBjC1(Z zUgh?=xFn?ZtD1;|?s*UAbCGEw=3p&THQn@E5|wm*IM%Yy?p&vi4PJqDFbs0~HR&^0 z*=lpiWr?mN;FPI4$vd;!y78liB_P4*wiUHQhAO?Fx>l}d+6nFYAEb_AzNkU%ptUN( z^Bh2JspZgrkPFeZ4*Jtm*>yD+W=Qe&wAC zQOI4|U|!+95nWkOX}=kaDGXfG{5Kxu;P?)!VH|59uAS5_ZGrH~;v7@(j_YV0EZbg3 zdVaR~Hw*R@KXC{TSf33A7V=x_fpAmP4Y`1jQuN2Evk=7Teu+`2tPlV!tWFovwiNfw0)K4WeM{ARr?Cz(iTQd*XYingL6GV54fRdp^!EXcgLOw(n_-(t!rgmgR9 zt@{|H-D7kJfqR~#S`K^rFJFH?WO?1^1FPlx{czmr%hOi^7chzMIh( za`b}jBLu4at`0F_@|)dvzlOnEVPNziu1xMV&@je;X0UQNXY&>JR|!dGi_rV`>K=E2 ztFJdQ&dlV-xVgH1P5U!7J))(gruX4G25cG*iPRyknf!p_RzmzpQ-pZ&P9&H~wn%YH zfbHSqwyI)=V{|#%HFxA}L9K3r&U*Hh5FIm>w4}jkv<*!o^lM6x^-x;O{&oBlUpc3k z;OqMHoVGbrOL28_mi@_=9-B4=l0y(WUZ^ukWk}Hh3f6yihJW*c{?!iU-x;Efm69Q( ziRa+jfG7~_+xPEphwiTJ@N~?P=N{MfY(KxCvVh+cKIEwrtv~l6t$4Kai;^_xw4~jXZ4zF))-i;>T zZRyY@+=tg2UaSC&Hh2^X19Ux=4HwK}|3K|b3a7JLP>!9y7}=7-bbEAngfPWt2@qAX zcsZe6hmKYB7L9geiGWW$iGi8lrCzquWAit~cse>=WohOxR`}stRK9F>aPeb^z^?vQ zTeDhdRf;3B847ojIV>TIOY`rjqo-3M=^k^A_a0A~e4q7#l+bSdan z6Det_?zi|7F3{>Bb<;A|_UWlUjvA63I{EqaHJ#4K9Se^_Jzg`4nZ^a}i|DY)TgW&|5;mssQF>jt&jg=SF_x_3|FiVIEKpDBRe1 zB(U%&h@GN<*m=@(i@!mvO;>Lq>k!Z)f_hOr=I(i8Qe?{e{-hOqUyZk|jF6C5o973H zMe{=OuXCLro-N~Nrqg!82Qjd0i!V;19Akb76bMPA?p`cZer znhU)lz}0r;l6_REy4Jn1Y?{iz9x&H);pX4Ty*!X&jg@egKDCqN9+lY?Ag5Vo>1Q5I zz7T1fF!gu|?$G#nim|}}fS0Znk*n>{HDr6=F4S~3hjt=(r}~wZgf~uXqw~0l34O46 z7U}_?%O~a?IHI^HD=`v1RX}d=9Qf9p{u*Ghx!C9EwNke62f**IUULutAC}^_kdj2ma0I zdYkC7i67PaO6n{Pn!(*%V)dTGWXF@a<7$)+?>{P|4WQs zz(Mp&g*KrF-qc=Q;yU^|79PpfmP|RSPc68aGpolV2BNKsXeYvV+T4S2Vs0|&7288& zQwdpOGx44A%ibKKWy|)7E1CPd-#CpCOW@%*ELWkEC{@FRjSGN<-+68na8io3+{t@> zO0ZI%Dx9Xp3k%F48`(1yN>n0aQJ*Is310ef%5%3jIEh9=d163kt0eNG#SXPgW^VZ84 zz9y@ZOe9PTocq%|LZgn2zN}zcWmze4TyGYo_3VtTahbX=<3nUBSY?9P(tPf)Jr5I$ zPJY1}q_Zy)-Q5W%zD=Q7o)YP#?sBuqNe%MQUndx#Bh$P`mb+@`WOt9+KUP1*?m7p< zCugQXmG>LE(g$ZwN+UzJJIa^x6bmw{WV1|i%C6GU%NN8PGc%Pw{{vakCm=!yjU`e* zBprC?eIr#kD`dE zK@1PU|FFTR9f_7A)D9Zv%10rCQ7wJ>dIOR4MZ(l;=7oxC<#uMNqoK*m>`S+6<3g;T ze072oZ#LN_=zSYL?2be4OE)1a<;FonyeksJZ<*2D(vu-w!g(+0$?zxez7+G(3m_>R z)VA)!w{KnW{y#`~x#dZm`uFro{vD^exw*2c=u1}sd19*UMlOe{Imop6RV*jzv2Lxb zev0Lnw)D9xgK`zEos^nS#%sl`^!?FpwV`5S@w{u)RCqI4pNeBMB%dSQSP_VO1j9(I zdO|>-#o?(QJJQ%)NXkyi$b)2aX?s4l9X&H{%`OEsK6$>kHsJKk+gl>!3 zwqQCQI#(c&H+6n@2&th}&OaMmT`Ph?YXCQ+Rd{6X55=}SGGVN^W9&4?oJ))d>0Gy- zSV+J_@-fxryoY6A=&es*zup{2hX!8#`Ue?M;yiED4$XI?BtMFWyx>!R^_1>XyLHw> zf+id+9ss2d`SLB|sXY}uLTEeDSSbyuAW-`kOXH#aijI)r@a7|1v}%vYedd%QRBEa| zM{q=7_3bY<`*M~)GU|%a&1IgK={s!FiSN{4!NK3A=nutCA-|1u>g1=|RmE&C_r9$V zv_f^Ln9Nv;S&iLoPOftk1{4++4&X za(GzD@RH8Q2_r>abj6a1rayGLR-Xk@tddJuKn)2}Tp!PFX zJ@%fWVKD(sFVaG3|QjT}O$EN#x^X9UU*3kwzv2%6935!PPc&Uxft zVH|%KbN0|y7?TC{-J0)mTR}mWy6UFl8iRHI?I2mDQDAF$&MVi1(m@iY&JVD#VJR|Q zx23iL{$zB;tFshdO5J71#y)WATv(VNI6SmV&&W3N_4RcN2$1i}R?qIn9gdA{xp@Uh zcHx?>Z3_=L@h;Y_Xn5I%FjFyJ_%*#erq;7_HT+RuhxI#=y}IrazIX#BaL<>6QsRm` z4Xmza-+ea{4H6OP2 z{>87ZJXOJ$KINbEF}vqi!apn&9&EqiU7W=v-aJz*k>T0&CKWJR9* zVNEtIm|^dhshyn&EzZ%T#H1_2jBV|@1B;7Rmzk0;SNbQ5p05R+mQAp2;3KwtDawi% zFACQDy^`4{E4dJnYfec(x>UeV1E!`+U$`LKoog=6-9A8(kE}1 zO@I06?&Y4bChD*!gvRY@u*%C3?$9R#joy%Z=$;{;uG%yrl-j9z(o=mFu_-L+EwL?T zGmv(Dxs@#DfAwn;ZA{vFY4YRPGAf@gu&!@P!g_&xo`qGlMjFE?H8xr>&Gfp4CHfYco&(|F04r_4Dr#~~TJhekXcL7l+h5GT8D}O#Inl%?Q|{ILN%6|X z)yuu88cO^C4G=i!&Qu=oKwy?NkMc4b)B__#GV5fHA{rtZRHmbSVC>n{;r8j?Lm;bN znS=eiN2iW2QRS@cqyW}eh*DF@%r$1WB2ST1SdD8^PE~%^*mAr@#Ty1r2+GswlryqC zpO9!YItDWUSe+v(T}e!Rg8jB>h}&tgu@*v>$_r0;l5F?X>5+Wn+P8iro#rXYz_nr+Kn7_ zv~*0*e^bgcf-*Xxw&il%1sxPnpZKKQ_oIDg}%9G+QlBOEFDQPuF?Mc}; z+mi$gngR(MIaVyWTSe2Pp=CCmm5VT*?Q7UFzQd#hqe5xmZa`;L^wGW05Db5Mk<8Eh zb8p;6a%bJzF`wMVBT)Ep7pE&w%;Xh>f4RUh^6{{IiZ>n8n!kKFvNc<;*Dh%0Uj5Fk z9)2r*-v#GY`DgEBmAAm@!Ml^&-Ms3C-iLcnw#N;63bHZlwGyzNY!lX7(R;+`hAkHf z&2?}((#g_8bj0X=4NiR9?nyxb1C~((I)WLi3CtFzIdd=%-rwk4dZr#Grb=3sS%Q)} zS^}qQP@`L1e>5~Jk|^D*mD%qW6rOvX_OR85!V5ot)>e9S7^D=uY^LP5_tL(sBD81A z^5VTt1b4vjSm)eAulBUiD1W+Nhh$B0g((6B)u)Y=)DBO6a6> z?%k9z=PXlBlP$ju`lU!j`MfJNyYU&b)>HAaw`XyR#;xcmZ07q>7je)+5q;cY5HQqI zvs54uA*H&{l~f?0P723<(dhKEZJpSsxFu{ji@sMagMfDzzIHeaG`P8#8?XO%brL3s zuL04h9d8)z!D*(0e=0B0tM6qcVpHb*4Pu0u4^%VSWd10-M5w}bn+AJwJjMZ_le)N! zLDbb!u$V;LxrS9HG|NmrdX{NlSF{IO2f4gHy6XdcO-w8Oo^rj4z5H1|y*!Q#0$a_UTwf)x#0&+qJM?0|86NuVkx&JApJu@xc6JJu@n# zWKW&E=x)wt$eAdNmmo&SxE0a(qaZvuVN8XrAANnuqYBez^hu;?GdFNVpe)He$`L~UXjC72P zWj+VniWSvc!9MuZx}H-rcTO%qc_l2D@9bhpliPFZM?N7tJ0pju>m;oG_x7<{yZt>! z@ab)X0UVJ1p}UoY#;`e%iE*7PZFREZdSzf&yf;@Y0Bb*zcp>Q-v(1ebNwmO)iC>n~ zqPMO+7zlwtMX7>A-*tb6%|Q-lw_%4<)4RVkLajsXn&z3XhYI~m14WlM?hokO?O{BC zWE;IE5aIeXLCxqJpvOnFm5m{%ZdH-WXiSC%<84XTyneWqHDh8;_xq8N3=f%F#wV;O zP0wM$hwC$~e!Hr>A8_7Hs?cc^oMDl@ewThin5|bkzKf{8cV4C=`GyU!vPLF^HB%MP zTSMKYpZN+##_q@X9k{67$JLSsl?{ZhCD!aI<$FgRM^EZ`6Al`zGQmkaRd?tL?ux%4 zcJ416p^oHUXVa?mSLaj2YW$FEsY>wQvT($I|YcgO44W0wAgz-g~# zx1?BG7KhbUJ;ZG(v`v#~1Ko6R!)W2n4_`xkw&wlj*P8k>UDha0v2`b8e$1u+4RHbx zUe@x3sMBPh@O#R&O@V}M@$*`MC=bDhtE1A`W^%IXSMLnqQ2=-}M%$iKpfyi2qt4)? z9F)rK9Fxt5#Vd!Z0iH&Cr=QfBSiDhOA3nE9Aw^%f7e!HddXT+L^7YI{G8@@OO~TI3 z>b5U2rx|E)LwuY&oZ^2DDA;=Zu;sgHNOuujHQ*u!IJm5}tuTeJ4kvM?ZLQo5Pw6~z zHUH&gscay1C8dULS?Ni?2-0$Qm;|S@&~3%eUwu_&le0RPR^D@FVytrVMve=;sPwg$ zx~sfr{NkV51npi?Be1X?rja|>QW=f!v5S5K0k?7gAQ**BAMY0L#-YnKIa%4OVyAyiDSH*Zocq;jL2IA7# z`EV*rmk@;*F`I8A@d@nTZY1?VDiMT%Y|Naj0`}$900)h*6*9QXHPAd`^QGLpP3UTA z2*I?01=bSn3?wpIA8m#j7TfcG)uT}z9SH#&R2X@u7j@1ZsizFx4&8|$Edn7n_I3E3 z!j8Aj-?Zwk?lrx>AP=|Y=EN^Q9d)jl>Yyw{ki^Kth;Gc0!-KyPlfEci3_F}Y>e@z= z37tzN-r<)Jz2P7R0HJQTT`L5qZATd-v!iSL<$gkmY#A?RrXjx5L-RLdt?qxEXJ$TA zU_xSS>moKkJy-YsCZTyND;zn)(yxHs?}}I3%EjF+{C94nL^0c7!}O9I^~i09QAuv{ z5ah@lcK$v8>7tAL(JoZQz-%7BC3K$Sr0l>)2E(o+9@1nMBv@=p|-Bfpkey7M1*W{F;pE1U$@l5isTsuvu@3LRBxe*eXx&~toSPGP4CQ@THnf5}tFw+So;1 zDZ?%rj82=m_OUOe6~?fvst*NriwXRAQ0``KYu{&=sXB5uQzEM_(!7V=mA+cc{}(ZI z;9ID`M#^B}yDeYhcDP3dXKI{T$xyy)?F26(XS!$6_M0oVV@3UF;3e-pM@&eTnPG;f zE-fOs5G|M1mL`YJK~8t-W~Ot*jGuKJM|C`gSRbnq++V^ihc_&eG4tmBWb)Td<8&*Y zjms^HBqen+qfScAj+2r{-ObZuc)+LB!@rJZuJotEP0K_8&d%E$2?k&bW=n5<$aWS- zo>6*lH!;G)dUd-0l2nG}X4xgPHyyYc!y36-h^!~d1^8YmT&$}r(+G03Jd5(~A%%he zaW5*`MrtMI_7kdO#}U=E)(Dz(WZ5^(DQ%IawwN68CW}YJYnYj2M*K9t_}*wN{-?6~ zfUR>-iRhTXp>0Z4UWdCX6CIbhv3+eQPW7$VaN?`UXD^B}>0j)9exF%jk+Y2NfSL-H z#`!&k4SKP~lBWIDo3qjph|-#VRA!+Y&qm(k$nt-*0RHUt2X_Vn3J-4XZr638Y?>JJEh@^!MhwDuPJ9$mRJt}WVr7~$ZL1X!mbK-bJRf(_V% zLS^r%^IO?Os>{kc^w9T?%p)-wU})XN_OdA;_GgQ;)L7%(K9zfcn5k|4!|%_TwSiOT zbeh$;?;+BXxToZ&U!a5fH8c?;OQ0a^paO8QY{z8CuDiEFtEoL8L)h2{HgucR7lsVI z*yL_>;b`W_?Q3>^@8tOYmQ2>=UORY2`VAdlPtkKzw^m}PLo%#Scl<2$pdL>A#74j;2_e+i?FBQUBW5Ro-gxQm)#TvUhO->IVsN(m-k^uEMp#^;`{;_SRI&=f!i`NoFK zaWi#m3h#_`#)Y3-n)#+IVVzgR==W?3g{k=1JEMbFMexhW{>a>Bv*iqzn6s3?aUG`d z7+BX04zH?*r~Fu>sBNZHL(_3IW(vRmcZ3FIDl>EQq!}mlaJ}~;>{>?jt$2(Nt*gm9 z>U%8oNbV<37)e42TS3E|kbreWX}Tuz%QXZDz}^z_(t5s7_PW};!d-z4eA_#J=)jHk zO-JbVv%}!QvK^s%3*(Bf5Y=Ac4X0S5$2)y@H}1Ryey_!FQ#OGO_d}hF2u!t+_&DaN zDDRKTLOD)LZtd{&q6VH?40c?fkWK4~Kp_36n^7)3&XqC;A?wo(V+|ij$35dctM7pX zl>TM9!I~-cu8}WP`V_jOJQ0?d=PnV00k&jg9b{_fTpxMd;2W|F4aC{q->J6gx%~a^ zjy6`frWzcWaO2pa#j!ofHac2w;ylN{#^`06Id}J23bB7c}nZ0+tiisJ%8o zZI!V;Gwp&ic-5^?j;ZJt=wUA^CX$r4Gca73NINKt@DIQ||v2jO5wEf|uT=6=IJBm??+Y6y~D zFcw^e-Vu=<=tLfRCf>15u@qLbBKa0HhC324;cgE``Q2UHY5p}#q=r!>twv8YMOjFZ zKD?a_MLVqwpE~By2vrrf+j8xm-=?m=Fun6L9Qcg?tNU}hC+`*aYOMKjJDf;r>{%)? z4J2t0pFoUOo$2w`jEy_=_q%@`I*lAz*#WV$+s!|`n=y2bj1J*Vk~!ir0hKd@Q9~+B z>#A!~QFW*sqQX&4qvtr6f`8COgsG#=;`6h%Yj1{ItB-taqw0E`OK(DqFxbnp==S0yDsMCQ?5xuxcCWag%+gxBt2vLq zj_y5H?YuW9!PwQ9@UKQBh075ROjDa~>k{^AC!|K1IA_fGNpE+<(&+W|3DmW8hUJj5A{^D^W5CX z1>w`d0%6$-Akn4D#Vs_9qSfiv^_*MG+U>3zs}6aIXpb}V*Gl z`YJDz?^j+ATRBj)Hpf;0|5M!N-6qw^X)I79Eyn}weV(7&z%hU$ayc$?bXHsHS}`I4 zWS%UuVwkaQ9u?pbiMsD}I28fubl>DgX|LFvy;#Bibqj6oWEZ}k;wU3VaO|VY-j*o# zFYVDM6{C~Iwk!Ns)sc`N&E0EKHkEJ(?E5h(25M;T=>x`3Ab~-cM-aL4^HV=9?g1T;a zVG43faxMy))UM>~TeHC)0$hOK>&>!4AOM4&nXJ3;d8JFnUC{os-gdJ0t(hxR^tll^ zgSM$9#Y0O@aQePyR(d$lt(YnK@b5J40;beAR<2g=o+)Ekw%%^N@0DRuDZsL}MG=qP zJ@zRHcY85KpZ}3qUZ%8m3*ZrdmWuvP<}LM*WfEvPJM*2~m&JU7rw5kcOE6k%g3mcF z-_7CZELNa)VU40$Vr+0@$_jH zFU?%_Q$|$f2zD0o7Bo%2JVDHK61-3?d1-|1XL+cbqvF6?d^5CB2CSvxG>xEJ53sgx zC=Do5@kBy(lzpmOhKT^&GVTEtYP`|mR#dR+KnwM8zw`9%h>dxa%U->F7?f@YCsz(7 z8BL(vBUL?Es1xoE(}6Bfp@-d{EjNTaVHv;0kR3+izBDe~GJAE!F>kQAI`fN#dzk0o zIVw=n(?VT}o6jgQoIXt{fAk{+&{}SFP zeOfyFr^&C2vFedhjds+vDo$?<*AY7W9H4`(=XWa895s`$O(yn(B|Mi@65NGa5*$Lh zF`eLP>YUe3z4Uj&X*3jhC(eBECt>NxbO5*$ujRuE*pz(ydZ+L{|6plsp4U-vuGj*f z?H!tkQgF?d4?=3>!OpLKl%1oE`R+E(C)=XM+j0Q+>>d(Ag_YbOFk5tY)GfGLll>5f z$n!O7qjcdJ^3}8Jx4ccssm|R!pNAO4K-dXic#*)s^W57(1s3|A;JnqzyS-Be)?Le> zY21zEG=x{^`3>8<_xUMun}?1-FLG~tKjP>LHd_ScMUef4R)82_$vDVODU}^`cbLfE z$WW0<>A-rp7<8R7yTrQt4pa-e2S%)9DrPdI^d(I7T2I&yf(FNRn__={Y-k8pepB1a zR1Jmy=&PzFr`kflQyVaqI%b|KR((l$@&Usvb+50Oege*{?cNe?2EDl=Dp=>kR&Rrs z$G5`K#b;6kM0LVf^n@x&mR`@BwrQ^>YNK0n|SWQ$TRjst}s z6M*oJj)>Y*^?G>Lj$5vP7T#n6rTg9uVeh!)5=y2D$DNo1f^OCUYF$pY8z|^&!1ywL zxsHELA>tVIer%Q)RenDa^ulMN;l4c5do6+LgDfX15$Qd|*@P!OnRU^~Bx8 z!<8p{#Y1A5(^IM*JiBZ;5hs`}G0=2)FZ9S(9d_KD@m$1p*2-AXkd$+W^zr=F!t^+F zlZ~~+s+52naipwFzOAj@Gh1G{RiTrK`qadED%iCJpgf!m+slq&5_ge5849)xaZvo+ zU$umpg84s{M|`h2zk)!*Mwk|n9~ja(baiu9q9EWBhGX7uh4P?jrehAK5Oa$=E<;CZ z!IPlra;{4ufSJLp7=C4UzIbNU#tZ8MTXE}hQp0y=tj3G(E6wuZ)(4{y=g|p`NA7@Z zHcbqoLI-u%np4iB5O_2U$lMqyIF>Hflm47S6?~r$QaSNa)Y%p{`9RaG03Q+_tb?z4_3EC7mgyU=9~8NgS3)GY z5f{I(Zeu7~cY8^}-06RY2o>lP@Adx9$y&bz+~$Zp*qe9hcixl!g58gq-&1QI) zp&bTd&)INhR}Ql|wi<*xcJVeIo;Ef5XEh7Vx|MU7#{z06_rtugsoKhBm&?Q6tQ>ve zSrZ!OLPF9;)2^(oL_KlpRgg|@CApuou6Ma`3d2$>{vqGY)FS2c4XNDc#}713Eq3Ib z05an*mv-eY$BL|IM^e`-4c>q*I?Pp9ncsWP3+ zsWmin+YBxgzOCfSamy2bj&E-WQ-LAe6;o|L7+wk$Y;}VmCZ{rEWTf5EokYg*g4e4|0@>;F1 zVEM@LvQW|j=js@3NM*J+1nElR72QkXRF1SEND{9j6)MWtzwA4C1$0+U=sR`Zfb@xk zY2L0+>FKp9DXAD+mjNA|hqLd&`o-iHEih`X6 zw*Me=c-rEqF*Tca>Ke~UCuHzaiv(b2)gvUXMUHJ9VOQf&#=RYN=TQZ$vW5%Te0S24Y%ZCoWc%nKq!E{KC?_FWGW3JO)DL;DRG@m4t@?Qs!5#tabGWs13;qgguv& zL%>;z(-D#VoyA=yy57>Dq+iwP3sDFoTWSrL!yPz{g!)!0_LzEzbVgTKCr z!-hBjAptku*jwzk^w|)zZ>86$%*utPDvi%&RF4ghxTkn8n}?Rms}F~rbF;Dp>^(L3 zLfMMZ62dA9bDkX;AS+cobM8AKRyjNra2;B8SBh&vvKjXl)WCVzo0hcfX~{g^IU0Ys z|0o|=89lU{pq}xaXtRt@4C` zIWN^w#KH6n5gJyQ(YDK*zo*PI2NY3veZ;UQLsZ6H%3$zfXm1uZm>Jy@Ae=rxVX!B9 zIisk9!6G62{Vwe=vu!!g;46ECWGMkYiJ9R!A`_G1*AaPWB?_+?BGzV`TS&d@gZe9- zZKv2>p!}Tvnc@U5F=ORCdY&YaP(`VHY1@GgF;<-BgxLbEKo&O@}u`dN1;K-W^v-C)5j@N3`}C=xZg6KlImIxC;?SY z&fLa+ke-80kLYc=0x8MBIE4a`r2z_=Iy2*^K92xU%NBrQQ5?+yxN<>&v|7NhD3{Oh z`b1r7RcUWAltz)kv%F?Y_t4)RUx^Aex#_zqUO7p^I+9<#O^LY+wZ$dCi_P3zyy9H0 zd1j?med&_tcu^X3$7%HOh?DOSqp(J*Cn@WcNs4^X{&~vt3@sEocDnhj1dMnDdReeg zt)8Z$>Gu*s4^0{NH~^nMJ#rpZ?;GpnpeM6+1n1?rmaK{7#6Q3AI@Gvy zCUi`IdX#-Lz!TRn;?c{)c>ahgGCiN$BG+3>6PvileHEefELoo4l5y`gp|aw_z3BsdHJR%a6=7EzFYc$$MLQ89CMnFj84;#-@GJ0U4)(6Xc{|wI-T>h%K9X5 zBq>kgkM|CVZ!zaGjvQ*B*2rE~0jxfG03WUJkJoV1mnw~~y08}s+pep-C}>u;7}840mnzV=A>>_XlCsT<_~bN`2JcT3!S-+6=R%FhE+t&CPZ(Xz>?~ zn{i-^&KhhI{C4x{)2BBt0G`bPqjoMkU|aO-$62vUD<#m{6Af{(7Nr5fM|uYqde}v) zLgml{s5J5ocGXpi%A${UdNrlWD1HgO-mA_|bk;+MvpLejh&Fi!Wp|7wA+ph!!!9woc0vCMIjHl8#SH+vp0!&6B9Oqwn zkEJe*ri0Zi;|tEBlRt1q@!?1*qafbnczY-G=+o%laJRVBj}@D_V~7_#k;DOHTr*gA zeUg8r${sn?zDZo=@kNBrStw^TmxzRA+awKcQLT`3Dvqt*6ShsJ+gPLQ&cg(WJ*2|8TvX=hE*j&SxFiipRnHZnp_E*T3~XjJtS zIC%uaoTCyn3Nrwq47eGoBbYRTPvt}}47WF)TJ^ki&|Dr3gL?*n_V1tY6P(Jc{`?SPM0X{yYdF>t3(P%AXzcVR*D!+R(%FN{mt#OBTZ(*qV z#qbskzUC(%;%ii&rvlIL8B;+jqjzVylryukEpN0K=r$1VLZo{ZnU0Z`~S&xZ(JWIybc9 z5?5DJ&7Nulr$wpavDdOU^fs}1t{ST)eU@JONPh~$`oPQ^7T!3#MlurM=D88Oup z+dQeFGHf&iT%SGlW70S_P7B4|cKh&du_zXpDU|s+A|@fd--MsjP(HOP)tFVZBlk4_(j_-j zOow()y;bFBeU*pT*V8qYl>)U3FAd8hP1<7$hcJ`^k;HR*l6Vh$h0(_#XTi5(I-Xx& z>49b8X=dheg_u#i<}hl19|+Tpt?P=YLj>ZIU*2s}krtM!=_B02Ej8AC8<$2CjK>=t zjVKx|Bc>XerB$4FVI4SJu`4U%Io3a*_)A|v3NhP!9`?*p&u*?GKQZF=_##o2zCVD( z`S#WG=d}*QF4HE{;9Cnl7{@is5_Pi}3j6wF`{?kSNVP*2W@cG|VuQ$H7AsWoE)`;{ zM2a)nl6=kiTtp!{?Aq35daw15zZA+#e2CMXD8ba#V=~Y_ZtCDc5eiye)LKW67*>x? zWiELxZHY6vv~3PU<#ueWnQ1lNpeWyDjuyuj`b~{g-N1t*ayV_?xDTZwm!(|fx zho-OKin8t6CM5+V1f)T_q`OhNySt>j8B$8RB!}*9q)S@5yQI5khMAB1eb)C2u63=o z&mBkXJ%bV$NWQS+SSA&8It zB9KVK87_TtAo14;3aqSY49Z#gac}%MG#moMn1!vqPrt_pqT%B9GJ1$om7n zUayFns6~Stm{x`JUF*sH@%HnB#~)mh?6#}M;vWw+4?+vQNrPoq%3zfo<)_z;y5cvF zSdbqC2%A1JNPuNS&2<7nqcz?jUX=~7Y*usNj?T<6(HpMCbe}*GO?g$ zo;R=SL37RD)C2^5>dAnfSD7f-*!=Yc>=Ef&6y1I=QvoVd1YH+2JAzxed3l%Cm#q&S zn|qNbtV?M6)+-P4l(5f6*oMVS&lFWu%A_I_it9w7x+_L{DFGMj&b@>}UW)L_k*%qt3Kl(@(^}^T*-%5NMAbvy&56 zBfr-_sW){k-bs3=SPt}=0%q*@bkVl7lo(s>33>GIibGM^%%o$vrr?eMz^>@^yR zNBeI|-qC-fbK5^wE<}r4At1h}+rx-#fS1DW=B4lC>J+7)^H<5CX^po`U%B(>sW75iWnfs@h7p=xzN>?d+d=QGLX`{JK}#>R!Ut z+5u+8NX`VBoWl#0DhZZ!Kll9H>CHeG9bUI`>>_hH9X&yU>C<8rucR4!b|Nr$$K$~z z2;W8lyO$2{XH_sXFPH)+!2ggg5;iW9Nmro7+I><;Xk+d)H3jZK%CZ$JwPn_49V)@M-iBb-CQB zGihwec4-kW`WVzQ?I0faoyNb1(IN^ZypNxQ&ej10uPJArexQLjA;a5Hl#?aki_e^% zTh%1EEg+hf8eJ~~n6uK~HrjIh*d>~Z6| z^tN#j%7UR>4(lCyR>oA&b`5Vac4$@&_MYzslji!JgR>5PV}j9IUJT#*E#p*0kc$kT zM+Y}=!*Go`lTZ3N32_$oZsA?TV_~1lC9hP|{rqTpbQfiOvhEsr0_(l@!CEMgUN*H^0q>=O4s$w}1M*`#0c1?G;mJXlJp=%J-s= z!#z5|#NcG&;ztLb~dX>W#M7$&6GzemDZsYjSX z8Gob~fCUs0--NvRL{sfWG3~7x_qwlA8>bb~iE7?WEzK}iVXNOz$%p*?4nMp^*6DvX ztedA@@`1%K&2RRH+b^7!Z<)Vz(r?)MR>*EDvH!kG(O=)2Kh7b+8hQo_UH%e$r><;n zOU{|qEwglxKdkPGry(P$LWT))3)@b4{)yp(KG0CSL~T+)-)x0b1kALQjjc?m3;BJ< zZ}3ueeZqRCGoZbI^)7!nh9{&*#9hJ)Yvm3;=rIMT2);-Uy&dwcJI6KA9FY;dwf%i| z*%=s!UHe}DuB9!&d1ci-uF5g1ZXJLxT;;gNC_g^Dszi%fC{`)+%5R2^6L7p6Isb1= zt{3)#n|(OEK!LpCz3Hg~{jM_A+Pd;c`)_@Y0G+qo@i#%i<~K5oEm8Z}x*gh@z?Yv5 zc{SHNVHC?hBIVz?)4D3b`rQj51e}T8alyi*2DkF~t0%`l6;l||78cL<<>#H4ZY!G} z-uH}^zHedFSxU+6`R+NBjMgRw$-K|(y`v~mTc(?vR|f3RuO;snX6 z=d~`#zV{VaCPe;PO|P`@XK&NV#_lR&i`}^@_1l}#ip?mP8IEl;CiyMxz{A6E%CSvA z?N!(oQ}pz(sB9a%iZ?ESe8GGCk2KriFxy9nOb2P|GhKEZZ%xk1_l#~3r=#A3{hjvT z>=JL_Ev{Ai(?E8i0A>}&P*3tqy~tN#OMlu~7h z^LQOOBm)6m{7&yd8JW*%uXSCyOok$m`%I&k>@NgGV`!I8Nl08vLiA8 zCjjZ-YWqs)G77v*P~F+RR_3$HTTG!M`xCR|O~iDcZiFBzBxJwc)o?r(+R&iZSsc`q z>)7g9Q%%p=9N!{0ScszgsD$EG3VF~mQ2{`Ywy)i?U_oJ_;I~FbWYY%zCK0)Ei`>58 z`%j(!#zyEeqPAAH~a6j-uihJj2keD(20iecVtQ#+xYI0@w)9(Dv^s2a~U)I zW#?1R{qw$woXvFJL-8KCMM?W<%fDBo&viWZTfH-Qq^$Wp2B_v|57q9bca71}w11=Y zwCt~D1LWqO);c(~jkUJ5GPl_aIPdMiIuj1pEl`P9?{>b$F&=EoxkN||gkhX;8b2iY zrZ4cY{}H;G>AfxQ3_BR+=5t?KW&91ArLOPqel=^%%Li)a#)jvgz8zgRX# zLGB}~Uh>65OskiUXs3+--%E0e)pXkN^z)`?~>`;Zn5l9=G=C{HfV0!dK*@BsVeT_ZMB zdhm`n!cZ<}0iY9`&&>9Dcz(ejA}n}dKsq}dRS+0_@ZBi)tv#2=i=W@;ig0*`ZnL_o zmu#X+8B2A*K03YZT8BW6tT)4HreewS*pl)`$OTgt587{8_LC7b-3>B?FCzpXTujYY z{G$9}7;<%Tk!1fR$@zDXk-m$i5yhGeRkq}EwO(d&N(%FfE#Z1bg-3g1%q_mxiYTg- zovP(|fNh3hrl+On3h_t#Dlqp5h5fEhUpy9yFC<_RZZAg`)UYE zPw<;hekM!OG~~twLf-(R#_D3}f0EbM{`cPRcx=}-;SqPS(b384d@dmZ9mt0hx{d}> z1fZ5{nLcqy8rw)2`aLgGT}au(`-i!$CAMyy)|XDH2sD+?3{3jv@vvtS`4X(YC9}Ua zKWJ6uQ&Uq1X7`6((TdjdUc-fN8`v49%YR<4<7oE7g>bzeaGh90@9?`x<<>Ur3ryR{ zM}U*$Y(pZ?20~gW<#d%vvVKmG3+@PIJfCXA?Mf9) zx>fj9?Lr?PFh_}99$biU_^&U&d2w0R#=RR;QqHxA0*f;;f8lP$G{CEsn@N(q=BAbA z00R{X2?4=^3I`v~f(m~Q5dl7g<3s+JJR*Lp8}r`ivz$fst;f4;AE>Qy?%$4|qy3*1 z;;s0;f6IOXQOxC|@}Vi1cyc3R&%Py*JQc6iiACvpNvexJ+O}k!N1@@ z6*)>lsfR^ZlUgOv(D&9IMk*i7RsWkP@+shq_gLB( za-jV4Iw$VJFd^`C*-{xx`^v~*_2Z!5kJhrD^Y9#hFxU;63rH>fEr0($(Cvx@1s#Cx zlglS&(kk)NaF}TlTxh`s;^nV)=4$BP$z+EzR|vXe#$=a%&`%?pqWS3EeXqB$pXTZc zc~KbZmErUIUD9w{$en7^_aR(WU7UD+d9mUnhEzT7&FFRRNqE}(3A-Y^Ds&b2kYI7~ zop>Bn^kAV-c6_Y2_>O|pQQ3p%V&Sukj<(5(qEb+Ne$wM7kup}EbI7tFw(zxh`T6^> z2?907pw85D1eP2gwwdHw8&4HX9du(uw@d;9+T(u&7e=t7FLP^@wBr)67Y&pirQc+} z?L3O&*i`CarPr|N^3+QU6lISsV9^;@^puj!(}gTG`QbMHsPi1J-7ryBc@9vCitA=; z&f(zBYRC#gI_d>R4z|5*>X@(2quVE)Rs*0*?ecG5LQ{C z&t>v(sYmFLB7gEUKh#D(DmW}t9{=LLz^iN*ERprHaS}(uG<>?K*0#2ZT||_Fz2R6l zMCM_pQOS0t$Ikx7W?|btbU#+@CyMpEU$yNi@r>~8YobbR{MV?1B?=j%hmFh}Uu7yE zT@?oZ#AVNLv`#U8)->e_$$rS?_tRt=pJ><w;z72r+6SF5 z4}uBW+0Q8is-~KUVe(-PCeMnW5EBZFC9DLeT=Ap^KEiQQ4%kfDsg0A|Dj*X~5gxh! zH0Ne#-1TMI-5#e)m>?R)zW-4L+vv?hZgNLw8w#z9C1et6P1Zq;vRn zFgE;9-A6o{AcvA%ZfSig?jV@|cFKI2a>Yz-)eQd6U#Pp0RnrscY2u^CbX*0+1sYwN zAuAc_>6Irv%-;iCGyVPj4~H5o+{mj|5OJWZqQ(!Y@Tm1Yj%%XA>*x>MjFI9{kbRvT z89w~C3$o$I3$Q26o zlBr&vHp?R!QF>&IjQF*0@tN-vx)~;TFWp`O)}zFZ^Nm3YD^Cw%>C3SDr;_tYvk-6e zfG|QH z$7onbum&{X^hlM}Pc)dEIHw2`o4*XkfXlHgp& zudPmzG5`m>Um-Q0DiEF^^AMo!@G0^i!zp^ecx~z!BLn>pO5FzuiGm9$h;2xKrLCP~ z(sIx>;>r2BYWxf5ccz4=7N3T77?znRLEY``zq3mIiHd9N-}q3wuj1!e6oL$kU*gL8 zWaxeGrOfyLE^|ZVH{2WDi|fl(0bJZDS!e5$Ka$_&zIR$}CBs58+codQqG@$IWE#rs zn>HaF81R}y*k!=S3$)b`LjpL_5Y-q-SAAF~(j40h5M^K&Pt*bFj!sOZtzL(i@?+Y^ zuxvx3@Yzf(UR6cV%1?cQuYFtOkvBmxu}ltFrv7LVPYnnnP(n77NLDy|GjnVQndgkQ zc4^*=K!K2vLA$1mX#8LFKfu=rpQH>4Yd0uqvnk&Fux&caE?YppgLuOpdu3nj7(DVn z5QUo$rmE85c+57(=+=9r;n%HV{_Lk1^3S@dI{pxZ-Fy3@7Jc}UCG{bpmy#JRgx;(c9Xa$?q$w#~2yte_u)RZ^D2dM-H2r1Q zk#x*9lVugu$Rd`x%!N5n(AhA%ixC31rD6Rv_y-}xhOzE`^~)H-tpJl?|Lq4Usv}< zKx~YRt}@VqDfAdLPY0~rso8trEca`fs!&$`uS$#!Lg-SqbH%*S-iM~1J|W3|&)vd^ zMpKC%eYj#=%ccejKs1Ohcw=BuUI#7W{_@gEASTTXy_LySDlu1t7(Rzvd#3 zK-!&o4b=1rAGvMh9F83edH@oAU>8i7{E;%OStQ8p9a6o~AR_`!ft|;~FeNKI%wYEF zSo6#1}Y!xpkgLzkvp0$?{ZX6Pdkg0z#a(-`rk^kW^MkG2YoIt zBkTsX+K~$J$&dcx(OD9`ZFV}6uZ8hy-?CFYXXXT6jkuA>5Y0INgv~xGSLtHV2b(#v~FCrVzjj|9V2yt}%63xPC%k8CE)CE4V2-U+{a1iK!+y~lR} z&y_iwFq)2N?)7(^kGf3P7d2n>kV3J8$EXR%k>4`WAWjszwV>HklaBJOPhCHG zfU#isz}u(PKi3^Lgmx|409TJZH8qT^Cnq)C=s+^3vS|WCaTM?)T%7iwwC9o$pAI;s zbu;h#WZWVU%J%I8f{6rlbVri545E>;m#TJJO{D8CLUVVZRzDD( z5`2MK3o3@sPvLa~MbHzCvR&J2DuVdv55+h^6@Xv@<_rbI$qB}szUNg!jfkOfttzeZ zQkN1*{+QYHACfPO&!6&fcmCi^E;lq*dRUZH9u8k^M zwJIhevwmf!lAwD1bUp-&vVtfd*k?P+X!v=8_k3pyReC?S@tb}6-+%7}Ag{1m|GmhW zQd|AhAH8LL**eX##?XiDL4ijKiDffh>|uQHFyNdW(X}WIH36rZztsc_x(TC~x^5M- z7RL)D!RO&!70hZpc3=?ImeRE`nxtTkeY_tm8x#V7>7T(8D3KNkDy^A+k$~Vd_KA2x z*HlVdObOrAM(5)v%2YRxtml6wkPytBp;*lj`GiFwU~pKkq9>iKK4wpDi%r5fc>7hs zL7-195l=I}q>_E;zes@(sSu}RfGb597N?=S4yG|pAy=Lu;+LC`RXT@sm#&5-d{TPm zlXv2bATEpn7(eUiCkaB_=Xh8LTj7WZGJahrYElZvW5a(*{F0o2&*U5TuDXEkkM9pI zyh{Orf4?|t*M>y(jWLQ4;%QPW(!gw4L!=VkYK;wD>6Q0icH8=YiN7NH?}$ElUPkd> zunP`}szup5*rp1SR*Vp=N}x6y*Jmm2`)HaHYbUfhY!(`yFDh=iMlmnOeq{eK6T2w0 z121#m(8pV2*dYm=YTghpPE@uJSIA&H9sk|xOiH)UF(AixapAZk@1iHabFvl0%z}7z zQte{q+Muba9l9ESB5T}i%b_g%%i`nv0~*9|aVM*GkDE|^#p50jhjySZC%lS@&%f29 zg$|0yczrol?2uCjg^<}J2AcFTmAu5*YhUpy6!hDQYK(vTsABQlb=*`&mrs`=s%!DA z*h2|1;nDB%MC;A=tsNxt&Eu|6dyxZ_P_&6-D1gLQgQ3GEUacbLuN-axBP-LlG|qDL zlLshNZ3$MN#PH~m&;4%ZZy^~$I@UHv6%=UNwcr)GY)SrW%U8|c9=pGOzXDz(-LR_G zJ^G>!J|H%fn9IRV6dd(f={z~&6T0?jlfx1~-mZr$Z71{AqiKlFvIZK6IZ)!m1x=Rp z!1d?nyW3l5h`|_}VRcd^=DrFNjP{|Xx5R7d=$R|xyg$6>jdn;qTPrJh+wI4|!txWf>*kvq?53m1hSFnW=sPc2gOZ`D;w4@U9D{Ir zYWklMek3|{HQ}cqa^WRxZXV`3;cpw;J=MjZGgFy7kF|gUU!EWdHW7hDNySmWe+xeJ zs3bhjic7TBm&;a~@?N!}e(AQo*Q05fx|7?wN0{e0{@k+4$Oc%CxsVEuNB4_4*T(k4#<68aDkS!S~! z1O4aU=&-L$Hu&A{1LLS`;BDD<$PQVXJW;edRt{><^BIhp6fH^h5S(QWv=tuGM1xI?>w#7>vYTN?RTSDiU&^Ce5c~WF+!0Nc^tqM~YqMb5bFRToo(SDh}F~XgRj)YtEl3Qi#lb z?@EtPKU3GCL zj-XK`0~xpWdr6Ggs+fz26GJ)EGdidTW$_HR!sSJOMMhu{e*emGWhIgE#&87-oZVu&u<%WIb1z~&pfrONf7xS!%PK2AAw=lsJ2~8_W^qvv8@ha z{KDDgWoVyW+2_y8`@rQ|J$e<9*UzaGcbd=ifqVT_{eF zJ~WuH9JOWCb3Xz3cDnrY}1PEI{bQu-f9X>_spe{-qn(8S{e zfb9VcEg8zP*njKFLZi@Q8$eYT^InPO<`hIJOfEtL<_vtc0p=HNkM$6^029M*q@&ED zOtRqPzcylw(~uPQi7sS}2Yh6E6rrda=`&iKqckk+^_>a;Y#AmyuH3`ESr4}}o9XdI z0M}~+s@ZN%_Q&eenk;SJ6``FWsWc&a6TD}i&@Ka~BQ$87vPcY7m z08Q@~6!qQhO%kL>(-bGXS6e9XOU8pcJ^poy`-Gg|=SnoiW}LCQ4`@Ry7!ia(Bl>_^ z+x87A1h}+QV)JZy{^ERGj1N7GCjIor52CzgULA5Xhey)6lE8%ewO`X5TeQP&lvz)Y zQz*hW?$}aJPPI$51N3VHRPttFM?FvG&fVxS8ug&7&XtXg>Lnzmg`zX=P3s-rV1X6H zE3%0f$iJa@;bKN1a~dC`-mPM0SjFUa;7hb&r@vpl;Fk5*YR(0j0>E#}sfhtOWILvX z!FI#D1J?ZLZjAGH0QMPRdb+iDF}d~%)i1h8UzhLC3mPhNa$|0pJj^M}ZRKm{vVh>H%W`ih62 z<8fqraUU!Dw6Yjmp3-TG>XHTx=I|wr^94hp`GTBFwBCQ?S~X~o49j3xgDax$e}Ms{ zd;{8_&}byN5D+M|kvx(QNT#&}b8ntejRnX!3lcQga!EN<&LvWAtorHvKTvUGE!&vu z5qfZzrI?FV-7{YMyuVYTa5%jJ4m>F1L{SF{MZhUYaPhi&Wv12PGi~&mJ#Ya@@Qlm% znz#RiO8f5oQM4R_ zgOh0k`ARiD9DWGV6L^sgO}tu@z74?EuhX^&c&{^e^BQpL-b*WF0{vS3lTfOUF9lFX zR8T$TuP>t*7HkN3X(kQs06e@D%`MKN)1tK1{Ompz>&m{Y`PuBwU2J=klxAYvOIwM_ z9YZ?Ex?JhuP}(TIb~k2{E+hIVCZ{~BE+P_KVjd{9DTp=0_t;rdYPj{94Pzmo-%g2d z{m4+Ta~HC2oGI9aGE2k+=az3fBU&Cr{r4eci|ypQJsDvx!;}lf+l-5ZB#Md@im($V zF0k+c#|H;z=UiCOZcZ*w$xJ|EuShvHM_g<}zHd&z)k>5#g#`j8ZkTI)sr?qhPaiwB zOV^c=QiUkY}0c-PXAhPG$fy+u%EM{-PiZ~AK>}#CE81a3#!g$z3K9N)x9^GDDLRR zA%J}o+E}L6G~We0`feGutLyjv^!PmcWLa04KxIFS)~+}9tLJeP(M~7 z=l!`PJF)wc0z}(}t4@7=fOkmUis!xXzZcQ%-sf1oJFS~2)FQD`j%N(kq_l=d8iXs8 z3ASec(?5Il8eu4SpU%CkH7HqVFv4<^uzX-o3a;Gem{UHSX9zEEmzxge#6T_zv^eap zf4hW*&)Va#$?LmE2+L&A>osb;y={>g1b>VDg?S=lg7v!7I~L&$Q>$IpmTXuE>FMxx zJFm6HY8A6kPH#~WvO#{yduVQ3=_GR8;XnEDrs;o606R`JZ_nSGWLI2_^4dK^#3sgBHlK4+jX|3{JSiK`4h8*P$aGaX=v zo?fFZiYGHi&uhtz{Jl12zA}GrMaXS0ay#+VU1k@v?t}m8$qVo!Rf{N zbMk3;I~tTY1PXpYO;KFJn5ipQivl>AbXw9EW|IQ@pje@~m7i&B#U z=h;`BlFrt(6)$^X_^Zg4+N}x>l!oj{fCm`6jFwhLP+;GtE!j(xvX3g)O}6(D?&FL& z`~cp)>#iU%625wM`RQly()E4~Lwn|d#OhS4c=gDgfOgptbFJS5vrer=76niOV|~S( zJYZC=^pD+bbcl`yS^n*_%R)2uqkZvBX;gVI?!_5?Gb?A8Qm(Zv&KEk@XPHLRG(Jvb z)%STNw<}@Q6H*oZ@J@14C5R_cK^3pz;X%ocAaK65TeOIVbAi&Bc zB}j61u<^!DPM~b3W?_tYvI~0#+$-Q5nshxzZ`v6YU67XWk1%6D&$scbf3rKLNU>9I z_vjFYW^SjZ2?6`Oen^)5L-y5=uoIJr!ou`l&psT0E+6js!x*$|;>(*xqH96e&b8fC zt`TvEs=4S+7BM%w$Wn@LSR@WkyA7%|6tvyM8y@o?4UR2@kW)j4BI)UqtEYU!avY4KwzWMjh7VWt>2t%4;&+2&V z#dASllV=Z7da?H5h(j&^eRU{_b2pd(a+uy zGG#4B@%5C=;5NQ$E;*^^S3Sf?loLl@bT?`07P-++-X;VN)FAy%2n=N|?19MYTu!t- za>(TPr+O8MQ4Pg~SWJ)-nsehw223etS6sa)GGMkkZx_hF=RuaqDyun6{A-i-l3~<= zX#*f|py@nv~=J*)=4dv1_fRHU8Hn2D=s*h3gsXWv0`j!Y!6 z@SUdJz~S}pOyz3C%017E1F2a9B~GN!)=g?xs{oExYzH5RRSxG&LFwhD<5VH=k&YAtb>7>dLYCMNQBN$a z@P`4RNHuEHW@xDEpJop-)&@-3(O+CT6VqAQtOh`E@neWKkMWL;@lsLyjy{UQk2`P> z+%AlMZq7w(XHUhcWaZ2RX(TH9u_v^M6g*q@@#GuOPd~c>NI`KQ2hb?&XU+@+vRtHF zS|8TK&sOh>{_g?v{WsqQ4#vzR2KPnc!7B&wC;e0j6*!5GJ;~{=6uvr=Os~#;poXi% z1XX7~^jrUMq9ZM-M9VQ$3!W>?InI=ERd#r_bb#B+NvoYMRoOj@|M10&@voGwk!J!& z<99C-f46|e6FRO}dOf;%7jGS$s=#ndQd|k#(Y9Qxf2E}0W7<4L z$h&3Ut##)pv^a+pLcv$xd+E{rV(xs|ulR)fWF|7)W1W=TOsvJ;+l{*7 zu5-?K?&`TkWAs;=8W6i~BD+61z;NW?eQL>!iu1J*|LNu1vPX3zBas{xEO}%69!A4U zo;MJV$n^n-d75sEOZE8BwQQcNVOWaT?gs9w^;8j#pTgRyeMxu0(%&kXASR%0`~XLr zj7J;y_#vX$aD(S|%35q${V8@%VqW!U*Ho*EOPhn}X((MQ46_^<;>3XAw?kUr(Q3E_ zi>#B!IF03Ajj==OnW@zkT5a1E2;>=GmT-{COiCkXAJm*tg(qp-tXVFp0L9?fte6J6 z1@51Ui9ntTjdZZOsgAawJ(_uDZp!ATpBvx|7!Twe>MCm52XP4Ek}qTwE4_< zI8cu;lF^^j1^@gEX_}|Y(|u~0r^zcsLsn4jW{cBu+#@)qD8PU1*qVJ zNMoWn-&eE%Qc-n`MVuX3>J>jHl0~VD?&Vp-e%5zQ9&zc4ihjqe<4|YAZlXW(R%;#6 zj*Eh0xKl8=^2>ZDBTlJ9J$cSeV?N>q?XZU3G%HZ^HQkGcwxjQnY+!PF$;=H-?* zGRoc19*+7p(z~$|C$sTlL>frO@eL>Grh%eve`!hr@|QE^h<*2uP_;|gSJ}IjZnE|B^ zh*|udUvC+g6M|dNLazJXKCVF>{L###tL{ehMQCXj?NFKypSTpE5r6KlfniMKx~g#V z*aVQ!)hTJ*bv3}j#B{1I2IG{H~(#Po!aH}c_wqVR{TjL)#58# zfKI2OC`7vu0j^mvi^KzRqK&-v+Lu_xr<+M9>5eo7bfuth1VQd|^6aqLS z-AwZx(#>fB#^dlWzDQ9;4N<}!tccg8xuo|*;!20QvIFZxmC}k{ji}RRMVI64vH$uq zY;q5+s5Pp)dXLi@h)D1)uhPF{Zyae(*SK(x1TTlVW$-@Gg=hKV@E+~_>Qt^~bLZim z?bDA{Jhg{HUdl(paSHbuh{MyqVRvof;Xx<_ex~!fRk)Va8{IEWd#5r#%mkL#E2n@9 z`l&>SCD1zF@$$9Fdc|Mp*rdh_Z5$LNcs$DZ5waU4iX>blb!e7TA||jol-G^Kyy{g{ zR%%M5A9dVWXvpY505Q-&X0O5i7Zoli|rkl|zTaNfPv@?}#9i`-5Dj5+w zjgyj#(xGeWOKe7!mbB!yYHN3ev7gX-^AtH*Yf(w9I*JXxe`}fyL;65g{$bpe!09gT z{|$SW6i9og#8c3a=w_0mCn?wsSY6lo7x8~-JaY{LXr+HLSUocd0mUwfVV(GmC-37@r#~=7C4h5fV;KGZ?}E%#?>0r^tHPYOB@70 zi&bBN`_10OW!Nzwqwk8OezekZtRwdj1 z@j%^}J?zFr>f}Z=^^=|7Bu$OjA9M^I$55JnbH}1Ol{$tM4EshWU0G>F4yQ`SusO@V zKXLXHzTYlJ{hsB5YiYy(hXid?;jqA63Z;j?Lq-w}Kt1-|4K2#R@j#HXo0>Kh*o{>T z{Z*S{$M+iR3$_vcAsb}y!YP?!FdPn;AOKP*OW1({sUzwzO|uYk8A zc6FAtuqZ+Y1{vxrI3$4AJngl77WZFl^_>ts=ialju_YH$--TY*xO&i%c=+cR+g+W1 zk>LL-5_4BF`z1XhH`)3Yp(mHUI$FPH_)^G|_K|>|bsP z+*&S~;%_<&z;_vJM%45wIpT(_;VTAA_t*m!n?4*1V@T$p@+_|uT~$PvZ}*y^mT&Nezy~nD?@z( zwq^m(3U)pEv|%{v9oqomfrhK47)Srl??qV(uLxdzNk+c80Rz|{hY}XFTa{oP-keZ2 z|I_GYgO%TI7q`S@ZKU(FJvYC`r=|lWE9>XBF%+^Ii@*=zVT0RX<_>MIkNyx>%g;SN ze*Hd!a}VoQ%6|i@Q2Z!su=&-|7SS-^G~oD6B~tgRNa!(|CE%0V%B5Ww8sfOq88>g* z@#}QiJyqMo|5J4#AzjiVg(CO84#mx+zvTw}kY{NU4Kef|zi3WK6SyS)W*F{-GnHIZ zOyf*Ar^qUU9Mo$Edg;@pGqkRWIPQopqwO@PvA@x4O9<0$DB-|IY~Qp{q&QE1RH1uc z+JQzjz}`KaLH0CK_*3q$shZ#qLy@3!U1J%Mj$d;R0;-`WV{z_Z#iB5#M(lTl&bM-MC)4qDm!vv|oXIGuz=P{aM<5`M4eqaf_ zsrWsI8K@_RmP7FuLB*EDY2$NX7L3oxS<{SZt#xhflSq$>&cP;8{xDp`qL%%VDG=(g zdAGea%eD<&YAb0hL_iObXgkFoNgYD~qvr08p;hVBX&n}{O#Mj^LoVnc_aC8R0H^Kj zTJj(N7*YQEGl@13MI62Gz>Y?{8wKRYy}0u=D77G^mnWh3^V=;Tjj9|AF=#7fCm~4X zlUeH)_D094*oR#)|Db}bmihawzZL{-;(yPaUp4mC&ap);`u}kFcY_+| zc$wi6udVvGJ^jU)+#71b*Rk0sd<}ZQD6rTC39~P7v@`Fk$5o`CfwB7^>>5=L-?2tE z2NG36{D&RiD>0K*>Q4ewb)W62*NCg0^`WNOs-rvi)z$@c$1c z*t(-^rlh#q_NVxD2Z9N^P;=(ir&n&>vzP{5%ge#x(24Q zOQNB}kz&7t?{6EN6aOOdc5QTGS1#gg==zJ{MRur~ijD&HkZcwQ9{JeR#z2&R4}t^U z>6n2AGOe}vuB`DE34q1B%jpj_M>1a}%k@k3N7#M831eT*4?V%KI3@cp4Q6YXn+c~u zkKCxE99?v?lZA!UtMz6y@`AzLE)l0b#T4DUcOs2Na3dPV>71F2T>0}1 zdq3#?SxZzV%)n0HQ5C1U%51$p*&*2p!Hy4oHnWp!ZsS_HoNE!0Y<4kEsP+n<ns@A13s}#QuXNB;zdPl#w+|NwB?$`3E3{LaUTB2e4 zv^JY@`k+>9+4v;n`QFRhi~<(4vFi1~gnjDj#P(`8;Wg$TX}J0EyFI6T6TAkfxY_#> z1Mi8wmUYF|ux~GZD?MyE+x4Ncf*zFYr3M56w7d&=k>PExOk8;CrOx(omoShW$>Uy zi!;)iN;O4EpC^fP?6a35*~wSmRB?mBM1JJAYmo%HBl_5N#rX>UfK+P|1^9 z_0>jSJkpja)%nMF(~9M(LIiq?@4|hDLH|q`L>^j{m*)d7kE+ z@9b~ywO2GK0RVt`5(M5|MR*jMsn~P=Zavhmk+qBscw3TcK!$a8d_hUcB3Ek{6EZ3_<5~C z8txd93)pw6B3r#uX#?&Gf^1lTm6bOUMr?rNaQ{C7PoJ9irw2a;dX`bE56|Kj`dd6} zy>)mRwz3>q{zW_Svh15yaXY=`vT+bN#-BH5L13dUwQQHSFy#67YucQ#P=vyX8xm_m z`(TBV(8oIr*L47j$3qdFcly=5DXd|4slI7}&6P?HRu?-O=GJ0U8k$ zp@Ta9!B4Z#V%)N-Leol_$MHWhP%?Wyt^Sh5hV8vF6|)dCV%;OLz}-_P%L+OC|0V#4v7s8yCN?DePG&b!sq)5Dq0 z7dyTcQXH{Rf5FLIZdTT`x2u}8Io5w_{oC!90EjHY`FsGMeQ>UJkJlU#WG6z{V8_6Qji1 zV=~BoLqN9c%~^%9Q1z)ySV*Jrmqj2rN3={HBVkuOAeHTu7L&8r@#wcyN(lYRC)dpu zK!q1s<-=iZo zITJKDUM1ZSk(3}lJx;_hy0YJYTQ<1z_B)~YV z-qgf67)XyLMVvmkk)?czc}dcCaS=i;otwtwVYV~+^x3dMKRao&uPFk&!*hPW&XkVN z)6V;#YD}gCR=CR6-e4X2rrUI8a&}&2RPXmfyy#`jwDd=veo(5vpkoXkGF&N^=#;!q!7t~ZqN+0(r{A%6 z%$qq1VsD-@zLp#U3RgTWU355r$1Yca&*ChImqVf*4JvFUw;hj+OYwMAfj&MyqhSl7 z{%}`2cBgS#HA?5WgBG_Ae)K}h`az}Ac;X+2Y&)wjG!-C>+lkSKCgl`3cQ8r!Wf#W& zfRzy^_eGC9a`u))f)V`ucve7{OMPIt@@LV5lG`f)cH}~_{Z3nyYzP#Xf!A3ej|WiE znu6q#;uvg2?Qnl$ta))XNh<3)=iW>~EMxiqPK^#p3egF#2TvOvC4d_LoETx51SnJI zEy1K*gaI2LQ{||M;WY@^bz9gW_^`UW%^9j)B7E~*1;NVnGK~_=XR~+`{Pq(okvVHz z7&wfVhlMJTR_I{bEG{nWucCnFaNA}th#h~-)UK{$&;(HIv443foSb(lzPH3HJr1`( z%5;+vmU6Y?c6u_p+cMDAWgbe*5^lf6@T#TwM%WN}<=pfv4}5XSbfME7%PubAKDn=oMynU@|jNi+>Hc@ya6++Q>o|0+QHzQh9S;cU)DsDGE( z`6llf^kO7nKHz)Ly?ZV~Ovs%EhOX=G)S5s!2_q4dMZ!h`oqXX8yF}QA?ICUA*-DFa zG1Ti)6Vnx54@MhfnYE@X`?{x1vxIULneHPhL z)jS&zLD#32uO?DE-OVprKAUB|gf!*lb$YY&Y{FOdpp>pjod&Cj^hmbXVXOD(s$aIl zg4b$ZG#_SYV4WT3l`uJ-{0Xvc()w~+oZA0DL(@x)H%m4uxoRx`5uGzJoRB8!o7^=N zFodQ(>AYomn=a3o4Y;^zct7?6<(zH@KIE*itzmpjZi03^q8NV4Mq`wG``g~1rzbbd zYN%*a{h-bdBSp5m0G-Ft+=Po)hmK7;0Vy?+pUz)s$SuFWXj=?b=@(j_LhtFi{N|yz zO*xzl)y*@3*^jT_CrUr@)a~d^-ksDZ{~7)hAu(|UPtULA=GMGVsQN;-eGj)Qo+qhk zwmM3dmL;h&f9(ffp4U$uIM^nquHpQnUW@0iCA^O7VpUqMjY*0q(AiGNV60oF9gT#O z`)NAU@{ri3W-v%Kn(Tw)^wvNd)dn5L^1FBQy%vwlQ(e@QDe}w_`ueWZ z)%2{gG+0iQn__wbYOnflFG{Y?_#dQfLqg9$iQ2awnks)Q+|6@d%A1>Y6R5=LV~IJF z_3_tjSS3-Tsj<)vw2(gc!Fu`<;pRcM3x)RYoP6{+KY5+CxBJei)2d<*59mY;{FQOO zpuds-hK3#@qQcW;%_-&e(^LVhkP*xCTmu@lKttE+*A~@p8)%)^+^YU!(Al)LeWE#XPWc zNTu*!`vU>W@9pi`=2}vCj`YrFeO?bS|Bm@md5PMfRUk8p-x2-1B-q71|63vmCcb@h z{$;@Y4>g2|Mwog$v+TeiEgL%0Y}r$nmdqRZ@`mU1AP^yLI}-Hlt&~2-54vryJJ|&* zKGgbaxb9&joY{Ws%2hdcCw^>_yv+EOUP9qHN`H?t%%#U-6LlBESW@QSM@(@2fUWW| zA6a_d*C{CO_0KmV^=FZFPB={+VlW#`t)O(P+$IukDT6(Z5koyTQR9aWJHJPZ-)cvp zmVG#)1BlyG=mrJQbJZ8sR`LY=>u+JU@aBgn{NKKWFoaA2&WC%CBJ{9Dt*<;n&<2jq zO`P?uR^Y|jS5ImsbS&xx?&~vg(AG0DP2YU>!}*DhYF%A5TZXdSTtebIhngby`ik>< z5v6z2%n0M&n}-(^?)pa)b*)lK!sSM3;(VJ@#k7I~Z}f|wbClk>MI`GF^7eD}p(v$` zqHeyHt(Mge*_1od9S@khIx0sNS};FVhbJ${_Km7jHz4RtJfzyYSHn26?=(T=B#s0TlO{$lG&I>DoSjCX~wFLhO-=2~9@K zW-+JTOz+Y@X4DlyEN`!y=g;lJ2}|}41^F8Jhym!6IpW9zay7S(4NW#ZTJgEbLUG1T zSQ8YE8;?)5H2z94x(>-WLiCAeLAT&nYUrNbUmY9}ZzsVSsIlo|>H8v<7-h`XMyAt-y`pc@pX(v`OM1peQo{Iy`1wf)Sa?7kG zb!fw1Ih1gwF?h_u!na3;dd;v*B3DP5$b?PzzXLSRzX94IpWGS^g_;&l!z{?}ZOz8Z z-f(t-haJg>2j)e)0#}D*Wp>_&`9yvRP`YltIV_^oR{o~nUFU>_p!=QxDY<>cS(%FA zV!+lfo{`SVix4uRI%(gpjKehH61V1n)3yDtMF5?@mEMB#N3909!QV@d>%UksVW3hT z5_`$uZF>#TD*PTJgtF#2-#n7*RO8Wzy|F*}Re_*}o^#QgI~=vB_s$?Tu+u0+~BwQ^j zz$yn_EBICnz+YuY>we3?F9YoQR4c$2a`O2q3O(P#8yxyw4co1kev@!{VRdFJY`Ku*=R(HPsj|VZ!(6C=i8C$WZ6l2as@p_Q&j6`-G_q_QyktagDMn>M8|4 zDhUl~pipI`_#%Qo{O{u!vn9*~#(eK&J*D|N8C6epz@&(@oRO5k?{k$(p6E?ubD1Ho z-#&Q$0@B7TQMf?sXQgptucJfV@tB1?hVr$VCeA{i0=S^cG)yHOL%dfggwv>$D6QL^C)t(@lD`Wic zeS7$CD^uRbrv|_f`-ag^h){heU{57`zi&4>VJk=Uk}`EYppZwvIi4#yG_WNNzH-Z# z(+~ZCoo(da(EWkx>_*?w;^36kXfQUYZ=naPe$&|0j`HG7OUxm2{Z7h$dhjW!DpE@c zCGn@-hK}4|iIiPNGRfk8IA2IB=7br1Y`ZWgDWr4O@FA;{lL8x`qC;$<5GDO ziB!K8jlrg4)Zr1ID6;;kh;?f7dkn%%5mKDh0*!>189yNqh@Y$d>%gwoXnAOD!jp37o6`) z-gA86uM$PGe4fqg7TT!&_S>ynG{5KWBf5q8g_)`!1pgr1>Gs5DN%+KYeu+WN&a_{R zRdBMq)(`7u@skAmQ`gJTZwcF^Mqgm54v`&qD9k=CDXvkFm;f{l{Bkh_mzDj4S4#nK zEGCof4RQ`#G#i7!EN*0ZO^~Io`y#yJ!f(*Ni_E0&74-}1OUb}*ViHH-#nAnslekWw z(Y)0vd0#s8TUovhr*7r(_lHI?E_JCBDu&To}AyCXtKV5O25aTe}k z^$7g=tnIT6{h_BiNDufbg7(J=O@c>>60W)qu{dtCyeZ;V5V^gB^m=Wi zM?`0*OWJ+UGemCD?Yw+$-o3{I(d`aFQV>mr)_F@m-q6ZEoNmh<#H!X^2!1?tI_z$T zJo1xu3&i87`fJVX_c9}(*lGWD!cO4#@|m?VHN+r%qb)SDac^sqp%e+x7)m8L%&OFE zj@uBgj&Ka8I2WIC?xem4a$h+U7In%09AYPeLdLZwN-k4j(*NE+5|StKKQxZwC)y9h zU~~*bl|q*BdsFE)Ul#&L|E>4n39I9U_hec7^nYi+RRc7!6}vaObJ1?DeUHhL8na-X75>2AHG$gMe*=Ub=4-B&i$&g_#HdL z>^Be@^)c}m6&IaGw#6mW`20xVI>a&fY3%N7g}GB)yw3ZINx#kRJD{GhsiCu@aGH(Q z`s(Hb?<{vFw$pqblCU}_%c1JNdx~(o@$sQy0b;hL87aL`|arWlQ71+I_}q>i-?z#J5)Q5|R|&fKR7 zVw4nAUem2HE=oWzzqc?HMse7LxM35%#Jb6TD1V3aWBhiSL=rERSFE7m_|mexx*EwL z^q!L<5{#l2i|KgG&i;kcJ0x<)htnMjQCyj}1WM{3)a6D`RSzh-(Trb<{y4OpU;ry{ z-9l$y(Q+bn;EQNf4$HGSUJDYPsXsNcQQkD0Oup=hYM8iVBJrsr)M}q3S-;<2V%DZ+ zmB8h>jazB@!z&kGLSGIo-+2~Zj$QGori^0tF5{*i*_m5 zTO}3BW)xEjzGX$>YvK@^fj6=SQGowFD>0I42&=3i1%B|xHosDGx;z~|x-R&=VfHv( zcX$^GAi!jYCHaNT14W!M!1!EmUz-%ufDz1)RS@72##{2t%?LcnOTq`eA6;^b={KDT zQQX!mSYq6aD#-+bOCmiB?Zz*#T@q2K)g{t(DKNPZ!L?c$AGq(y6VK0LSkmaK8l=!# z9Fgz3XvEyqP^auynnvo9Ef32BZaIXeix^`QwBvNBn(uo9tNSmbcmemH?Cob}RzvC! z*>^8XVrP~xtsMUH5Fxz1V|4Vv0AsE0k@$qAw%eMGiObF^qVaoDJ#WrP6% zv>qZPF{}MN=}3-&QX_~$#eRZ=9qwtY9c?ozb!~S?ciCswr>g-d0}k1t5xDs1rqSKO zAF6~CY}E55NJzKu1-qyj_sD~8!A$4= z;#30pBeV;#wX=|TXCkh73QNvA)o8!#uTRtS$vuJ%MXHNK!fSNj*t}7Y{&#@z@iXz^kP#1Ei}c>V zeJ>eewTIJuTyhNNVarV~(25HxMAzf+ac9;sWiS5oo4lI77+J*w&aT2<(3oAN_B7E4 zrTh;}x*=qG*(tq$`+um@#UUfAl=fI;X^6@tGDFHS-atiX|w%32kHxg@+ zRwJ?pqS8p8+R1frWPX#LKU-n0yNdR__oFDTIJg{85;~z%Iv`Uu4M`;0+}mS1iM?dk z?jdyU4>Dv@*^FufWS(R=tZ|MtiP3w<>UL8EB=`*ENu=nAMl5`!q!=kWaFFCVv;LW8 zaC}!I63#%8Md9>SmfXwEPepzHr}|00`y&k~{uhSpG^603a~HhpTgmdNnA#zdMOQm5 zjUU5zA+43tmatw6Ls!0H3O}y^jKip#vq>+vFpIHi%^P^+~7a zPDDqdcmbZ0bg%x8Zbb2K;$D+{H-(KMCW+xxCtc95syM^|Jqn9U5zo0stm=PAEVNQD z{u+at#Xy&yY@tC*CW_j9%PyZXkDV?3Du*-48Y4wIC`2M@h`xGjxUBS$eXtKh)&SuT z3PhHiA$~XN5~)*G-ur-0?oxh#K;U&|9+{ETKqE#Mbc!|)eO^ph5kk@it0s(T^~}pt z7NTe8;Q01%wJ(FQ!^W9rz*Kx`=UY8^H9GJ1vaN$&@6p2F6TSy~JWW7Q^_7pL3{UAG zU{0t+GVKZR^V$W6eDH1)fxNjzb~;`R_KRPn&_?X5m1ak3I#bbombXsFmiFR~EDWZh zmdXSIP3m0hEr~l?D_sE3Tk0`y?;P!I(@v`$v`f!DgGq6vg68~J7_@n${g%?$eOArM zCx#!8caR`h0DsTIze3KJVdjdlNUHinLb=wv1xST8PL#UrSn@IWhu|$1aq2SokQ|MK zQE+t`>rDBHID*urfbZ1sEbKSL=+hpGE5^Y6Nk=(5e0x6j4-s#*};O-m^P!QS#UxhXn*geQcpCDXX-HfIXrsjlVGQoNFSKD5f_E~Vg zOvjNt#%~FG0`?!DO-%?zr_LM1-wmoV-FqZa52;&OMY`ompu8|@Xi^_0@~hGXIVr!G z?XF%4@!s9%=>cu`B4eY0{+JC_$qFiSCqms^KRnTYndG64h1tjsDTagCr^8&1RIv ztJDA7QRpShj71){`gv`r%LssiILzLYu@+A+oV*1(Gy|ArG5!YKL&*pd4uga_a2e^? z)m)MDn{lFHg|YA#X!V!62JQd1q!8<>(KqlO4c)W*P* z@K;V)(vhUuJBo#m9C z+MUPTJIlJ6Kv`K*Gtm$5I>)w45cT`l|z~3RRvH?@-QX6=p%*zw;?TZU&zXKZ1BI7eYre!j-kG(kkD*vJ4qX8z|{X-k^ z+uPt>Vgv(=d!FoY<9y~9XwZ-L-*M|(v3y+=sBvlavd#2frr;73C(LPbs4-dK5Pi|#zWgh;cYn@*O zN&2PVUQK09MgH3n=F)aQcdozHCPGw6=RsDr+KZ0X3pvl5(@y>&hqhF zu`WQ(U)~e@Y(lIM_jaOrCFp>z{U^ed+pD9%S<*fiu7RW}Jr=eWn$ARF_=!ZK9=_Pi zd*5|zcRVq~implK;<|Z^qga-NbOaA7r)2e>yN`>*9vK@``d*fwFG+<{s*IiVA4>9{ z=ppf6L3zp)F0g^~SFw-|H?WZ28=1y7ukOS|xxH$Q-;aR|qJ@@Wy1?J)%V>vqHY89o+3`f`<>a zD>XGN9#7@(h6i!7G)fbRTCJzey)OnbuI~qSI`Z!O%RYO5h?djr>4xOuzkW45GWjtM zo>clzXa%>HG5JqviAo{O0N=?wp!`HQ4?yr!Wyw~b+G7*X@R&bdKW^hxQdWHXDlxIG zux5+lQuEJF=c|~JW3GilsYD&r;*YyB_ zKY#{*09;Q2k(m*Sw*~i$Xr5c(q8tX+q0r~dtSn~GGZ+^B87U9{U)lM0G+(4?olE@! z8#x=8;BDyrH(Jx&Tkq30)Rd!aYpEW%%dQ`9FdbiBQ-|^vaKgG5w8pfPxZensBhjZ^ zyS{!aE)h#`XMHX&#=9%sIl6q#3`82{z_ zUoYibc;o5?K5MB9N=)jgg2+C&=m0t_pD4p$;EVKg(%wvrI1eZ!GyKdM4OYqP!(SRe z+hQW9{kHRBP<8h*ZLCOeQ$pbrD1d>3hdRBXq2WVgL^>{a*ZJ#&vi{m&i!fXv$^WtWfN=_yg`GKT_9e#~TH83)ymG{m^q#<+_-|34Q%e0vhhNI5EQza%P> znFv63q=`acnEheWwKb)eGaFMCyy%0=ey+KG8^OPl7vEo zpwN(H+7Z7$P;ZfCd@kz&A1+~BJw%?e$q{lKIz%78mIOI_x_%q-<>d@>ro#{RF?wK5 ziMB&`MBB)8WkY&Sh%4>j0li6~L0+#J(SzHU*;BEP`6sC$1{muQs|;sSzCd%pSwNG- zJjzO${!@*mwAwm<(}M<-v5}Ey$-r0lf^f^cP4tB!HTD075O{Uyvl`vzB)k0200l7; zp&0?Ytq6gvq!$Qk?LTD{o$Rxa&Lw)=I{8{lZO%}aDH#H}tdOR%Cb!R6oZcN>aLYVq zij=BC!(0EG@}10eE~T@SxskC|*-Pbp5VQaUY|QWOZ)z@M*t_Tb;kq|Y#KzGr=jI-w(!jI3|m^-u1IV-}$(LvAKoEy#8^J;Lyeed3u3K0vAWCBh9oC25e1C@}|fO%gaBkK)-{b zg?>*fkmQgMY5iu0oEKvblP)AfzAwXF&FiT#qX41sY{vFrtTgGd4DLuI!H)sZZ5p=3 zW_t*$nAslm!PSM(?{bs(-0LBR$Sa#^*D_n6-0{B!uCupR}{0%I2Rb>QPe{-~0ld(jaXEm9dE`yFY++@FUlk+|H#s4A} z#71&qOgSjTye>-PqwvMd_Pv!=2J~-ajS>xIIu}~gfVH8NdJ;$9J@nKQ#DIe%aOw~G ze^W*xBr~jTEjqHl@Gi#`CBlix4|r?zlphifFd<~c@5uh5TFa8x4JAaem@$11xRB)p z2+QNYu-=zQA!G)BXvjN%I%I)*HZK)l3*dGMw0yJg|0Y0AI%nElr__V1@yOe;>6w>X~F${iZyD$>7 z%T8zaDTLNTL8nHa-B!1T*x_zCa;gc!U| zN!x#Sw172v_$?OyFo6ch7E4QF)mh$L3az}I3J0mc4*H=dGBzHzf}(ta~cC8dtY*AKci z77H{^!>wGbN{XkLklJ9|S!r@_pPQc>4n{sx@-?g!tMkPhR5$9$f1liC?W~1?C`eK{ z=9dBgC!7=u_TMhqGlGVAF&fz|=PTYBRQzmFsN0{2RnPAmw^UMU^nd%^q~0TkPzvKs z=Z#uZgMi@BG{#P$VHcvbWjZFnN53ZbtDsuJnKdAakm zmele&{L_=6q?&1J4&rxESD!kRrtBB!x)o(vJrn;)7;z$QO zuU53*R21wG`%r1GYna4n$nZsl(&L895Gi z)`1xR=DdFA&oN)te=}D$2`-3yMG@$Y~B@Ltvu)uDPGn8aJB`+ zcvWD;^8VpU?-elcB4p-EZVo=RZAAs`&zf%nEW8QSq9H^}0p+>k6zqesJf(xRD!muz zF@p%Io>3{|r==7pA%d1< zwixOW4vU4c&jEu=W3}9RX!qC@;=tH;;+gEytXc)OjW?UjuzUoup0M4YmRBLCWHx28 z=txiVIN1-rJQVU`4$@EeqCEZfy0ryvhQE-x3KBE8P14ynAZLCLo{Y8$`k$wLs!A&~ zRQl+*N7KeGx#6)2NzcFWh0ta3axi8Ji!j)??I133HJj5fNRMtHKJMjy0lXWgidt%jWo`vBLh(*CpfMzPTO6ju!qUe8bN#=bDgU z4KkC6;U0&w)H)*#?<<_EXY(DA*UGg(;nL2HblHdDv-?qy+y;9zkNMv;Uo=#lyn#W#PFZs~_xF@T)jhy4o1Z3?rB)%bZ6G{9&3UlYd+2Bj$8;dx}BE zsB)#co8JLQKXmu|q*f>~)XE_QnGrFkdb}@7?t0?4ew=-yH||vp z8W_gk@@jA&zWyek;O&;wd@{gjnJxVosg_ge+nrHkRQ_dw(v-61Z4o#tv1>zd3=xok zO^Bo_^KG@wK1(9;*>d|Ht;(XsKxH#;bGgxnm6LVaH{s^5XrHe@+KE+GB8@m(O|M-p z`$G-rHk1^H^SCQrI;x~x_!pTTF08gLms#-9;pb(FA|7ZU2!Q$HH#o%fw9n17ARJ$c z?w0Mma7xt@v6e|?M;IB^fg5_YbSM*EHHQj#N<8xibmWwlUWyUX{g|}lSPa+ps;=gr zGEwGk!Wu`bX%FTn^3bhWu=xQv?LIYs|6z7|x}2C6OK5LzT&G0t!-w)cW;}0{qWD^y z3dwV^;@;2zytnx{K0lD3@(5e}&3d2@q=xRiba?=l00DbJii$l`&oy-wj+L&UBA4>1nNZFaHV3_@0*Gup3^gFEleTN0|SHEu8iVIJ68?cV7Q|n__Vij{jy@30Sh*s>0`};S`;q;7p=|p5mqy4 zOp#6zDGY}3up#kA9W&i#YDFR8c;_W0RWC>kB~tO4VfyX7%J(ZH%LHeSGiuB*@9Zi% z&tXy(y2<)75qc6vuvEFmN*eqSHwoTFOhe&NJ;DVvPIsqiCa`r~DpM%(Em?iC%fd7o z#w3Tv=O0LLVziiKDM|q%r#)&Dda?-I(jx`1agne@#-=3Ye|lN1iuMTn4wUGpN+;KG zH4A}+YFpffK22((&d`4Z{NhlJ%_85>#I?k@u%Ho>t4c&-ubtkgwhkAs6K`RldQ>%A zQSA}QZ!XiFMMvLWX(N^L`MH`V5Pk%Yz+@M`sw=oZNW#thrFkJBrmPu@TtjH~i2qyL zrv>CrA@P|W#0<^ZguJGK{?Rz1my~5Lw&Mq0%k-SkYAL^3LA>rkchJ0aXF-G3RX=g~ zSPIX?HG!@2XJTZbnFU3L2CuYIGg$4}915AK@Sg~^hq31h=C@-5;JE=!CvU4bt9$5! zJ1DmFP&@w@73f}*qt!!LwGTsnhEpLzB<(+PW-H8_*PH_~F8fKXKEHv)?<*p4qysHQ>k_<9l%bSg3Ok@a~`#|x1fM(2_^Hc zGSPM)bh%&=X#UnJMTQIlGW9HabHwx~`d>b;g%qqhtzIb8A4Lh(&{|IyABQSUjebjz zSIH#faJ)|7wZ`MieDyAze$Z^7wOs#inz(-EZ2x)MYee6YVZuJ1A2#?ege`od&-ct` zI+NYn=6fZ(iCr=*hk7LkgqxbEfFrkt!RJdHy;iH?Nc|T|N_Kgr;HD;l1J$!6&%3jf z0Ony%g9g&41&TKWzOVyI`>yIaY^ckjDsqd^^O@O-f z2W}^?vuo3|wXD4j_|$BMiL4)a3d%jnP(2PX4&)?9Bw@ zV=+$%dhtYF0MJ~9hIbQzZ+9!W%i65=)Drdtg0-V;Chw3Jtg^9jq&KhoFnp2idA_)& z`xY;LI~uw3=r8(hG+=rzCpaA`$Noey7EI{itte@9pWu?lG2|$c%51DQ*?kyza0v%X zfR8fnpNGU@jEp63-f^5iU!SoM5CnJ&BM^i%@>37YKOM|0tOLXx{t~17nBm87&OW9z zwN}hUQA|R|wP*8o=q0mo$=@pK>_oOG*CYBvxK%#PRP)2|#|B;@jsyelV3o{Y+9X9e z^AY@$*w`3t-gw{-4F6T8$cse)usJ21WL^T=zPh=JG5KfkG@>TqbbVE$KiG~?j= zb7kKAU?a&5DcSt?GQ&yJccBF2B7B#={lXt+gn5H5dVw`fkBOLYZ|jKRUvd`aKMB|* zcv3#F`Au!?dm2!Z9Z3Bk5CrmGJ$RLDx2-tHS|do~q@fm*nSf*VaPK05qG8!Bc!;7Z zakIbabpkI^PcJ^ojc_19i4ls~ERHLh6T))^$|loC7+Z!EYDuF}%-;kl3kYPNCq_zO z1k9%qv1Pi*^1$!GjaGcPK_O}QwhP9<^{r|^qtw)Dn>$6=;n%f&<=8|UQUZye1S%b& zgNBzZFX@*O6e^ER_7EoB(b0GIRM|)ZGGtS@ZL3$$J1MFoGKpe^z9ly4AjAVg51Yw} z=i@40V&#p8JqJCII@Mq2l@H=5b;Mq$Wiq{QGs88PB$)#VAAhE{;nv(}@lB=rGAXaI zDpZHockLZ5I=}9wE3dAYBS2{CjsAo_K2O4tS%bT`Oy^b#FzUHk;5x3?_4o?2fNQKV zIiO9XO$EipT0hK~COyBRHZhEceHU683Yd6re3}9b{)G;@EiuW+X{S!VgZRor5Fruu z-BAfRG(KK}9sP?(9zpYeKmi*YzK>azI)tMN>^)Y2e1K-F)bv!-yhj6@FpY2(KwjV` z5*IjsK; z?eT^X-fP(p#2xhMRcbnRbrzxD=-<5Qk3ePjPzWL0v4!}b5`m5bRAdLK6L5}t-O7%=z^0uwVzc~;V_7{JKIp~@c8(? z1gw>mVoMQQ`QBodW`KcS7-O3mc=0^T{XD~+>Wou&w*2tLcfOsedsMRg;_keN=1GrC z>m2qnLNfq4Q60$PzsOX6L&W#$HizbU@&E$5y()>9k$;3i<`ZVK5fG776;01Tr>Yg& zC-}7I?yTnzzDtI?|#Y(2^=b1|Ce`H=gA$d+@xU(Y=`Fx}I-P zDs!w?aS&MK94jekA~YN{_ojRUQ`s$GtJUW3`nF0vMDhS&wps;W=-=Hb)mN+pP9i93US zc+z;ZEiXP81;i^S173ve&fl@~o*SdpJlwG(FM|h6zdo>aCidqbJv=r6qY?L;1ez5! z_V2ccyoJB|J7j^)@_ z)Y)3A{Tj!6@;kzWJy%yi?dnH0_Jv@KS++8<1D+#aIZlb+z z#fIJwBi=8k27l>fw_^K{O6d%H0zNz^RXv9u@K2KnPxdgojEDc-?^xOP(U{`V_)`%act$DFq4c5=y?V7?s+&7`sW%s@6k;d+~EVG zxM=Ij<{IL^eqfQ#x;(+FnFtQZ1uxZ`BnSfhbiFyvPJt^9vrG5w*UW*?$lVF_z<_=3 z)WuH$OfOx#5C|k1B>3RdP4kdM6ORC!y0)t6Fc|C@hQW2Z<1fa*>TiK0%NQ?N>Mx^X z+^WFaBB1fQS5gh1pX%zbbAQN_?r0I{rviD}4s1R?vNme*Q~_X&F7eWVhNRi2fJ)m>wd#8K*t!Ht{2(92!|cO(x<+U_cCvvnZJ<;tpqJ^^MB zlu@Eax+`Gw2IH%QZuOTv1PikM%yol}vH&*uMA+X7joXjLJ|zTPm@l7Z8J6S(PRKT^w3hN$r}5MO~?Mz(ta-cZR2>7)A5*e%hL$v$hY+^{I6N zeTz2~`_OT)YdOHc5G>)#bjl|}?ulc>-VCJWeSc|&=*aJ~w@Jo}2a zYGrQP(LvQ7hdD!@;B6cZPJ+}7ropgPTt@>L(tF^7w?sd#j`;AT{p>{I-3Cy=!;v_Q z3VZ_|vH(yx6W!kqehK*We5cXHA>oqJQCYrL2h!6f29gea2X{0JG98;hx)x!$wkDP| zUCfW?6Ip_z6y$X(OcX2V=}Di z^Y8W2XSpZPJ`DVMDla|7pEGntHD@tuWFdb(x$4C2O3hPGUI2LZ_4x zlDZLJ59jkZ`a>s3hvC7%r)TMlzPt6+keBJRs73o-N%^aWxW9#e1B}Jv>M($c-Fo!B z9`0W2pA#6zn(I0Y@*sz9m-izsaOLxS<*%n+$LCRae%|B3L3`kJ*_f%0=N7;mQRbfY-0n82{KiD-D&69QOi4f!| zM>kWqS#nT&2ph`BG~SLf>JqC{Z)Z$WUuPtt^q$(5&peuwKT6nJbsO3nHSrhyt!#|`($N%yEE2Tv?nsXW?El=u7~PFk<#8u(343i`1uf=q1!Efd}Gb5O395|xg**A z8C+EZ-M^Si_BaYG&ywZcUHjd7R$@i1iL0CrPRxtl_qgiZeV}y1eB8d>KT+7)`L*nw z)ezJu(vHfL;KCQ&7 zHhUJh$G@w;l_~ zcDc-QtOHNvHbGBAK>p_)FtqQ08-5J}*VylJ77a=Q{N|>!wgs*@j1xaZ$mBmVTw0sD8o7)|yLmu4E zdx6;j+a|E9gM~f0564wVQ2&*E{%J;xyv-}LcyH(G?+{|f*qUE&9f915pZhV5;(B_x z`q}?pD#98u9$n|oM4fe|CGN7NU=AHhVksm{|BlIj-%pLQB+>@Et41tBusk6Pud&g< zL^n^~#N>XHAcG{x+m``tvyHe&El>jO#K+@txH&+nWACWQGWD2}r^@Ido|Y$c!b4jq z<7(}U?EL~FO3}@0;f0`gM>$c`AXl~D$}DrD$hXv9I$%Rs;4=g|cEAsUUd=MU3_`NH zo@<~}ZioKd%JM3?2`5`BVcsCiju5@ca!S>Xp>}Km9W?Yx2Kz;E`S3p`3Dp17-j)AD zxxeqRQ?eCOLZM_EQZcqsDU}i}CI-{VmYuP$L)wKlTh?+)Vl0KR3`1GUHp(((%#33j zOk*2^Va$A=&gZDU{{ugHc@3WDzOVbbulssG@8_KZ>vXog`R&k7`-i&eJU&UQ+2c04 zP+RKdhLiwduW&mEsvaMS@;h}1eWT|~dW+2S5l<)bsi-|3OO5U=+{t83esOk1SiJnf@?(8ld_2n)z;I~FY2&zzqp--!0E%-iE(($J5oS(+|`Q535l{j)&!(EfblTiwejuciQn z>*28QGiJ>k%QD6L_o@T;I^~%7kg!Kd)pO%h)8AnQzzJSkds|>!6+r^=9{-1#itYJ0 zKZ||COIN&D;UlICF9*}yD+;Pf6mrr4w390{rA+fGdcN?2N5oZ zw6kzJ(Jaf-RM;DzQ!oG0cw)|)E~8hE^wLww8!Q zm}s2n7RG^6TPm%os%rL}{wVVt%sCd*;pdR!l(c*x_p=e7=|Wepev5_xRHC%IJ+|IT zQaJUhPW<4*k6zc65|R|4_KG}VI%INSg`Iw`A}(b7qNsXkjYGLMezh%S(vsS6xPE~} z$xLe7!()-$B0MGeCg&l{J$llavi)-$RNrLz!`+TOd~JAR+0vH};$}xuT)sQ)7dl(E zn|iq$Y#Dem!`;AG(M!hU!!x4$oWlhzya{RnHGiOE)H6b4fnjw^txk6K8To!}%-TR^ zz)5a<5aVmj)PfiI0+mal7SI#Jl1$^-JIi$W*6E^HeZRC}6TTJEPD^gH6{F-X(#bEN zv+cT4i}Sqg?W1Tbqi)05zdyAdns(&1=xDqd9?4~$9&orfzt@+9wIla8$jwILVGwfH zdK(EO_|oh7#0E1QP%h*6&_7ocNCQa4I>(77GM1RnMZak!i;P9SO_pzPAg8bkz_=Z= zZl)&Db1d1{;%(9sR7BVdEVa%d0E`*J?+xH@3RmS?4_(Z`3|XA!RJA>kO`!#jEuWRx zBY7jdg_Jp;G%s4ruw8mslx$w-j#$l~GFMUcygqEMvfC4>lstMB*tNy|$1fu%lG8Hv zUDot)b`orx0we@!C^Z{pie&c%8O-Y3s}mM$Nttz@u-Nf#U8Xry{BZuHabwnauJB~< zB-sj^qviA&v%6`H#J=Ac&1hv#wWe(CO-!J^rpY#3zPXC*H+~8V*u74wlbmeRW5WaB z>!6~2i`&3aql+Bzm}`c6 zFuCqZ*|3ac0FF_`dHX@+@ADOTm|H_d$)`n!BKP}RP_mBhi;Z!swU!ddK;FQwQ5z05 zLc>>UPD^BEBxM_#>@ku&#(gZhstoFGgx>r|lx_KSU+I7apXWf>;0g1XJ?Xk z<7aWydi;4{Ocr`AJ5qUbHi00TV-TYmWA%*sEw^tk#w@&_to|Tr%xs70_V`5;y#vCp z_21b>;cp!EZ9(mycI(OgeA96J0rvehyQ8HM33du6?lQycZ4{;fEu~IRw z3$77dr+Y@2jD>=mO?S=AMpGgSx)QslnDUj}_LS2@4hQ47%+teT(%f^CWAMGxz(T+j zDq*JT!T;z)BV+hQFZ*?2+Q}#eyG?ru`jfXQ3vzqP`8Crd7=c_^xPjy;-Ok=TXu(k z=wFDk%7vI@Z{f-!*srHr#Bl~BY=CoZ1ZyD(*c}sAg35oW3LM_YSmI>4OMNu|k2aO& zDkUF*RtBqy8UQ3uE5*~~v8AR(+;iBAbDfLxv+I_3%7yuP!19F`QN=S#vfe2&9Pn^KOJNy1*y@N|!S6`_&uoSi(-*&Ux2qVyWA z*e)NgMH*2du}i!mhoL4c@Lj-j0M?yLvbpbZvzx#O%YxF;svby6?&--~zSLaJ2kXIgd&gi@Qf z*2{!f-|o)XQbXFZ!*VLb#}rL$dpdEddZ2pZg&(gYQCvq=;-AGcx z9jP=c^X)$2yQ|a-ZG5Pd`4gr132eO5$V7j|`^?bYW7%8nDz28lmE;NGUkG=Nss9U$ z)Zu02v)tnHEnbg~GjHnRF^bLo>!b7P4cOzTD1{X6+~X4gi+9`02OgP_)gJMz88^3;Ex`U>4ihtE|K`x43v)d9T^9 z$QJD4SIb_+S|37#$H(cF_I$A5peiqTtL~E+rvSVW==vC2YH`5DOrcfX<`Lp-PhC<} zV4(o6#%KRFs~l5EOTB zKvJmSf?bZ*Sn*}GOj3gTTwuGA(oC}eE6VlS49*CxPkcX%EmBG@*fDW^=51=9zC<%} zce75LeRVj)twuxX!A~dZr>qBZQwZed(x9#wAne<=hq1=f3NCPa#H|7#G1A4Q$G?fD zQiq|-PvYq7qGLpD*kfNuyX^us$US-PbHpctH4`xoCvmc{F50tgeIc~vZg=#d(y+|c zgxVuRvlWB~OMU3uMb}Jm6RVIszYe?0+a-NY+CD7o_eq$KPHDWM@o{0Kh0xK@U21Q7 zhZg@eY!p}lU9XTPC1f7k_*7!$YZ|ARe=?kjbJ~-ePk_AfDfj6nBES2sJvnm|dmJGp zP^kkYP8ZkJzHNA0XC>LZZIO2CxUG|KIy2CxB3olYAr>IXG__*bnwRHG0dAzdlXrSo z>hmwYBw#CRkWT1r zfxoZtywXg<5lJPpYsPVPy7t`LTd5txVdFm*z6Oh2*LzsPMIAqYAofdZJA&l!nVnzeK|OpY=6ll#~eMP-2@}_9|t2cSN-6jWYhQ=HlxSmOHai7UM4|$ zsj~X&myilId(CdI*%W<{11`pdTwMmCmnfia?9SZ&Kga-#<-;olx&Ti$P~hdyNpF;O zmXF1r=f;HhJKZV^IB3N89edl93PG3j6Qr3>Lc@FNo!b0hlXbz=fx&Fv@8+bp1mBWk zBM&AVEtLG?@a1F^d+#Q04xCHmIr(&4J=*tTHyG|^VS>RLVq8hyO0@pf8i#@vQv$;0 zs4N|=XrWkD+U6(&xi+#MKHO9zsrNfAKjqTFA3N^;1dgOZ=!^q)#24dG==)dDRu0@B zzSP&?qGBS%l{<$4nb104EUFu5A4AqKad+5uYuWtVO3uf@uBvyf5fMr&xiD(+tvPXi zE~Bbw%NI9ILM{DpJBDe6q`!=j+L3f|w8`aIQmH@3d#A<6nvCCr+my^BP+09++ZRdT zH3z&9vBnkxB3DeYgxjYT&%N@#C^odxy5w(6PjyP_D&4YMZ!+<0r4zhdcrq}4;FJ6n zf(G|UtM5OHd~~(r$_&3@{HrN{s^JQ zhN3=IYu{tO2_eh;OmVp^FeZcMp2&XsBG}6_c-YSR_0?~I1!mg{h=cui0@shuA$(Z> zG@*Q9r9IR;%+u`<^e)X7xq8BrEW(!Zmz9~s0Xk8W8XjR+S>ia5_~D{qO1U(-I>@8; zee?k-9x2d4=ZzL_O#ca@NO6cMFTaAF(socOcHwNzbEjROK~Ndn0RQ_)>XR#T2);!V z=3rVDUaPNYCio=WajCrIqViO96N(rKxl{F*hklVoS+=uGC#n{+j(;33IOP+@iD>TF z(}wg4EE%}TwGZ`mF-<$#5$RC(~JrXAt8;9A^z8f3g4Jtq9`q-q3*_r9|9JBM$M4K6A?g*kGF zEX&3is=7J#cYIxWcOVa}sv6=;e0I9JrL!pHy_3(IBd}>|TDZL+7wwJj=T`mI2}^M8 z!KL=xcvT(@f5<{g;Oc=826R$KwK7{QEM@xc41VdocrIZ2}*QGywus?JMIo!ZJk3Sz};k{Y%ob)1U4$qhEB zH%z@!XLk`-k;$Sdcm}@Wyqw_-bK_Fef}KZ~hEUOmps=bf2`y^vy)8fo7qD6cvsxw;`m5Kv^xP#B7%s`fwR#gUGL7W_LU3Ul-d))y5cwmH&Ue##ya&f5>b+l3p zOT9z96JBl8cavMo)%1{-NkGpyRQT%ACJy`Qp|mI?%FgWC5XdA2dp+2&1~j(a2h zI5aVi_MocvvL6DOlUVvh;K-tHk>Z=(K;->;4XyoDbrAyNk?~w1dtal^B&r)E*@xic z=3(VZkB~vYNwrHr?Ro4qUP!uaFgFFfJGHmlN)(h%`Q6Wjjspy67W6b;#cVi$-`CIk zoF6uz(8&jUESmqF9P8Ar?A%}v@`<&JfRB<}>8V4S#s{z>J{D)9i-8clJ#xj~7jc&4 zfRIJzpq7joP<@!24O(!jGR_`TaTV$rK#G1=5!)bBnsj)eQ(Bhke)DVh>dto`jJq<^ z&W|Wl?~W{SKdTM;iR0U+#N%&f*!~ybs!sA^{75ByJZ@@Gp?7jbH?vG= zkxotYL5+PXNzxhnK0$*$Z1m4Ac~>7;LEP=N^QnC5y&rc<>LqCvS32Ra*Dd^w4Nj3w z7`3Z{pB+(74kw+~9)E7Ne)0=&9XbW+_-*Lq7bTy0K$K5Z?(EFDx;mrEo(<&0HpczT zl>})_3CNXv9C~Lt2iSt3I%gWBR$57T6q*$0)l0X$A4f|YU+3{*P8*!9U$LE03!Afw zGhx~u3%BLA-{d}QqDimTQkfirr52CPS(%ndzSZ!Pa79MTh-SG#qXS$|v54QCh_5$T z!txCR3a5ZhH@Xy~56Ff84OH^-0L#Sp!jgaquT3J1(M40efj-~Y6C=G;b+5X(n8!cb zJnyO6CqpzRXBfH_08GRcKk{nTo-2Vk9p?!;attC<%LJ3n?Y+(i5}e(;?%=@l)$f+?Or2)!)kanKrAb zO(^pbad8fuW_K`E_RMXWKKDdsHJ{x<@k8oWwUx)eV-HIjb?`UR;h5LJdtA?lj{d)@ zkpePtb$$E>kO}iRF9Id21TPXRdP6aNVrO+K0ZfYU`PkncOuAxI^psH>apehYl7T-_ zaB|(=%ccyKUy~u^WqkFWaZYA5VVC}9@9$@%aeuRdt<53 zK6D57EBfj)MMksL^coeAb{laA@Wj{15=ta?!rAJ-vD!cl=zv163giKJCTl$siKSOZ zWM2{-(;7zaohJ|DZub^tYxB-NF}|0`;ECIH%6-fsQ)6pFZSpQQVI8AXUxkC_Ax=(| zkHif_VH0j&ny39oB7Fkvpft_tQ@7uJchFCR!CUgT!%7|Q6F|E_Wo0YB5U2x$gKyw3 zu{6NXm#y9bEA^u^NN)p{&r0unP_0e`RXedtU-;f>i+p{BKl>Haa<_`k$MLFK@7{)H ztjRLvD}PPQ`q28@!U$nkM@?WcwU+Ds=1A35O?t`owKwJ9^yIg$KEAsydF;j5Wq*Cg z!R{lBU+-+c9#t{!P^-8*jmq_-h~bF6A)=rg8-hT>Ana#6O7Zf#Ks?m^=SNyRMweO* zYrED)mif7~vQSBIX+B*_72|SjTRj2Ze5?`-NzM%+q7-Hft?_=03Q=r+%z5>`4<;VB zPu3N+Nc|0tXL$!Y5#4n02Sn`WaHe;PbxOmAcY10th2J{~a?5kygfdzaJpxBVjJaSQ z>*y${{{keI3dp6VX|RQ5Y@@UAP<>=*JAtQ!jG%~cygnJt{vG|9C9gv;5;*j%Bo5h% zceNi#1m*{{XWXiTzWb}Ln#5v64hvrfrFCn->+kYU(TE&b>A>C^4qT91bEbf#*JkMO3Z zrMt+aiw9Zc5YOFJF)K1fyaP!tP{#sp?3N25W_tO8b5>_sipflv`(J#j$mgle;e6B8%-`6+PD!4ruaUFp9B z|DS|)K*=9Co#ixWNK30y!sG;5N*GKmo%egzHyO5vJzMm>p_@tUU%+hTy#F3?yWyzy zc7bpZy6I}vr1YvQuxZOLvn8s0XGceE;F=uWJ!Y@^Ouc2^3=*}qrhi~!AZT==Yig$3 zQ6!dMcY`j)@_=0M{5X8~Tx?_hR)=c;zXpc}-)?i^XO|7*_$hMdEs#nt$95&m79ns0 zVG#R>15GGWuvcjnP7M3LoF%~!b`Foe9V6F+7t+BaGvB2%MCV5Fe90o6O(@$TqVIu~ z+~|eV$T?i5zHcjyixmGu@~8oQOCqvMce~QuCtg?iSQ=qO3sfhm0v&5dB`#U+s833> zyy3|AqiVTW|3b$wE`^>!=(4=k;N&oaOKG)bjKsqx(|Dqbb}#{yE&v(@rue~W)TAij^2#s?x-&$}6OQGR$2*6|JR&EFreIK`|Gkc+^u^~j7Y zP`17F9bBj(@FQA@D!BsOacMq5+9$X$8-aYl;tWG+vmy<|J9hd<3t{9mbk&y1dZ}~^ zn*q4c6uJvYdX?#ft1h)D9cqbeXJM~rs9i112z|_)*i!y1a|~mgOd^q{Cc1X_(i0P_ z`OJ8g!Z(bZxcEP!ag`SlL+|Ld5_~5&MwOn)T585IE$dAYX~gOEU`3M^e2*dAv0_NZ z*-1=e-<-WOY7PqP6t1s)L@aIq)9@NdNA1>P(kdeLeO$k;%bA#MY4Yn}S{r^K+vqW< z8bY6N+}>3*uz2QI6k>ly!P*^i8HmEe#_#XlJMu!%l~R4(Jjlcd<-_1K3ayeIoF@;j z0IM1#nbjGedUU(ytpItPMy|E#D`6A7Xf@}(yvx(+ZlszUB)8Ow!=>3cH)AsIYHih? z6Sntq$9=dqU#BMqhuYrOfAx()H*xiJ@ziw&-pzppEbiFXY|rx^iT`EbnQZ|?=qKO6 z9zcWwR#0J$fw;5BhVS#gVQV|OnT)xz`*+$Qfx4W5=caqr0Z)oEv@GB_X8G$ z#pt-&z_Ey}6NJcviQP>29FBaUC|7!<0O;~W^%XyKilNV_rUO6s`$f*I(+~%>K3F+5 z-QO|p8_TRp-Du+cV$Xr%I7ZWL1Bhz7FzX0mApE>^v1jT+c(BNGy*&KnTHLMUKG!Orx|$)DNrRn!m4A03orq|!+BO}( z2Jg^WZCN^I7^=~1=l(=x_Fljch)x3mK z9AtgMkKI~P9uPTr--u@#&Hmzf2Z!)u2tcIpB;LxkOhl*N
    jhTYHPZ^~NOfP!_Pj zSnLVkXuc8#>AWmBV$Em%T25U4eqe%d7M6#Gct`xhq88v*NEDN3;889Y!+?dc#m;|D z^u7=+R6h9Vl3>sHg^adkH86~%n5y+h5+TNLQIcb_Y`ko}y@jT1kIH(4GE`Y~BPH97BmX}>VA z1I%;}1Q}*1&jfZa?qZx4mp3%t1Ce)~e|l-ZNW1aOzOemYguB;lBLYyk2MV<7EeR6G&@ip3`Jrwv8tof%!3if-?*APP7)p_27!53 z&VgL=5T52exIn+qT3jR)I5uV^f2Nz1jdVrnPrK#i!Z^;04HvmFeUz?Mn-DPOej|rm z|3;BcN?0gH>0>_gALDf1zg30$Z8yei0i{*8hW`ST)-8br-iVsBid*kaG=3CSQviYF z63&<(yNu=kks7PWutg6(?o^Ks@h$`KJFtr5b|j(ZmZ zEO4!74IZtr9@Kbc`ip>0Nqs^X5lhpQv(p0i0#L5o-{ZUNXQXyNj!ihsxBl>N-9~FbpPmRVcnaL-pC69~q*_A) z(4Kz<1^7ni8E|>lq$!s_e`pqKhA`vJn|=B0&)?@47FAW^(YYLIDEI&W#^xpek;Ba> z|LPw~o50uv#wKHIU|^G%|L8oMt>kxa-UP-bFgBIk?|Rr2pMTWDCNMUEu{rx~U|@4x z-B6RjWWH$%{2nzofw2jUP3z@%J#1Ppf7HV!FgAg)X^C%OKvZ>(%M+_^w}1LcPdfyyW<`oBszeA4Y-z diff --git a/packages/mediacenter/kodi/splash/splash1.png b/packages/mediacenter/kodi/splash/splash1.png deleted file mode 100644 index ac0aa0052fef5f23bb1ffa67b4769e2b9560b382..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95223 zcmeFZg~4weBfXk&)vK4bFS+;*E!?W6LrONXIahy0DyB!kL9%h0CM8D zWB{r&#GAUhE9ZzeBwkvIa)6Sat1HAG&RD4^$^!_e|31R=-V^Vke)`zZ3jmZ*u1CVTsasgM`eaWaVaN{mCd4#s8lU5qXyC_|DRf*?&m-TqW zyKp0Z&(s;}wSR;I`|-TXGC=H%>mt1NOGhSxAUzzfQ6ah3Iq_21x9k8CDj5Ljg-`(b z-*1zxNol+!MRU*mfhh8ASX8fFnyJ^d;Q-R`u!*a-~r{|OaFa7 zfRvNHiL{C8yrA}r|Ge;@M@s=sV*gwf6A1|e;L+1JDL4M{>Y)^Xo`0^jiHfQeaQE5s zuFD+%xEdee>G}Wju8A-HNG6mbl>VwsF4aG-W&lv{146iOWXgKhX1AQ|570T zDyaW3?eCoVSIqvG9Q#+y{)cIQmlziR))oK5Ef@YR@%~nQe{<&F67Rp{*uT~Ge=+T^ zZ$tn8j1RsTi`c)8!KTio2fphDD_|O$g|YU#X-K4LTsaJ;zkP7;#ZB_Re3fZM6uQB$ z>CQiVewvVBdC!}kz1nVVRUq*5^C$2*Ls0`+!~8~OB30`9?XiZF16h-NeBVLqH}|h7 zD&g-$gdhm{Hom^TCWn}fjRYhzqr9TR*%tRYsfvf4mH)DfyEEHSQD+FM(b(74{a%*a zBn}3%CTO-tf&Q+5EraNEuw`)2|9Wc{Jyef_fk2>NmUL^#hISD!wG`CYs5de)+Bq>{ zWC#s9Dk&*RT*$GFtEjFvOVm$nP%qQh(?i4NZh&6G$^C90tL4cSPpVB`&9S?nc)m)G zhL$p~M#W;19G|Ti*Ae^bSZ&f>3T#qcUESd3>|8IYmr*4JKFN1+lP)Jd)Q%!HdrZ zQlnH0l6W+XaSt;BFcrt2al7E-Oy4-maOt_+0MHin_-gaFXE6$mRXx~>*L>~AvSS)? zH`iVEr@6MEF9H0tlKzK%5IPKqhwl0mEOVc(!`L0JI~}l;vE8?QPy`;`P-mC@V?Ay5 zQe5WcY?$y9#RcGJ}hZw?7DsKc0T6~wNJz#ZJUZxDkN^iiIO zRJA=p$2SYkIO0nes=3UP{{7?dS!~on<&gA_Yfl#2GU|HhH0Z_)hhE4`Ts76(ts8nS z=$D~vawoi6u`<}MAUgCD?oBlT7Wwo!%#*%(=0N!wI(#c)vz~PKI?2Vq3(`=x=r_Ty zar-rs{jNhcy)PZYQCRr47wEtXe?$BgL@KSMvhRy8Z?Z)d>kzj$SlQW-juBA)NPKk1 zaYA<}+)WhuMnG|=S7t>xdNjdKG;gOxIz~8TVNEXlnGXs4xG$y!@lHr}P5Oi{*l{5! zpq+*chNFmrf;YStC?PwdcyOp8%^5QLvwu%amEIt^;1lWZ_1s+|2Os!BV8QsE%mdhH z-r;BhWV!XbPoQ}uLDiN$lAv2e{ff`WiS#q*45U&e-#PBRc7v!&gQQji_ z#M1*?5&J37PuVmS((J7~HU*%@Gc!?u_H|zJW1Wu-B)j7+C_I|*@hS`|NV_refL%cC z?|zXJ1N_0I-ynCNTyMRW0KsBTu0d#U*4Xfnvk>&nWK-7(yuo6IDnn)O5bw$ty}~{U z7yZ)lWjDh<>75XD;SYR5lb~~+nHisrIq}5>QT?g*;L^CV7Z$yiYj+x$eV&&GgBHU4 z7_>Gc{GlrJ^mTFBo+CNdNPC|{X8}EJ{d>FD&s^h_I{#5Zq{qDG34R}XqI_SY<Zj9t0t{$p{a&KZ*aE05POZJD|rna(yYLqW|GF9$)t1$w_B-``zU9;V+V$iFGuC zV6NMEFM(RBkJfqhB;b8}NOih+t!6C$CPFYgj{LVsesGZlKP-9iR`l;pyH3@x-NB1@ ztPP&cT)cmQAg09lg}9bg;#$5W957;5k`lKM)+Tj#NBl>oOno$x98$;ZviBcuVZs$- zg>Kh6PjO<~OFhXa?6-sHZv?Y+U&cEX!H-ovnVVLq9)%Y@3TO}Cn10|fCtvHeRBO0K zEk?Wl_wZCt{d-cX-+q6x2I+D96!A$Xt7X&dsOf#ooavyt@G8}Lz0&7;JFJlh=Pl0+ znceQZ?c`(VrbrDWe zra0&~&+0>c>s&_)afd27Zv0^Dp2KmDPh!wlft|4B>xcFn2P@DJ?kdx|POA&tYJ)zd zacz+ojQJIbiTG@Rs#3qBoYBkYXQ+pb_MystyEWCUJBiJkN7D~owgmwEb0+m*I3JLI zyc2MQN;yMs_y-#s$qyO5%HA2V+SPE-3*) zS@^lUKdORtKpq>moTwpE2dV#Y2F-ac%XrV?s^k4C%>4a#L4jAb!Gl+}QX83i-@k?^ zL~XVE2X2{jXRSJ&Wy=04bMD6lkp6B5y zwKh%B8YN&!LD&M5;8k~aor=50Vd_=Yj2RXEKWsn62^r2Wgy4)%it|<< z3Um%)hP7Rj^Q%v1dC6Or^~AJIUUgB@tNx*13z5-G`b}thhwtO4Yj{AX%VY~u<@R* z15RL2_Z_YGsdYK)Zds9fHIgM^fJa#f<{0SWQD)NM-9JrM+I0;eq@+pxJ8PLP5>w^- z^WWUn#X-UkNEh?ERf10o91>kv%UKei96u{kmA`*mTpJpwz~Udz_qnRm7?ZmrTyL$H z45!kJ7(g2dqkfs+#2Jf*LsZ9BtDfG3;vCd`$SlCuz2(Gm%=^b`Z!5QN=m}fhl0c5 zT&_Ri!Vzz}Mk@7>9Ogihc1J2FLH=}lJC@RA31M1HdbQ}Bk~;Sujv#Hsj~=bOh!>zb z2EkMTEic$M65}Sf2<2jEs(Uegy_ik= z|Ft#DBvJ%IG_^crAJupb<=FT2inUT_d=d$JtIeoY%7%g$*`VyFD4|Zon&*IRlO$^u zUH^wNn~{}8hiS!=PQiv7a&5sEA+5>RWks{D4spyo1Xeo)=)V}g)%EZsdGorOaef4GARJs2L(`Zloq)oEFRp4Sw6E$`hwZN<2@u3BgbK%w7q=uNx zA(uN7`EOlE3sgn&3Te+ooyn*gwJWUOSi{JscK6+dp7@m&)ehDaJ6_@_cN$v0%t2d) zW}wR|%Y5GpR#&${gJ0Ufp)@=-XlxeY`LbgQfD`^eY-h9`li8xqiOrK zS_pJE_mx`UBgKF{kg}Zz>uwHn0BBbN{>A}4u zFg-_mg?+DZ`hzOXp0OkVgFiWYe_6!u&FVT`iz=VauL7t^@`6Fx(l__18q3Tmp;?Es zbr3u##}?FCv{LD4{MJraBjQsA(;pA(IkN+Tl7JM-^*;;ioZ9s~J1sXd>SqPfLKM2<^5bneSUMMW)4 zjeFU;`V?QEU-2LM>y$iMFM0e&CR?ae7Zn$e?+}tqx!Nw@=z@Nh70vW1TRK5a|JNp=30D`bnJzFf5yzMSUbH29qcCht}Gc?3=F zl?vmK%$$#;fALgg#kKWo1{ra+O`NX?>-FtP!q3OOpP3emy)phV{%EDSHzT0O znwJ(udTmESQoy9aKt26|WhU8Ah^tZJ-zD*r;1gUN-~2kpuv(6fOJ6gCHpDXH+%Clp z-EPl^xl%3W3aeH2p2Yjyx2f1yHgn?@V(Y#%Y1vD*<({Z`3DYn8+6H~4-8o{`I_nbW zcPsxNKzu%UwHl(kA(UA(Vn#1sQ0xF|GFM9p#4yF>-ZPMYBdgZ)ecNbeyc8-$OkLYJ zvN2w^3XXH*zgUtOPcy`AnvwslUuth|o_O^pNnMKAI)Ny6Cc7nSX$005cQvHh%VHnD z7d~B2=K1Gv7NMMz^C9S}=EabfAnyy)@J-)Q&Lc&_co5Y=KDKlYWOo6Er<1S$*7h{} zc}TTmR+$a>PHb?9?nk=v`ucecNsa%OTz?Q7g8^W9_RTM^gM{jT^8&}m$*;Xc;`Bu` zZyBz7t&#@ZQAZ159+ZECYsJTHu$kei(g? zhX=M8o4Y)PngKT!HY+i3-Gb+lXMjE1ez3Z?j^5*OPRb{Fnrl2jvRpCU1W;{Xm#z^!W~6|@Q4p6#su+Re?HHI*9B{n-#T zEMFq(Vp9?)8y?W!p#OPA{sm9CjmB5L6-nV(GMq4mtOXG)gucXG*jyR6=%%>YyE$=C zc5Fh)X>F^$=5S=fH(n+oC176bL<1-cKL7L?{hwJD86thNE0z8Um>ZklXn@J#w0mP_ z^y=5Xz?UY^(tr0%(tN3P8Z95(c>{$OZfQ9)%}Jb-Omx-i@-@x-YQg3qx2-r0dmAHb z3!V|>J9NcY-C3w-9Ms2l(V4=BP#4}z3s%P$GDRFlc%WWpwaA5!8BAO16gns;eKk{4 zK4xiZQwpMMx(%na@K|QMdHooPeJYtUAi$*7vzAYQZ^AG3z$2CU zmGU3?`{0yBW9Pg0P8S*dy6N~hP|O|m(p~$t0-6Ya-|u#s-r~>ZNUQKw_Rf=?{IXOb zi@ngjCmawF-Q1m~*7A0_CyxNPV`@xMoS(312HmikPMds?;(j8SrUsJUa+h)tmcM3e zKYrBGXuOl}N3-k<(1(JI6BCnM`H7;J+T`z)Q?-oxA7blb4qM8EOxwrD0Y1kLHL4U# zt3FrvD7XRfs0iT}5o%H;xO9auj`3qqrZpwTnC0hM(svDd(Lg zxm`a9-n{TIXn{BgSABa^p(Q$KsGZUVI)vfOYX_8=!Hp7=68-69*sW;(h?~@iJApU(6tZP>zYRaBAA>vtmRKM?Nsy!7-@gd5@HrSlr z%b}Bu!1MV~|4VoM>mCnz>o^XRkjZd5f>Zh&$kn*HC~d5hOObxD+I9Zw1g#=%*Uaj!!$qIJILlkQP5yY`CJc9M&VwQlG89ptCh=ER7mJNO zC}l$KTZms2{w+kqJWi!?dV7Z9DH0|dlX7c(;NwGrG}O(aQ0iB*B`pUfVlTn?V7i`gRc@jl4uqB`z#4oV)OZUdfpRGIr)B< z;$|w)y|2}TUH6q2?+3SBVzL_sx&q_}OY5KdzkBcy;-l;A{R0&$uHCs>V_tCp;N#;P z8wJ$#(C?1_QW602X8?kr=dE9C-ef{wC0d*VFHONy8Z8AoMLj ziuF%sGZAg1yKUJ$>A%9~Uf9}b3D$20NAa}o=G3D2O?(KxxJZ?qgE8nW^Mq$L)@%+mJY{8(o+s?X|&|(=Ba+q`2OY&L9m&Y*WVUH)#ia{Z4f^KU2xuu3*!W(ui zK7IAB-DAt`Qe^nu%zK%iAgP9~qi>jv=kPctUP* ze0r>lubNUS>^qK+jr=?UHT+0FOAkrEr%`h)7mQ&sH8egr=(VWrWt#9Ct%3I&hj$C; z4SLnkH8;2co4I%59EuNnTO+}D6Se!UYS++K%W~6xGw;@Odx<5wE=H+S_5Ia(RVCl>>(E-8rIl-h?y32>B(ir-i@Y85!DQ`AyAFS zvfIL7s%>w@GvC@IzCTAWs-9eznEg;TOfNYJ>Ab1B!CDZR zuA8Q&jeq|=JY4g2;r<6Uk%*mm3tbLS{Gv&%~EetPR`BDc$+*L`2_J#$;?C-Vo7H($B|+}crPWI{zLK5 zUZSNJN|Wv5;yBrA5=X6%V1UJ{w5MrElsJga_^hgZf@+ z+LU1sQ5Vz{qX*OW-Zl&>ZDod!Z?#CLVKwvH1};SsS{TZlTGUUB#o8~wr8I_6f1Czd zAUgF+0$FJQWb&7PS9~p}z`ga=e)Ug`FYqRHzPiK;t~wZdMlG|_R&Wg)edjp7+i-26 zT5t!h^8USQ%#iY85$n_qgnPOJ6(pwo-g@&vGv*ncPzYh$T`RnEl~43mhaEBZoYs@% zj1_Y3M-L2%q*b|ZfJ&bYKaMY)4ZXiBnzUYeg+Nx?Y_S2QU@tT?FyPDUUCw#4)<9_y z`RaF(5uJQGmMeXzdhOKkk)*GAIxA-gYP?PZxLES#R(m`sCzq!OT4tdk2TjCS!f79*Io4U+(gjgtCPL!fSfDFfEs`NGpX|y2Y^z* zjOy5LQmHvjw2k@RUv0WBiZCJj-s7F=i|+(>O%QtYYeGdg2DVcM8!r*uv{?t)*Xlw< zYVux5yXLpAW&R3t>x zjpCrMH0rM5wFRTKUfH3O&z3QF4Kr*r$c)GhN-09$=cy;`Rn0eVd2_Op{gF$I#BFNx zX-MHG%9XHMuBVH;E1s)Al?Kyk8Ub(gLmzJB@kz>@baHhEnxaZO+VZuOzId^UD9(4e zGPUU*T<9|MBH|2Bk>AJK;>GGb%1ubF|SjMnrw z`Jr2t;nEvpmBSq{+l1}cgo$IPTJIID3X?%{j=vi2v|^^&Gb)5tk1-S=t^0CZp?8nODkn8u>-1Q--Oy4z0O_ zN>1`-yIw|12aiI0Q|Aa52tO7-L>jql1{k+;c>S2&v-6qr@q2TquQ7-((0vW4BawyS zp(Vvh75iYSj7vy4C8qLUh8#}bn+TjHlG(`nKL(~pgf@g(8YFmRq|W@RdM?qOg4 z=ie&PrFITet&g)Uy+(S*B4#5F;@(`G78;~)r=J#zw%6%iZ@&|f+dKencD7dYAIdc< zL~=M*6Z#x|Y^&0%CFB`aksQr>%72v_JrNO2+S7i?lw=9g;~s2I6eHRRio`>c0D;PT zOrx)KwMs5UkEdfB(y#V(`z|x*)OZ3pA*vx43=(33lFs$k1fo<9h=$O|&A38B!Agk( zUBvjFc*;t5{CmhcW#&nt?)yepF;&m&9-wD~y3YmR_R%SP$BWZl*NVUHKN}FOMEV}N z^n{>doQ5E-Wf_gM9vwul)x)znt&ZL17g7>GPQmqtkaz#v7a`kUypl{w%1Z1&&$nxM z&w)M=pmKe;lEu(_gO6DD?!FaUVfK&{43fU{O*J6L?A4=jnB~}O2*QK#9Zz3yg^=R@ zjZHkZv3|GYd5Fs=^qtkiMWk&j<RmgR7AQm#HKL zgz|-4_@Q4?qu7mn$%Jo0Tz*cwPX1g3sxcMch07JW=?}GqRT>WLn%~lvoY;4z>_oO% zrkh|&Cw?s9g+^K$59kU#CiLTqYPL#=Pa6ndZAJcIc7RHau! z<%z8ob+y`Xd&)oXKoORs+4WB8x8Y`T(ZIyyjy}``U9wv}aJM!0mh??L-RHO4S_AN; zy6bu8ZVBZuTftnv+l6F3sXlu34Q@(fL8i?F75Wrd#IN|K99F+pTUwORt?sqMMaXUJ zzSG#1h1}Nb>HYZwwYFex{oVKL_J(y(PNlw?t8`M<8dbTIReSOgLB1T}M zxTm#>W=zXhy9k3e%A^@doI{?Yd>Hu+{JcPD(<8!Pe|=rsdK@{vB9}jnEt!83l;pC# z^-Ml&d?&c_m2Tw`&#hp;IzUJ+o9oZ3+0DYNg<5*|gyMlb2DQeL`2isxdR-+$tpai< zZR4cPkK_-FN=Ak?!lo>I(}QVe)@yebT3*dB;Og0yWqiuM{~{6qdD|)3-n-_y_={{~ zsUGV{6Sbstb}$y9Tg#*Vm4{?yPJ80+dlv3@SpDHUY}9_H0jO^A3cq`IK&=IPhAy2F z+d>|V6&0q{F!WLYuluC?sC+&D_4UUM#^9iK7hCs$DvS|AVljKOT=VL107x&-W2KEm zO;(!aHFr#{fO6%ac74=S{x?J63jC_ye{{SXNe$x5Gzjqc%Am~b+{mc9W-A)Lp0qx4Oi|Bj{bQXm0Ve(`_$W}{uCO&l0Q3BZ^?dd^19fo2Mclp$ zAr?*%$#eb3yh6SK*H%3~h-|H5-?B`7A_*`uGIHV-I{TgB&(TVs)*zTkU^qI&Q`LN`vjEvtXnq#}>S%@+S;iXcnDRWotSij#UY56e0LjNJ%bEUkhsEIqV;{5QBSp6NCw&V`cTlkf749UP0M>-C#);-)DO7qqc) z91>H8hW9X#RjW>^=(rh6ViZeF1BJEpxO0f`Hvd&sI%y~FJ7k!5tQef>4z8S-3dxz!C6 z18t(3KhW8-=>?%cs=ADbKCR#hm3ZupP=>RDP>N@*3+3zhYN&4`566}}FXQSY78blCU6)SzIi3DN&_;Tc9I}A0 z+@GyJ3lH<}~}sNCSvyyZf9X$XkX6kZPIK((=yg=t@AReWAhCikA#!zy-_Exf}3u zZ%kdkI^t%%7QzjYFnlE_h!ALKYP@HB;6ni!XEs;bL1PhyI zO_QH+PP$9`8(fzz&)mPY$tLMLw8ceUnNA3WE!s8*WqC=Te;Fh3JF3; zxoq@K@yZo<8gMM~e^`}jJR124+c3uIyepp6sOl<;+)}nUcovj9E1fWasvCjcW)nV2 z@D5OY5THo|I6J|`4_Gd5n5LLf7cm%aEyh~1s&Vw$7J??}*v332cY{SWcpb~HD@Am) z;8OXiimsUhS=%+nZhSSujeiScAb0sBlZiJjKe)&zutHBEWql>1K~IV>+-2A8ybJCmaMk2`+zqjBxclf5$sOCN%IAfj$l zJcJX-$eDN+Kp8edCLWbot!s>WL8XhY#;lzz;e`@h5B5Oq)glgA8Q5 zW>f^y=NY_z23?vOP9^wsEYHqqM`SbpQlIMtlz55l0Tp19^JvLf#eVLN>fj2q8!M{gK*H{n@EXMu6L-{UO&z{p3-rOrSZd?b72er9NrHcQ}`O*!!NZTGPa{ncIbr ze#*&8s(-8^H3pO>$>5h2LEDU^t5*k(yr+6#K*-V3i681ZTL8KcnlRe9PmE?5qFb)% zeTIX5bmC>2UAj^tz|DMega9yyJmWme8Wi z2il2f1;2}1QGxPvH51X=g?nnd8)FsQbQm~BIxvcWJ3#T*>*ZBCo6GrQ&}{Mbm_}Xc z!&$nHAdvsg7sNSfMq$rSG6&BOFFrP<3>Ymr%!}#CHo4nJI`|r?xh-UVD0lRY5wW~9 zVt&$^nFPXCfOy@<>Tm7pQvd0w&N!a7Tn549%%{`3VR`XQVnNK4OOVyPj*LlI)b>`J zFT6OUAKaO7cW?)Ld!RDOe{$#=U_V3}N#56Jh!}3ne8iUrG`l@&cBoqW6s;}>Ss3?R z+}`ut-hJtL^7A(1PGAsjVBj^p7CbKPF^Xywph)Y5`RxcY{7~?5ZLIi`a=GD7U}LSP zKx4rUl*Padqd11FKHxsIzqI$NrF(l!`mI0V`9TL3Lqx4f6t6pO7}iOLI`IwI*#iON zHXwJ$k$ENSOA1nA8xxZE&84iefQnqK1QSc!g6b<044K%erA~WuTzZB(U57bg*gOde z-YZ;KGbf~CLsoD72>nxLDV~06ou2*Av<(|wSSQhnf$bx7HY5qbVt)HYAtkP2jq@eF zRVmBL^t_r30qFTv$cWM=s8r*4{2bwy5xN7B06ORRRUTUb#Oc%?Pw_4cbT66CWa`-Z z(*XYbT>weHva2B5IdDMtqNA5dVpCF$`5l_-zE8b_j$nZewczvbT9!Y~y}$i4VW(R3 z-u?kE6DA{rzrL_(y4J#vemyyKIidwrXKM)58c;vP|F)6#HfaEjrz+ffMLenv1xYu5Jnd`r)QZ z;!D~d@mCcQzPb|>X;t6>8bA`J!NjfcxYcubpRr`Bl=pC{bGwc@xIQGf)y$~IDwEs9 zs4Nqi2vr~dIi4Y`U+oiuYz2J#@Q7X5{`-1$79Klai%~!zWwXr<>Jd+Bj#50 zkAS^{&zkl}=F45(r%-{reVFTGAMs)AYLdbb7``HXeKP8*VRJf?qLU#z^x_AkjC^1<2{Xx`X?iC?#ZR* zRg-%fNqg_@I|>r?)i$wS2O}6w^2Qf76YWpX9Tid?eXG6c&ni0PkfMUZPPun(UA4RN zu#nEE+-ck2`;lGgXhOTXfhxx>!koe!$ zZ{f&&+T%vt3EU$N%eT2CdV6H1 zt;1|V)S;^&C;VHJ?)8!T~f9=~V`8C(t9f#H2gfFap zQ(ecFhe-9xH}dWAg!@e&+`1{5Vxz@K^Q(6dAVI=@4R<7p8b9n zE$rT2l*r{KR<9z*mhnW~S9NK=%=6pE*|E}>p(;rqZjVCEfgtNRiUw>C9j@XTs#<~! zYy-T`C3`w?2q2d}ce`Ta^*dUl7&~ismO73nQloCD z-6oFva#fM4?6t3Vz@qrvm8f&!g#z3IBX*KvQl&}dN>uIFNZ@dZYnEQK<4YY$1UST? z$HYI^q$V&sz0tvnuv=ShC)cA;Ml(GgrZrRmNz+T(eht?jJ`>}vA9ZYhIeCL%D?J-|rX^|+HMQ21f6 zRd0tLcN&F9Mc_dd$$5-#q{nfY=;V~K-do&x8lS2KdQ`+TdF2<%bT|)Na#ZH)eV|c#+Ct=d`@On|DDz zrHlJaKzhv})l-dLlhTey$^lq3tkW1oywFlT1no!de?jDrw#@_(-B2)T-^#_)x@J(> zqVj#s;K2r zbpgraBM2&sb4M4OES>GE-5+7D9v+z!lmqq{AyvVPO9Z$6AgcR4xc5FHOwN%;0iTUu z2Sb9uSFjfk@wABXBhpZ`DbMjWnlh%3)Tt?G7q7?S4lg2VdR+FU;TQ*LZ*setohr31 zsaV^y1j&(dP1B(@y?}9rfU-qhJ&5)c#Y5MTSYGu^-vnLGdLF^ z?H=GcuTvYaqgU(fC)%*LZ@fTRePOf5*gXMJb~0Jb{Wmg|h!s)ryUG=s)6LU#;u3`q~o0r4Gs}0W(*7~_P zhLAOh{rz!CWV!o-oB8DBPt>!mKh&n=Q3q1vc%^tcG?Lb;zX^8jAdtI(u0Kv*N}c0) z-Y@`SH+}vC1KCO5PIF5c@N&Mo?KKk|-xpVZ9bLgP*QqOOMaZfx6$CD>v%44kDZTXI z-U*1XYF>wW@3Micq6nSH>bI^Sz<9=YJak~xO<`dV*SO&z%$~vCZ;!#uQ?rAMvcC>*0pu13e&de zF1aIlpo~Az6ZXsZ&#&PgJ0d@<5r$FN-VW%=K4ebc?uz1%q&o!{cF#I*N^@;@w<#cO zw^th%>p9Dya2Ni}FIEozHl4HBH^UK=V#%DzRkv_dlM|MWtk}}PI`7a=KpTVl{L@_ZvR{H|So)~(^>XqyfnMHrEm ztU#TSzor#b=utEQN=DUtp1NQTdkeyG-VHU!z$+6Kn8L1 zav(b7Uem^Tf1+KoyWNBVFG(zPW8jA1-HrMMsUY)E1`6+uzklC|O_Z3z(r#HTrxRbB z@fZ7y`}clG!y7Oo#l{OqOPRpl3F8yfn&lCnOI-LA(I5e1pAXvs7`vX^v6V^T9)m-I zpYP|w14HM$DCx#uK5*L#`^?Zrzucq6% z_$4Lqvu2Vl(C|}*%XYb=kyAcX#aU@B*DiJETlIlaA8>mH69#GIgt;t!+A%hQ{O7W6 z#rxh3E#hpPPZeoCO91d+A$U}L!~uv0g3lvF)QM}=Ib#4%21sA@IL0l_7e3#5-6h%` zp`gJ?X+?swjjYo0Nj&pydNC)7zVUECW#J{Gc_olb@(v2O;n&FuMVL(o97HGpd4o~c zuZ>kJ0RI*R^QU6CUG^>0FUg}tS{TS#Z~98o*&Pj;eaYC-c}u=z+_)>}uIYuzgids^ zYwyx!A6DPsEa0$uHSNoHyRk37+<|WB?#DMy*f;hD6uSmj$I3S4JCMWp4rlRjAgWF1tPCM~51=%!VA+PHZ`)G_zmct{ON(o?cWWq!@N_ zcWl42(Dz()QZ=4jJ5LK0%-*E4h7Nk{A)II=pqmc&@|hq%7ZC8`NDp&G`LoxJs5X0P z1o#tg8u#_z8zPO7)EG}<#p6Loz)lGiu5-KR05RWBH@SQb@cgq3%jX+TnLvP!&(QI7 zxvAli>?$q);FRo493uJCH1nGu^%Zg>4jbaR&ieu}OCRdB-B69_rK2=o`zBZ;F7OC{ zfUu8)OY-@l*GS86{smRO({Sb!J2_RKlC9)i%Dv-g92C4?u`t{l(nAq}nuZ!r-aPh6 zgQF#et-aJZSQEbZ22vSj!l1C}q+`2?)^Xmr>r!Xwe{M{yXNvTg z@ez9T@hQ}WKJ})M_Lte@@r(YLS|lA{}mnTS@P~;)WFC=<#4w7;^lo;B%}^cw|VHp~@1sYU707MotHqtdjx(6o#KWcc*$?Q72KOV6WLp=WT4WZ^oBaf1lFs$5q-nU%5_>Wz{j4UTE8nPCCiCwUi^ObJ*9TR>mDYlZx3cA z+P@ERu2EzRvJB46y%QR$=ic{aSkFm_B1X2?!hVLt0xRm|(a}8UI9t$%v02{a^&h!q zc-k>icq#tNK~b$QtSQ_zVPJhs`_&3ewKc#Ioc0~T@0=#s`41VToVzd zWto)A#CXwzAq1vDYu1Vv?@aagL#_=Cxj6>poGgNHP?IN0T*?MYq0>nS^vymxRhGxO zZ6g$^$P)B3)IL5j=r&m6HS>)gcQV+8pj$mYSEh|!IA_fXbxH!{VQ@j=!bR8sBV##?{Z@T1AbAQYd_qIBsy&nl+S-XdLiQ4!H zb!5;2$jVW-=?m1`D6NO-;v$gh0mEN_}q_*t;=%U^;O5af@uGOIfi&lZW1t2egTa zx(t4dxDW~;eA7xS=-A{alaL27+!)UQ)LMw%6a2fwDdcqo+mvzTo4=~pt}9`aFt-F~ z@B*&@o^5QhU7M+1GJ&Tu)49ZLBqqzlXE2d6klUzuTuz=Pxte03SsyzhDWB=YUnOv- zpnm|@9q|FG08OhB3)%9l^~Z&qoAzjQB89eqW&TgJK+{RLv><_ENFu}{0~@tQM)in; zS)PW5M&$~j3XE?Bnq2+gO(+{V^tG4-svO!yxp0l3;}$cfDBzgUm@HF_)aL9X6W9-r zFPs!*TdT<{_MH?3o2>w}FkVVZg5EI27x(#aulCMJobb4+aOJD`khNO8k9E-E&n?f5 zq40$y-cjlZqoJ`XgUtuhLNiyr1qgEpf<^~3b}AeAqRV&BsM!KIR*#8#V0DQbZeQnX zt1~znsEt@*;TwEK*o@2$(jio5Qxz0vUhDT%3unjGL7C$a?XyQL-4{ zigsutU_N|MQb)*Cg44-<%(gC4V-eN%L9+f>MCy8JU7bw&p_L704OEXGOQP zRi#);o%D@HUB1fe=k7_?wFP!DT;mdf{{)Mj;cYR;0NvVQ1uTE*N(ugl`QEe;UrVjzQKNrz}i0Kg=0{ zb<>gN%iiV2&-WkoA6FhZLR#~yz>+((Yl<9%pYg%FsEyR_y~Xayg^`%F=cT`=-Tys~$5_@et#E;|`MBQf8@i7xPWBOf3>dUcu*-&__?C4CYZJ$$MPJc;; zVt!iXdc1mGz`&FFWOOFOfRO;alPm~aA7p45zTRCobyO%S2`u|uX^lUg-x+*!2IPE? zq}oRRNPm5Q=cU3WkLl}=Ohp9-xQf;CQ)ET$hS!#?`hq2SHA_^ZO}9*0jvwggw-z(! z^V15K7`gid(M-RGzn8s-&YLyZ4sf8oW0SG-O1fckb*^mKejX?qmsK`yrObOb8_ium z9DjYH6Mz3vX679`T#*#pN}t##@0~pGv|EDtmLHjat28TI2?3%0{4B_QI_Aa-W0h0N z<7r)^vFW(XV7ZgRo5tLd+4*fEwTM{zs~FsgPx>w@40QgZhW`ZeJP^KJ4iA1u$Z+;} z_q!c~quvCz;awa~`vt_0OSz${dtV`I`a`CBDa>_w2Glb8Rs@UXzJw<{N*wrxTS&T6 zzVrXMddK)UxF>9QvteU2ww=Z{8#j$@v$37VY~#jiY}>Y-rm<~2oA&PidEWQiZhrZ2 z=A6MbbIr_heoL5~m~&raPm4(i{mcdo2z2{ScL_6zz5) zRBax&0iB-c!_ncJGcCvYitGi;{-n#2NZQoakq)Hzdk0`-7*u+|bEZ$FTW$)blpN@lT6uldx) zCLOIzb$F!O44B-qr51VJoZk|yig%e>dK5Rut?%`XQLtF{%ReYjy?{=)S~BQe%zZR!duUpls}A zj<=TRxw=%RQx0qEq*>b(^tjv5MY%4yQOV}bR?zBF!e2VHl)YA`^2=W{U!ZU6dG2m8 zV{Ovz_Lqs8JUM1yuc^a3;XysVe@G%e2b^<%|^(^6tDO9mw{5yzf>+PEDwE4FQ1hzbS zo9u0X2ebe|E`wkD4aBQX)B-Y#OHlRlu|-JPg!7A1rE)FL>=SBkJvE8L>5xhuzgo?K z=2gUOchf+m3U7Sa5WXyHve=4$5ov#^fW^8 z8q&xjiP@cL{)%QeQK=FMT^qT=Y9_sOV@;zuxWt?PG(z3m$m6*eDdrgE1!&FF^|D9~toIEs1p9-@ReliM&iaLWzPD7&mP+T5WB1;Vb4ciLinb zRxk26?YZ#BhSq_6MC)(E-|u`m!GP{4>}M*eJ{vQ6@Q^-j&NMXs>Mpc>U%mUhoqkJj zrry!h^S80x8mem-wVH4DD4EgbN zSJzb#Ym&M3v$|Ib;mN7c0R>+vtq1tp++4z`;zWId^~<8F_tFEaZu7XTNBwP-NJ*nL zen=ACk_WJbYVwd&R{Uaip*Hr8T^=*y%Wxz3Pc$?|^{*;Oj~Y2?(IONC?P#Sch!Ur| z&kbsGYZ1+2p%ytCFDGC~Scb<0NM`Pzs&5w%NTCWBoP5`8UkL)d(^JYnhxt?vd)DB! zq}9xOI&rie)Vo}bwDq*{jb*ijdTV#8a(%m;v_q0M$*DXj=!ZJ0Q1h-YvE4gCy52`} z;G9>_I$8JGn0;9f^jDj5Hkn`Cz#kGu@1u*#Pb}%Wg??1cvA{+liE|&bd2eYV6|lF4 zcl-1u7~#=zbDyPP_&FGuyp8M#|7|P<0m~IGOgmH^1_bx#&$DvHG_1#T z(EfCdwt1++4H#1$;h^Ob7uK@ZFbFA9)Cg6T%c?$TtkiY+Z=N||w3FIDx8s0?wHU(~)QZfmSJ zcuDeDcLzgobztVlk4Wg6CW_IbTOOGa@$sGT=APCQUdb#FVKLshWZwdt+~4rdC$I!d zgO>+;Q_R)F*v)v=An48oCS^Fn@%5#(jGcbz93E$O;|s50Kxx0+>}h%@?{;OD=Z#R^(3^H!BMZXDthH|1p1$Z!EL`^UR;lcyOS*_}$a} zC2>a)a@?BZ?50JIGJ1+#g5ibwl+NHVsO$T2&H^1_v7|LFad~J&;71N z{|$_9PdePgyTdxymm&HO4_fpQO|csmiedKes4%OPqr}Q7#zuI{>TbgUuvwoAf>?5S zlA|BuG7Q`_v3}Bh`|id6o<&7nieWp~N(*mj6kKWiM+lPC`KX|q!x@!^QA~KEVLs|D zEU6_&O{I>uYM7D?c7mf1bXB0}l;}a;S zebT){exkE*=88rBcD58 z*eV`_O$nT8jW}j4+!LV|v(&e!v(8JFh5_>`^PWtW{ZWz^Nr<9aCM;bcpg`!P}fO6eA(dg$?IMOcHp{zv^kSfg9z_+UG$mDC z$X_MoL4KQ<7`;I4QESbdFr;Ws6Q#c37gbH-|6xHm1LM*0R&1@32|XD0Ef+@i^#v)R z@ATWJ4m`9NEKn8L<#{eN_x*eD#YtsnRt<&CQuA!k$_Q?_C0eojy_a9Jw#%-`^(t_8 zdzGQ=tyE)=dwdiQhXryj$|)|eyqLXfs27rOWK25C>YlSwKksK9WIGCs44lVLP(P^` z%^kG(EC&xLr+F7K;*z784K+2Z&InVkWHW0C+XNT)cwLomOxm=X%d7>h-su|lxS|)F zl4Ag^ER`8hypY3mgDKXVm^WO2YAdduM4~=c#wBA%tu5YM3c~?dzBSV{ zsV%f6I2pw&OIxSy6Wr7eK6lf4Azmk1TCT+BFh^PR%;RAkY4Mx2=@0(xd+Cz{@w1f~ zU?YSeOl=87g(|+m7Q|%C$JJ_5B1Q`{se?Cn3f^4~1FIbTN>yJA8fb-j`4%+yDZ4t1 z{@o`__goi15|#1+1}lY#n)nzJBWq`w~(GqFvQ) z&B?sV`Ched&0}ooNYt}^tsF}^oQ&Xz*1k+Cul9?p6ED}W*wgnDf<=joGw0?X{0Ozb zmfzD-M}1Jb(^9JV)s5l*uNT0`VN`#AsI`qz&u3J{XOqjj^{0GxyO&7&<6Pug!|OLW zoNCJBQoCP$m+ZBi1hvLHCzCrS>NT{xijrR-Oe!j-KV#%{@NO4}SqgIL;JEzH7wlZ`D6MsR?e_2!JQN2t8NYasgM^!nP}4JEps{zPIVuy_7!t6(v( zgR??XNT7+NaW2cIxjJDJ^%LfzPhtOXO#X_f1%gK!M%w6u({|b@-$Ak=ja@+jGENM zV7|TbVrj|hI&Nn14uME|vc;!+H5F1=ZL_-CZoGhS`^IE#%01EU$AR!|)|;tLx$~W`y;}wvXsOtyuzV)tOY*_JxG_^|Jzvo-E$7a+eD% zH=x!Om%2`en=_;0TY%L9DRaR47`miU{!2M(jQ2{j%1C&Y#JH;y>|bJvqs?}|ByF$E z)SmH~K#aj?U5hE3qldYv(%OKd90~|k5J3Bn6|@p&=iTys9UX8oq9DC+?#z681J34 z-REFwuR5*2=r6ci$z9xAxu2nooaB5LZ&J{U$(L_;u>z?J!EFX6=-_c@R{ew5sVF1g z-)xCsf_aRetX}mtq1qwMCsF}h+^Hw|m{Wl##L)U0Zve)^MwYd1dpo`=S3)EG>u+`@ z?Z3sSv%$A)_nV=t{9Db0{|gXRke0SM-;@mVI~n@-&-|k1RehS8Xxq#7s-SH(Cgbud zHQQ~=gB=)L+YXM&hTk6Zy&wfuU6G^`ZCmwlem0^njmVxN#?3*q1|f&c!H1U^5xy+LP;L^%sx3M3!DP7R8NMc?I-|aKdi9 zs?ixWY(yTq{)Bsr)sxy}NQAssn7fTZNu1!rFcl*6Or=(qNn=*bR?8dr034KuK7I~t zy=-vorZ28n-rY?1T$a$bg9Kn_Jb?5a@J1xmqBrXk-1trU#J`S{uwX6p@Q6+4f+)M3zfh3cQ}D1s}6arBWk^V-FuxHkU4%!1YXR3lJFN z+wGp~c%0hif_3+A*GQ@)MQ+36=rNKOE-f!^s@jWyUc2KxnyLAln^iP7O~u{yDyJhN z&Ti4i!k>Z6?iYg2@oTpCsuKsh(Fjx@Dhr9tdWChVDvHzu&oBrJYG)w9hSfYxcSJr3 zK5v;sOIz7KRzGU;@UURYe&w!=8gI>LlcfVJ99ci0-h>Yi8!z&Qo32N~Z&l|TwGb`< zeR)FF`NkMtR@Vkqvc0JsIh!tsjFva3a!5#w_zikca9nSL207bcP)y~mNDWSrxf(&M zDVGhtp3oEjM~mE0BELe{`0)JQTL$7uW6ZSG)y++a+$!2dlPuDT%!EfnSl$LV9_sH! z;AKlBdmd*kwG~_{R~~NfSuoSzRj#Qb*fVr^=J2x=3Jdt?=>cPLm#y-Kx+zbfDq3tB z=RF|k?wt&j-3Dp3r29V6e`Uk_R$4`U^uz>d`IBiynaRj7pI?5sxe)`Axo-Qr3lEYR zaf#RPn$_zBhU5v~N=-9)-OyYeeF9!b5!~%}Q&G|oGm_4S&9uZr;m~+fvh!unJ3ZGj zP9^Ny+-lYmh2w~s`{L3MSB=>G)kXQ-;V_TAlkm?hz8U_Q%ws8tPJc?~XZyq;{V3Q~ zV?=$!34}bLylGEmPX|1|YELZILdl{x2u?22WT>S!K}aW!x2WBdxwcZcZM)Wi~ zc&2}7>?R@9z(Z%1!U43l>s--v^}||{ZPh9vcEtd!N!a~Dmw}A*xiuA+%X+hH#0Q-= z%+kq>QRUyWT2~YWqxhwyT`aZX1n_BDsd@9;e|TQpR|3F^@b+bd$DHaKkz*w3xTy->-^3zijEt}A zSpAkCp})YiZ81YzzYgZR@h~%Tm?i)lAgjoxJxhqltiBPZH*H%UW<}t6{fYHM@$ud? zvyjtbkMt+kxV)I{w+{zuy;DJzGfCkU3}fEQA8@c)K>72Yx%rQp;-(1?*C>BRcW z=|NBa`f#v{0~zK#f0nNBbAy{k9fFsGxJtz03wGxod%w6{+ zzKQRL1#rxc!)yk*ud$cbep8nnkWKNHY0kE-WLFmxdl4)zyC-Mtv$^0W!ZM;3 zQH99|;ctMs@JWhqM#2_|n5cymHRGO%3Sy~bX3?AL4@Ud}(o2COgL`XJ94@~<&DQaa zr+>IS^cYL3Z1;T3t2)x<3#qzt@&b0yl$6s%70JP^7GR`C4CiwL5)Tu`X>Th-h)9c% zL_Ii_%?TY8kZUc4I>Bkm{EN5`4@y?&*xAxQie5m`F0Q2>pFpF%@HoT&K8KFp$)A*X zP`*Vu5v?&rdy-45brISd=XZ6K;UKhiW~ZUO?$UGH8i{OG~Y)pYVvq_g}#P48*)~0ucYKs!VqVS{~j|IAWr7 zC)fCQU8-lbdZ#Z*DI1BjhT)47D`-r!79V$O+hPe*Z+{U@Y-8U>3mT#IeMi~~_%wcb zsO(BTH#3tTK5w%eKY>24P^22-XI<3U(nSMKemLF#+aqx;zuU@+A8MJ(*2ln;jj(Ar z?GgoWjozJDx^2<2CxT)`uqhV~L9iAfeCvj^7X7%WRey;41bxaEQn6OvkN+$l(>wOk z1LlCx>c07%FnmEqB<`5hLqGd-I)((s>z54@Gd$j5O9<})>x_PO850|i-)8AyXi(j(9$2QQ-`UXrGLK-C9Y6pj5JX$}agm?BR^OWN)sd^G#559SoFY4j zif{c;SHe`{Se=y>2@r(~jng zgwHaNFy)w7$MttX(xIqrawp z49i#9ig2EXrvcBye5sQl7#QVvM8_RcQ~dTXfAhRNZ3^+8N2`C4A*7U{{s429&IBo% z%Cr0v<=1(^WRUf7z<3GupkT!7;z@R*YnSZiXIp%+iwuDx-n9mTrg{TTO?RtT`>J*L}UtS z<~PHywX3x(M=g?)6q}nB;JSuS++ND~=DQv~HQiiTnj2OnH&a0_(%}V;eXOs|`u@0} z^6mOgh7f^EM~tUfExJAdLrN2-BmJa$^>N4spi!g#3szmO<0XgOjHH37KTy7LnOL5e zF*AJ%2!UsTmKklOC;fD@R?FI5@X|Lm7z&ymeHjvEt#yEH5ZP$U`W*Y3d14(DtFfT( zQm5Fm3EXO*8yC3)^L;`0ja8VXg9!9RMg|IZAoiof{}r<$7sk;Az`6o?czt|C6(hsQ zmP-OVlA|RhYw5^j8rC#lWa-$DIgOh$ST=P+P}_|UaE9`&J{j_+)@i(nI|hU#U`-x= zx`Of%j1~u#!)||Uk2H(0?yAQgeXzx@$PDAV|A1!i(Zw6+S!~&1xsVuD5Q@``eZyysh`t&Nk zm?t&bWmyc>J|wesrxhrqJC@Dpl^tKXn?si`@J~9>HyxPXXAc~&TrCBY0)XjLG~L>b zM%2AvI=1`EM^sd6A_y7^uQAOIJ3iue|5983BU>$6alsj=6wehGN=zZln9U4;*Uj=elK-?U0LL2Lq^BKG9W;g0cj^7oQ~#K;AE^J0R{^8RAdjz(j(tOkkj$ z?BpGakHH7PK!*X;X7jTDiU;Ed1qKPgp;G!IEFB^63zTmuoxnCLDo$WNF{*-|&gc5s z11H1p;Zn*pjzjyAiuvN1j!38};tZH3)rGNaIc|6^M2naJy<7O@eaV(sb!ODD^E+@q z(nbz6c4!V0=$Fb6LKg+iGv5e2Cwn(k+JYoj5izaBU{o|sEO8jmLA1fWMH@c$d^U}= zun5x_-z7?*c7$r4ydU74edJPmldt(@NwXplu{pY@E$yzT_k2)tsiQMCAe6@2ur(Fj zNWjk4PT<0W*Nphk>Bvrw@yG|$J5LY3-=0e-*HGH4=feN5^H^oS_sr3Xz5>~PKul4APuHCF(5l&7oaq= zVqN(;UWM%s$cE^HR+lh5VrNWl`3Q%TX(ew=e6%!?!yEGIiRk!gPEphUZV{Cjy2yE( zZ_~Q#jn|^mZ8Oz7g~=Ibjiq@HgOya5lsU9=(6`C8HK zw6wWkX}W+v)*B|1FJYpb6O zIpy@tmGvAQW7?>DbwZv|BM(-2ID%R5iu8bT(BxS_>GHtgXk&qJ(U*yqe^_nsYDjk0 zea>&rs0fWDn5!JRBe!aR#m`NaP|N&CKgX=%;s_DW&m*<8kknDW0w-N8^;cDiAYg&8 zfcJEN#iqjtYNl$cDT<+Lh<5Eq+*XtB$@Y3JXf!ot+DW2{?5e}$y&4PATl5dLr|bJ9|5Lw^=_gzAnu-&Bq`W- zQ~R5Q$(rqYM*3#=7*RC7r&Uu-(EtQQn$=ml#LxX4E)exK6*!AJ*ST2lo6Dc=#%wlm z`?)nZ$kg+kt}b8;U+jEpCzQdV4n7obHLs_QR5^s$Ty5IuHX~A^Qfu#cR}rZv`;xO# z;!^d?vT%Nyr3C7)&Z-$h3=t0$NBGY%ys5C-X9#v7--s4_FCj7wOMENVcQ-Xt4QA3M z1ZJO%D=H1UigG#hN9#u}C)jQGhiy-_r4LidJju6N0HuB_t3UBVl=Y^1(B_^mJ@6(9 zc^5JJZ@D-ztK~=yUSqhVC`(k&=m*j#UaMXARl`y_eIs=D78AI$gq`ke|(MS40U z+h61WNF)v8$1&tX`PxM$I;%`e!taKZLHZ{9I1~=A%1C%oHA9Hn|$>!4+zIE`7-rnmQ{J_QH zbKcE~Sm8GFy(B92=cB3QTZTGj<{D$^QD=0s?9lgd-Ccjs9}426%^Sz}i?WrqBfU2t zxVPfxd=D;FeP42=kWt@vv|+$6LTKM~ytYLmW}eBa7c721KKl4fcr*z5{Do)OGbKkqW)C}%er@u*NBmmsXWYr9x1~0x~jD^iB`AHL( zGV3acNN^^!J?B)!PGX=|bzMfH-sbLkFJdHf1m0A-$GTFL%eC4ZBGOr4)TXW9>SSS0 zS(bx#G6wrLIa$6#IONK45jkxn`NEeUGehyacBU3(sw<@Ldd2@74WqxW4j2}g_~@JP ze$t?yAn3ojVTZ9WLG6RHa7Ni?-(}q2tCA8oh*7P9Y~6wAA3C<-sOgA8!`1PUQ#vz$ zWB|lDYRZ=k(l0r|$-84;Rft|B7#qM^nI>EDA1#A<^_`S1k{LKEni5(ug$NDLnaba) zM^`R@fw2s+KaEi2qBQ8SC?4`T*iK!;34{6!67CMm+x(Wh%Z0Wcl_Sl;eAP{%eW{x< zKjnNs8dF&U7dvQ*dklsHj)#(!$O;SHs}v< z6@;-{&;Bn`($ND`OIvly4C8g>XPZ+@29u(|^ zKBsnh>4lDdBs2GXKw@7-&Rp3B-Zxb?Mv}*en!FGW=MsOv&%qKO?pcSCjR2Q30KSot@+Uc_kz$fXPk|hM!%ebCjNTrI5NQ5 z6DsIQ;+;q!ujmmxz-Dq6LSpIx>V>it77&=!UX7%@Kq?=NGQx}V4B>+)v22zn14UdB za{C&9l>!evAOt~(k)UvEUUdXoQDWbl>iF!BOq5kVjpMmF6keX-VR_pS=X-}&4p4(t zUXi&)VQ1A*phkGFJ>%IQYzNnJs~@RBJXej3KXP9k0md{R#eGS9ae7QGdv;rtf_M+W5)uCcX8fe10HJ^k7>v)~lY>f&kyFi%V|@(E42eDsL;4>C;#(|$pHFXM*yktbNbgJ4eItQf_pI zlW4+*>y%5=jJyng-pqVAY}M*}vL>_PqPU~`Z6-(H#~dV5sEybv+e&EbuJ(X&Kb zzUE*>7^l8G$_D870$3oG>t}Qnn0AS5;^hrpfju7#)XlZSg)^R|ehXa4K-zF$Ab{56 zu+|Qwc?tMnJ`eH+A_*w)$R@0F<^a>|%5;#-E z9<;#MiwUKdn^mVyW-&{a2imKtbYhH|`#JeZ z{Vk8L5QRDO+HkgqRl1BCQ6J#u6*JYWoR-XDXJV?IxIS@6j#l(m<(6OP2OCH{Y=n?& z`c`-TuH(41*bUn_?foSVY#ln$z~@i2gzI1f&emA-7pkyCmXrQi^8pa&VS+utr&`EV zJwBR(%qv=9Ul*zq)L<=5O?k~_56*KeQtG!=E~R~jIE|gc^a-yq zE5%_Pvm|`DPL!09?&neoOFo8tUhIM&1_Yi{%K;^Zqq57HaX5e7o?bl4CxBl3Y18(R zi?yxIY5r)Mw&e|qr_EZ7Q-vDO$T)?i=kUP~Pd9@U<5;oc<>BL)t2lvuV{)BJs@!4| z=hft*mmuO8{3#&wub75i+&k2-_l?@zIROpw1(o2LcO#816KP%O?pv?Gnby2$F8z)P z1A^@_tL51x@pML{=UhTW`r6Wxl>gFH8W1!rIY^st0*R#N4zZL0a4d`CLUprDC4)%D z5+&zOo);xwwsJ}IbFb5y7?jn59`LDCwYAX z6`DlRYfdELB)%a0>Fs78KE1U+5lr#KyXDU+ke2GgfK09J_|66FauDLt*NYy z#0P-NNqd%La3W!4KLQ*(lkgv)*ysrV^#VW(-nIESOb{+1)Z_g+ga4N2FYCJ<#iiUH z2(!_)RB+x`z@BlB4fu`P7<`-hGPE*8KxL14Glo2fb4MU7*_>eB;Ekb&1T5(d| zuRNmzpuqa3AV3+%U_K-lm7x$IHPaHphlM2g3n_&j$z<~G?^#|=D2P5N<;O%sux8Z; zrl9{Vf z3g%cAJ3_};L-YtbT9X ztUbF@9a2eyBPGh{XuYUWHt559HYS&r%r(|mJ}#@4<$rq)*t6JX;MnZh0Y^5q>HFeG z*r3}iKe-T6ci6KYw%=TF*slw9EkQrwIgTjXxJcDF5$H`TK#uia1`UGmKmcjS&p(mN zZV@Gf1(4ztL#srVYi^6~|0yOL%a|QqvAefHOx8@?P1@`+rbbjGU*7O3@}Q1l2B&>h z(c;@^X-`H0Z%m{Dlzyn}3yHwjdRUF~j9BmDoOPv^v`x&kg296eOL2g=>22Cp251}| ztm7o+c(r(c@a1J=kMVd=0Cw+eh3b03kxmVmWwCxO2w zbMGO;@2Q*O716w31e*Vw$qoCs69kyu9x?QmQT#ub;fOpz3&0mtLI;9eHys?X)x{6` z9hf8pkAG#1Rz;8~WNE|Iz-uNxjHzq^<^6-!LyZuvkS!;;CF8WAydAZHWu7Y?`8bni z=Et4KJw`6AyEXw@io-+ehnC4J$3`ufncE*Mx~Vc#eRJ$mtLZHa+-|GA_IC==Pt7hS zquv-zk!{OGUQ3>3<%_oOaQ8ynMGoflLylVVrN2NuyCM>`dv>&kiutfSgUyosg_Om< zARR8YORNqbw6VFR5_d8?#!G}g^GPDiOW1*&63i7@OkKJVKNxT$T@fpX?x88;>J^1CPHR)~}VC6C0ZD;kE?r6=5Y5kMLBitYZnqh?JRlOxms zqSLt7r12Pw-@Wj9Z1KdBwSPlj2MuW^po3=Jt5h2VKJvtgbif!%)-=s4;GH34sh`MU zA_`}-NuB+Z7&&ef4rjL0+cPdmYtwKG3(R)|9rAx_8XtXL#G!m8o?&C= zY%YsA_zNN`Hs2~Mn~0g)a3Bxd0wW5@Z0{mM9)Y9RkE9L>K2JctE_-`qVX^NMRzlFu zA7)$}n80^r6mE6c8?snV0D6lDvgPPjrLGtI?*}qgbc~Mb&}S2%z#1ec^xFukqVNF; zt}tY)g;FK#48~p!9e!yS)xYis1xAB8s#Y$|*`2>3ZC_qe3zGERa=hlODI2H78PBRr ziv6>0B#?Ex$NUuflLm~y)ToPFeRRG6p!#+74tfxa%dIK+FnGmbWcVE>y5Ayl-U|dh z#~eu+HDQ)~!1!*ipsI0=E=c6*2L`}{FdH0mG5bMUPt4LkN+{k%==*4_C1J)kY8SzX z>10XceXL@@yoV>1m1^zA)+dnh6fEft_359R=^%Miv;QYLy&(Fg7{Awu3bb0>FF<@9!Qeh>am4rk#mA+wc6O)KGsqYQ`u~ZMuQ{Rgo8UU4eTAm2u z;yfO82ym!C{q+F9dnJQ$L5vvD#JwIkHBeY32M7Oa$8v!@zE&&0gK9km|2> z3TM7$eA=Q)e|Szh1R$F}3{9*$)ZD^>n1jgLxOV%pz5C`i5xpUV*TB{uhB?Q6&sSqI zkBf1kK2%Kb8#GG;0tgEkvE$(|!Mo61UU&yDa4=u96S~y4UKR=>lR>Zk-tG);n!Io9 z_rv}|cgYfs1)3azHtCvA_~^%DfLey(tY`y>C-L2tS!IwagZ*_9kN}m7I?G9rVwC`a z;(MtE7p6e z>1dsNvq;MhP)R#Fq6K_hbmZ1`;G6|2Y?|P8nZ6)pb5zxIcu;+Mq#FMCtN&yYjy}+T z`COwKy#Lw@fxm!PFu}4a2^!aGYQp@Pm?MtnZ-DScHbedd$n+D2d~+Bb_QV?*U?uZg zGZa5VXYI^616=AqN|xdq1scdz*m*H{)w6&6zG4PHITRW8g~*WW7+Z{fZ%Ms6333>Q zd|Nuy*WogZbr~Cg3)fO`s2OjAnYARJ1D|}hUv}5!4iC<=eM%L<9DNZIFSSlq0p912 zO}c3TDq8+wp#?!I6hrvuR0$YhlzVNwl<$RJ7F9k%)81p|`U6Y1jB>RyRM#VCMGL8$ zCz+Sbsl^9%!33?1yb(_Ov+1w|8`TuC6xx_!YE}Zr^mzb#$lalB1MgAkpFioFuEq{W z5~lK7UhAq;xm;8PwLIZBnK;%$^XO)Hmm7ZI<}9T7t3G@X7r3^q&i|^%d9xE&@b9%6$X`Iu6sJ^>D1Ib*xwt53M1+f7F~?H=byn1uN1x*GcQ9ZH8*q6a zBY_Bxfw;KubnuFozEG)HlsAK&t=*cbrYXtxcH4j4a}BuOET7;ZNLlqlQGODt#{GU2 zzu!Q(nc<}o&7#-&C7fk4-Ht+DEp`vL-(2X*j3YW|@;iULQY0%p&x8`tD>3iDq#4)L z0}6BL+X;s7CB<>&VPbXz@{`Ng<}`P@>I%p4G@2?szAqe|vG<8iQSC^34)9By^0ge8 z|AZU@^#XvJyY1=KK%Q4w$X7Ew0L5{z9VIAbe`XshQxC`M!iVX(54pz+O3u;BfS+xb zmuXaJN={g;GN>nv;+%H5P&P|OFmG0vs2K~>i(R009SgwAX*)^m7g=sf$iibcK%Ako zm&1;&RW%-5{;(d%fpIbJPWi=?{q~Bs5v;aIRqXGDAcIi2AphUH(SZ8X!4!4LFEi_r;neZgs>a^;*`DyxLhjPxW9M0{e#hmKh)c0I?lLH3|A680T=8? z=`K}&V6j9UF;!Nlr=@Vxmh4l^ z^t{>6|5^yTVa%XA7#S@7pb{;22)SaHok7B+&BC1X1S0gc*+zF$Ep5U;=%8>&q!q2_ z@89Va>dynt?}*aQrP-RSSEg2I?w>yTX>mJh2p5%L02kYj@L#9zyK2jkxKue6I8|r# z3(tScx!J``{PtAq8&BOF0$_ieFICgcPUb?pFdI^y-d)fCA7^?AveFISz!?w)?u*=z z3-crWAc#m11_&a^2 zxg!+2^>mE{T)#d{f0gbp_c$G9+2b3EeyyUxECoYu&K*nTIV;nVPzUqQUGJCf<~JVR zBMK!HzaO3Db)E7_im;i7$&%9j-$UVp>~#;2UG$bf>0zVn#okVeLFMgDpt0iCo7_UW ziMNV15li(xQSI)_jef-?H7E8w_*O;BAon8q?Yjy(*n|H)5m3Ki1&nbM@q1{4LO?vN zM=eb-AxpG<&NO`>fdj?XT%cP`t;j@giX|(HsW89X%WD3+#+v^X!Jyu1M#va!uwWqN zVGsbWJdE@dd!aIhK;S|TB10}rW>K2i3=~OL_FYVh$*N z75BPfYIQ)@lAR|P-Kc4x(h1_~Hht-$bq^0p?NP^`Q{~b9K8fOeDlKC}h07(grH2UBWoPEJQ|@M&mFHu>k4ZK4Ixgng{|Js6(6ePm23x$j zeZOtd%!;pL582(44k9nav+f%N2KdKKI6Wb5-zD{EqCRswl z#d2YG9$(y5ebuCmO#6VP(K7T)ug0dEnka(o5kuwfpt+rTZ#wVfmUOC$NJo<3$}p` zh)k?uRPVm=fny9ZaArDz4Vk%fWOZ~n_{?jyRm2e}uSgA{UiO*w_DY+gX_>7~g>Plw zS5Ja3*a8Cm-#cOf!3o>Yng2%b3V4{2^R>&nIyX}sIV;%Ejk$e!kr(jtuT+h0l%&0$ zA?gGqa@AS`*OT~ZDm~@^qSwPDtag)6Xw?Q2=w`*;-C-e8#UM??zol)M!jlk{Gd=md zvto@UTxOF;$js!DffqM~^S-oMp?*VTj&3#YI~(62JIBL|>BLDC&LtHl%W-IpxWYeR z>^A zwF8&)mfEY^6G|W3=-10@^^CJ^PWB%&1kVr4?DpS<7py=cqi_GcBq9i?w_F!I^XDJn z47xLjMPk1wds%9YD~OUTv6l}3LEcbXl)Ou>Fm(n4x%vgO%Xb&!U&99N=uUte8V@y; zi#%&KgR07ow4^nKHCr%O&xYR2vi;DHC#YBDau)!!)}hBP;X6f%7A0zeu>odpp%?XY zJGB!ti0~!^j-u0QkeWrZOT;}tXWHtek>dP^zWmTd1bF}|M_(-)K_@Li1bRa1@p6U2 zxK9mSC ze>+|s6_&ckYR>&|n<(hFJ8WR+_59%%MT`q>Q061_i_XM{V&U51D>##EyUs)m^}qB_ z>W!zTbz81A11Y=;nBNO6AQy5hUlQdmcREzq`(Zqc&8QM3MmTX*==)KjIn$}LIF<*> zW!yN>xL7!}(d8aKyTx~Qe0Q2PLw4H8aN6<5V~71-6S;OG9+;2&c$_2S?=ARzkJ zR`)pXp2~R+hF8*wE12G)xv+v_XazX`hq zkpbH=cv$MP|7m;ITVmM7p)37{+Zs_qtY5d$eN)nnXuuNmT2ictvASV&i8X{GEZmts zzDQ(lBM03okqvTBD2@kICE@uT9v+%^p#dbOJh^2HU;q<VW}MD(|!X=eu|)x z4HJZ<>(P7jFU-)cK zD#+0l`N6vbRv>bhpQ(n^Tf58O$gU$n7wKK~C?4%DYc$ioe%T@U`fS&QAkOTEsD{d<8O=73~9=*)DOBY_d z{skchO%;J`&I1GT>N&@zTaC(1b|{zk4+*lCXF{?6>p=d0nCJ4oq#DMDeNg)xt{+z@$uj2?vC`YfyEkC_45s^!;=Y}Dhn;Gk!H=e zGm2%<=dq2j$~N-&BTtTJ>OQTCrrN)SsyEV=4a5S>{0F7gNFY3+0m;I@@JDISNuRQH zyt5AVy92-?JCRLpxqbw*gna4}yFRpDMk4@n+K2HR$3Dpy^qVwkd9LM^O<52LnvNib z0s!rZ`trBX>1WgZ?CfW-9og?+v>U$(INc)NTH*X3y1ptb$}ie`=!T(7xE{d1d$G<8Ie>;C8Se2B_)S$7;=W3Z&3f9bMc)ko|y}t{l2sJTI&~UZPf2y zX}iDG@WO*SuqI`)%kci%J~NW#;W9|AqT?|=2j%ZYp^k19=?E>rN#-#*I_d+88u<2n z0WAUIC`WS6g?l&z>Q`8N?)+UtFdpqlM@URR-`0PSvD;01V>8pfxg_k$NFKn>W%Q{* z7U1eJZBJ0wW0d`wmjm7SS$-{yJdwTIBB-KG1kgqH?k!v9FxB#Pmd=eN_AX^0k{l-K zjkB#~`=KG{srvB7^qye-&xA++NBMyZxPKrhLQ%28b8pbU)K{$&v>I;_a(;9gK|#>=AMMC=wMNI zoqUxqeTGJpzC-Nq17l}k+%*!xU{t;M(#TVOk;E!r7@s0L)N>fMM@UPIFwG++JzB_3?w>PQ=^#xu@Bf*yV*%kx_cR5PWjKhZt>jW5%3XeyWqZ zMvjREx7AWdNzx==E8*kk0AEtqmW~V8;VqC1&dTZ*ISJhp{!wOtBsL(!7-Ll7Ib9Dn z!PdUVxTUN|x_9T>n>5|h6f1lBx`rC^`Dzt^tPf|`_4-!-ZGV*E6HpiOH`+3PVnKVm z*G9xm`~2W_FA{hR9<;S)tSPB}aHHhv!8p{^j{l=BI%E~%U^h873X0wvP6zyw1N88e z0?`$M+=m2S-q{01fZ9pgLH8s!83=i+A0djQ-FA9GvSWeL;f5I|QDr$n4bqK`voi)I z#?&=KY{>CU3!GMNIe%NU+O7orKRN5xyLf>w-=@fMyUf-jR$#uRHTFH}{?&kgQ zrirbL-`1hy!W!2ni)C{v>yp&G@4uST@|FbR`9lKHglzRvjDHMDnKpGyKyKP?uTte^ zM5*hOyj-oOabVxi*JNL6hD#AtWAPA}lr-4AJ~fkPx0k_i)svDPGEWieYQy?9?W&uUPtB=QAq?|QeI&qe%@j0;tI49O3}Mhz79 z1lLOJ`|=)8g!>@dWIJ;ajTVf954E!;Fh_DeK2x2uYA@e_!mm3C<5dhEd7y6fcj9l2nMn#LS<6Bjfj2Xk-~%6tl|$387bT zyhSb9_wU zV0ISrZ&{pfl7#)uUQZ`o>nX!Kw<7pr!=94OC9 zUxjMOz%{cyJzlZVA;%lJz^?HSFGqs`+R{u-)%g0uz;*Om?ka)YC5M!2Hk@_agNpe zb4o_kWr3rFeaGnvM5W8Odq8~-n(Jo~dZ1cwRoYSIl)_ui<0WHO{MLe~VW zE2MYFXPnwxH+Q#QNCZ`yr0xwod-DGejw)%PKkSW(#cWc}VbD42eF2J{>V^-{={P{Nd}yE*hicv~1<6G? zWvMDL)9Es?+B*iiy`|#38=8a&1ePvAtHD zc+%j=_bA*^(TM{;BKC8`rOj&D0%g9N_4Q$`Jn5D7H(#kA;a!st9{!H)C|=p=R*%`c zET6a)u2ylgva~W80I%(F277m3hMRiia-081s*KC14u1qpE`D}i!GJribuV0tqzjSn z^);j%ErvcQ;Gl*9p-L%-WgO-RWWlCQL6NHUF&q>=wX|2hXRBy#*ccfLysNY={FP4S z0Ob}tMaU^BB#M8vy8oxS6UT5n4&B!cC0~$JF5^R?aHE(>nh?+Y&ywiI0a)@lXi_ru zzk^eFt01aYBwYFU^mkTz#Ek0hVJ%I>{YAB9tH7wmmiAzrhmi2sAXCCmcj5T-ifmyk|(YJA=P8CwpVlDXII0 zJLR+aB*}3RVwEKfaOIEBr$6x@2_pX*a05yC&r8gP&aT|8cCOnvV53fy!L=;f{RyEG zt8!nu0QU&O!T*7&<}E|b6uL3i!REgmj7?jXa-bygYwRWU zsHX-gG@BnZ7d&@~!xRjbpzQC6E);kO)!%2zm4%w_n!DHNXGZfgvDgpf?aF$^7S73P z-*5xDQ*`6a3z!}$+~9;!v*f?{lT4p7qS(@>3s{)9u%SPuRgV~eu)chIh11fb%$mbG zX+Tl7#6iNSi|#3$`od8?s`jMpM;s4=*A@em2M>5X6sF5H?{!pQRe4rcQ1at+hGrZuH+Q!Hg+|inb$Y%DPgMO)&iJ z%y0Pf01Utz89fxTRsKO|!0s+Mnb42n;3-se4FR1GuRugdGQ*kUF zHBI|37Zk;>Bt$|n;n-b>xp>eJ%tx~(6NEd)UcXKAf{|lz!+ZEN$hxF_*iuM+OVz$}f|p=ooo!g*c8V38=6H$kjCtm=2*uk;U7i>CS#tyKwKMT?ZrMjIoYbuvb6DC+RaYV z0I66#r#q8_UCGGJGnuZqN$n>6y(IWg29EV7Z`W-Vn>djVT?ww;gV14)&S(NZ0O*2$ z;rECNYNh-#T4U)tW$ys%D55O+|n3;L9c5whGDC2r|%5+lA55@TKBN&D`<@e z_(EcSp@9hj(*th)T$ig&En3IqyM8@y2Yi6g@K<4RC7=64!6?|d44>UUwb9w1Mc;a@ z6s1tPH*Y+~n&`~&)DGMCyW@#kYCM(6kIA1FUp+;=yCHf;^;G%RWmALCbBj!|I;@YM zXRJKIF0*nR6caH1gLcgdZmEL*X`6Hna5I14=moH373z#2ScLs#J~#cqWDvoyr~o`c zg)2_VIc^GflN0)T;fz_6aUuXtge5&OI*eISEq>xQb#0ASo?;e#E6QIme`fri2+il7 zhJaiMH9Sk9FsuQ>j95YYz}PknbaZk)Yb(A};q_chEtTgr2Hd}-WsG4}7W-s>#=Lvz z^~pTll(*E%Sa7(4t?GXSRVyyK6s9XCjp(0Oix%?B!#*-h)S(U_iA(p>f~+7wU%jKB~>wo3CILrvEha^|T+#Xj!4X39FwnO@LL48<|z za75`2`g9sT+CO6G9xCG(x9aNMK1YQkZo-`e8j06k+fp*Gclcg}vG>_UkRGs13V&cq z^W2m0-2mvieS4inIL&<_RAd`M)Z>1Mq#FXb9)Zl5byjKRur_%@f>ic1rkKs!`%-a2 z*5!_KES|e28G$Z^j!qT#rN69kaRlOkFO#lgE7Sw8Hf?xS?=jk7e30~e5Z~)n-#rh) z-iguOGO83I(ezfmk8vdpfh>!HbBAaY>u!NDie;9$ZR=e#mIvIfcmNkwuJ#_{^$ZB| z+t9bcewUOu_jLZzuP9cx?I{IZFO}L^^Fi_{>26xU8FwpP4Der=VrE0}({5P5^S&?} zK-e`@|IquWVd(Txn3jYJ>ucBsl9RkM`yH_4-4{2HNQQd`Ko&<#9lSQp)E~CQLN(PV zdK>=8D;I)AC(~|yV=ldv-6CnGYcjFuiD}lsRs~sAQ+>WvQnU+njh03CAZ|ClLG8E- z21cEZYl_x3t5K#iug?H^FXH1nG*-@Qs?zq?jO1G$Q>)q6qsE#H(kuy?4%eIZg{XOp zJgt3)-YE2uWsU=2!%2DeuZX=B1C@%4f0M2i?6|ONct^*I$F*OuLOzK$rTr1fwk|pR z<@zX1^nOjY7AOFaO4O$MZ9Yp>Sfj5!AT<7*{+Np%eQ&Xy7~nkbY+|=LZE?B+L3Vlp zl&Sd=m}!m8RqUdGt%0J2yX@2ZLfhS!@zGE$Lh0lC0%4jJfH5auNOx&?|h}=W)GOJn%D*4lK$J<*eLPa3_v0J8|t9oEF->` zhsP@WC&QGn$nRar!Q&v2^Wm^?hNod)9^;8U;S}%>rTQ=UaB2c?a-@lJlNlw&wiXX@uBWhMG+=r zql+^OXAA&2gITk(hp%Yp^CP)XcWgE4fw)lkk7@w)uM+a`9)iw0{`2`$fuytwg z|C-Suq}WCE?!ed6L$7K%=06%)>x_SU{P-BSUjNG}ub(6DJ=Qlri~SeZELgR@o+C{* zK5K1PGB}uuN`FrxZU`M31G+(8?$_UxRWA_A0zM@MPvg7js8v4Q7&RjiwQB)j4?W8Q z2hbfIT*&DfaIZ4$Ii3)cv-U2zSh$a+8|Ks*ZJOG2tNp;OwxS7@Z}Ld;N9syOn*I^G$ z1IE+T>Owg(65Ip2-c5H>7#EBm*oBXXmK~gR?S_NKE_N+53iTV$+VP40*#>A7P=yYu z+4yfS460=v@fdc~bg3HP>nFEJ&iO!a`C270_$Xd1Qv7b-FNwENt5g>9Sx?6!Pc;^5 z5##So(U?~Z6ZQkI`cLLtu3hev-Onza-OePYf7JsG3PZ-QCsEA_saqpQ;oiBcYkte7y$K%%B1)*a*aVi_LIOfzs7LaqsqD8?mAp4GQ~2ywdyf``Fn5QF}w<0@gwD6LsMX z0~@a@yZy4s;oDr5RA+%i!D=sH_#@I7s{V$-GA2t%)ANr!X{F`vltwN5d0AOc4051$LPR~>Aoo|ZWw{a<1 zr(D${wlz+Ev+gTe0-GQokCYr{fS^)qm;%XPiUf!r4Ma`h`ZuzGj9Cze8}UP6@nJkE zZkiS+6=sE%r@Dssr-BAfWct^HDv?-`w1`!TN@nEqc(P%I8x1c``sAv_Dd1|(S)_h7 z`X=`1H}4|Jz-xYS?DN9plML}?#^ZoDIJFDjtT7iKJ@zh6Yjo0JU?pmC;ozd@T{#y? z)y%QKN?r(353Z@5TGYHO5>a$MYf<$9alQ)eKoZN}fa*NS9olvPt*lovCEWkb?a@W~ zq~&8H`hJH&4i#tz$%4*76TGZR$)z#eaygXSRy|kdd8G$$)i`xO-*udVG=;@7OT?<4 zv_xaVdG9Z+ zgL``<0eRMc>LnJ}7$rape7M=h=yk1l?cvOQ17(?acb?yEIIl_^-g|!Z?dNmlrpeO& zcYIU$&Qv-`A!nt|Z_BSwWC8NW{{9U&xMx|ot%ImqqmWh_%UXhWP>wqCa0qd9zkA|< z%tC%q<{{VB6+=?p{r!!3lAxES4N&q!m96blhbI7VNd|~hN=4hzT-4i$^0e7f4OVv= zNiqF?BWX~?Od;5MWCb%nI5-&81RoO6g{<&`KbfH6(!Bc(MZ#O}-ag2GjUR3-um%5v z0?>6EiQ^9JOe_?@OuonU!Kz8y75~##Vz8Hrx1NJ$8Pf#XQH$9QsCwq&7cnkq*4xXw zVj@!-aPQ-LmF-;}B$NpZDh;ENBF$n2$bVezbsEhHN(EvZ&xdm@qWp0wbxNx~$d?&9 zIu#gToerF);#Y}H^E~g6k&bKnsK=0g^F(j>$&Q-^gM!0ADD_Wo9_PA8Z%DtMGb3eY z!H_GqCFB<5nmyaB79))LCTh5%;4j;9%eJ9#77cavA7y|zMBkD2CK+^|d~)uAvz2| z+j7R-Y5-ihhBRhRuImFk@Vbu8x<^OvJDDu8guZk#L$|+hV*~s5UUu^xsBuXGz|6y4 zlkZOQf=?EUY;+hyuZDTtK#f^DQ|0Sn=v#JL3=lI>?{uAyjB<9%UX?klwoboLu(9Kj zQ>2xS>c!R<+vQ{=ZO;v%B@-~83Aq`$HJYbp_ZG#r7x`Tw=!`{>wQ=f&E;kilJv1+q%Y(uPc-Ms zRK4Y4Z$O-loxja2F7!f@{RXy`d~$Yh?d{`j_A?7NIMf&r+0CVT+A}<<&Y8aB%`M1$ zT)+f_wqRrhxim=o90P$;+1dH=$g4dMgvVk{Pdruxvy(z@Z`adms~pwO$~Z$&meTGp zTj7%3gLX}p0h!q-&Z?N5$hr|8&GDDQ5VdsEedf`P!U%3Ji7Nz-OVKQ3PJ1lbq7mQK zJS0SA$J602hYAL&Ye)lDv3^GcN(FFMXgGYK$$txSbI4TW4?ieqITR1#YC5~1x1(+Y zki|&munWWG0ooM9(==0Y__I<0Q4g&_8zzN7&8II-xSyzO3)jVM=sClEoNNfn0kB0d zQ7UYQd-5<3xe~11aty!8u8MFcK|D^AijgAru3+sID~n`qu#Ue zqV3zA9LAh{Zjen>XX(wX#K-}4@Rk2ovguX&X|kXQK=eHgV)>d;hKo6i#5acF{m1^j zpJ+IKin!;f)XCk>((mc!Oz4JKWa(b2FWNdQHQK@^K52Y?MYD?B#6<)6ud$do<^D%` z1JPGd<)L6)tlw|?<3S`ike)$n1$EQ?)?O_H6{PkHr%e6%n$EiDw+6)*wNO{N*w?$A z-m9V232b;pj4eU>O2WKWo=7`aNFmBC+Uh&zIZ2x#?V7Fikg3Lk1!nfab)E&z26X~% zPHM652Vk<)r+27AcpLQ%{VyvUEtH^F(LtY~6aMvk2?_MgoW5!v9mk*JD+E zq>T#r&9S3uL$CF~!Lzw-$(nN}$iUv1_gt@n0vQ5tf9Yl~{-^0xa&X!i)BFPwOh1(I zCZ(*so0eIyr3}j=VD;6(FI4SzZ8$-$vKoCFt#a(dE2`eI=cw>n&KGe)TXPQ5g6}Up zxJ1k?CU?jGRC2!Tb^vtiV*=!F&i6r)PyPdeuB0fU;5)8n(jSG36g}Xpy5GqOOz`?D z8&X8F5G>GySbi{#2lMkoT_imgEzp!?5`0~K(&vDS4eh;$*L5e{A;JvcIok_)n)I2H ztljC+GG4pfij%c$O1tTR}WI`$}~bD_K%8&Z;-O!PsQs97&;SeL zPXVo*svS3Z!+)9ca1ulO+&P&-)2@^1pWOqgpTLXyS-VK+4F=mK&Lz$k6sqBO0@IV~ zMo(q`LNhkFg8M}^%@5r zYmj`W>HJ-JzBud~xHVd!DAgp0dvE#JpPgAo1A>De8q9LYZI8`O&dG+%*9yo&IXWPP z!r4b;vESOTL#%-LL_@T7AZ{zBAhsyuc;`he!cadPNa8%hm7gytnbh~47B13oxT}1H0c}vh@&J76T)%r^xYG2l%wQb4<0wQ1H zm2(r-cZ!~MNv!OzejeV6g<>Y5q4FBPzqlo&rX4HOKIF;TtsIjV|>IY zS3Ru7*Q1BiYFmc)Xi_kcfUyGY*s&eGqAo;|&Q}=S;J(y)=JuWKma8RX=1p(#HKefR z^59x+>z&ILHs?^-YQ?@5E5YHa&zWf+ld_X}CleX~C~i)vfJSiV!*Cc@{>{cP_v9R* z+ZH}Gi5pENS4dIIsC3NShCErnBiFBCE5(<%US{m`8`-&EN?o8=5o6CU){xgYTR6!6 z;Pm|fgmVV^V>w!o%Oz-UEHXU<0L~n8qB8wRKV7aB#>YalrupWfRu663huI8@fUp&q z%Rm5@BxDX0__pX0A-%FV6PVTCwwM=5vPVd4PextF;RO|hb+u-%^d^A+nRYgA)$5IJ zExO;Cpg^&;m%64S85){avNRr$w19VX9agjjO+6@tF9cFc1IqGin~$vhj=z{bH1$1> z_1N1!^*Eh*SM{3je540+C=89gn_bpn4o#QlF+pwpuQ!jzG9AtoefZVLE!FdDYHDO! zb?NO+X0ddI?iE0;#*nfPEBvA5*ZVE+n$HBTN~`L;2fZ++6+J)9{GFHF?(@mZ(|4vzJ`!7dM_`;=2^b?t$7Lx?Cl4H2 zrOW@GhVQhRW%XsroSjmX?Nnhu@mTgoA3LVU^mycyu-!|{o;}0I(7XcMM@Ki%ZNs|$ zoO)4b@sjB#`ebv#>3H5EfYK~({tmUqRM~p~;NZdB8*t|&wvw-9%5-~1DbQE@$+uFu zdXchbqt5H_NQ7*M^z|@|gE%QDr{fiJKl=nA?Sgnq^n_M@g(Z^xlKp1RP9zffYU-_$ z=fd0nyZ|fo7@e3Yf9ggs&_@mxX?^4x+4+7~AcmOgg6ozjhYI^AR44^|ByPIdv~uSd z+$_(V=9@Odoo8m|)LoiSt4~T@0{cVJp2-(`d3ha1HS;AHHKsn4zK^BYQMBv%Rc@L@ zN=0*w&9JM}7DM(OVDa2~rom0LbiSL1;HfmSovUb061Eb2)lx_g3Y5OyLGA~qnIQLF zikebQP$$P!YbP^JdNvY}k{nU$F`eTq&+2ziiJ%8Bo?h5)8hs{GLP zCjoPyC&Nw=OMjy>f%WXv;|tA(ofkf%h2NoMVfx{^m-nvvPW|0YUQ9r!9oU)R)By`` znw_55(AJ-2;8sZXx8a*6r=LXg{V*bOshUJ1V_WNt{#oHI)h&IXrZYCCM)Gqs*?(&u zxj`~Uav0Su8bE3u;qM;)jq&?6#KM#v#hfSEKY0H7b9nfZo4%~PuB_gj^=>^C?Rd_J zvwWry{IZa?>O7la*UeSEnc%BV?ZcMy!|tuaX?c0GZgd<~81t}9jRHC6&$~6WzrJNuDvE_ZT$*A* zjxUivDV)!i<%$uFs?Iqih@uPw#8(bpz;BL`62=WT<`;V{m+)5-&_(TMCVm*w=)lMF z$gVSfV!An%xbqdG!<}h7Ql`PR0H>h*NJPAZtE!j)m7q-@%4m<4vslB~acZa-LQ);Y zH8sR^dTpkZ7Atm=47enR@hV~5;o`DYIc%>RW*f$))!<3}QSG|Vi<1tQb5?_ko$2pW z>?rArq%J)d1U@RXs?m$}fAiY>43o7#%{b^S83cjxGKWF-fqTGq+$s_QedTx6i?cO< zfL!rd84d=R$5`-+d&ytLSMD(#!F2qI3J7Z}Q23UhCJwlqA;e&+f8TKEiJNDQVMljE z(~$oUPZih5W<`+n5Ly(ML?tqh#3er-bb}jt&M=);Wo>k+adDg+G#SW6e7F%!_K)ss zra_$_gt_axKO*Z-W@vtb4x7g73ejIRO)HY1T8l72_XqIUc<20hc{jvND?K6~I@NMs zdNSw|#Mb0`U7tNZR0?NDR#8TAkloeM&M%<~=*Lu)dSInm=j}P=Nq=24XArv@qYqUG z#Tm{itVNE3)InEa$WaaMu6gvs;A8O{d%qQNq@mxnQA>JR(@kuZCzb>FiY}CnKGSC& zt(>WZ4cNZ7`69W%fZ7q0n@g`|K}OAp{J9cF#JaUjPAFEPz+SvY3Z(?;8kQL$bx0RH`%Ai*0$&z$fZD zr*S0VCIIOaNf7QMzbJ%GRtq|34-8mQt@qq1ObjwSJ|^nByh^G5CQ>0rP`s%T3@-VL z5u43!UwbIpd*8p%T^`@EXfwGrWV)num>1>98Zc|cRzDid6pzKc-kM#kEyoMElwNEb z0+$!@AnE~8PqLOxzwwi)$&q?1#>luZ9GFw1g)smfcD|mQ%Rc=@Mekg*s$OjH=rTV#;Jum5`_5O0m8-zP6f=V4gU6MZnx@0>G=*^P zfc1r@hH0YX5ZS%pw|vNP(8|~~ZS6_&uFa9l@#I-h_v2@`Zxswgcrv4UF3T}IV}H-7 zGC;?Sfi7{2X(W(>9PM(nuI9iGF)=uOif*vIumWPZaxlOXmjXJI!}0F)Qi;z5aZc)-Xxv$d|D1FCKTh54kkLqc@ji(jAG|Ywp(Kx~=zk#oxtWevlM= zbsLXerS}#unCCBH)LWC%AdO47T&2^2pc0RDx2bHaz8fR)8-Ev&%#w|>DWMttRm|D- z1m20#L>tc5I+5c+w=>y5 zUnqrpb6jgH;7v=*?C|+zeE<=}YhB3bpLQfCi{ftr{C4yI&I6+jVHWeMpz9fPj3~#| z(%4N5b3B~CTrq;=-$KON7UZ=D7Ubn6rztt&toCPrd82vw3|^|s7t_TaqaA5ndPyaq znG5`FV&!mOgd`_qNSN~HMtG_M9$SC`2?mBcDJjPWSN3=(&I{u3!3hYP`cs;W#=!$53qU7>>8Xwo5@b^ErugV zU4Ro|R(v;l4Sxs9SqR1mM>fG19(W%>`!NiPn5H+R$x32Aphtm*?^eJsEM#A~ORp6F z?Uq)AK8r=kT`l&VqB*}=>?l&fP^$b$%;-*9O#insIVZ=WA#9GBL7~Yb!Drtfg|Y#% z(9-fiq7Cc-k*1pq2WBG)bt0pty6hkZqZ4t3gxD;bIfI3n`CPk|FOzUdATQa&!k)}l z0KFtlQer?{A9AD%f`wC}^^wM@uJMLfb{?rvf0zpTI)(c^uXTtRx{qEGyF2D#<{IiL zEa-ZT0%1+hOdk4AnP@i%G^W(RP1L0&s+|4dpPSrT>$GZWLWqdDENK<6XX^m|4&<2R zhzsRpAhfl{-x&&8%XOE~jkoji3HQ8cIAuRp8z%nQyOiwl9eI~wIia&i!VU>rl9g#w zBmNk#(ayhb(_AaFnvh(}HT%6~Za)a$zjNS?^lHppGE5)m^O+?iKPNEY<8bg~s#C6G zl#_|Qapa64I(11Stet?b_xqy4No|do!c_>Hbz9iwLNGja3wvR!CHSB@`?(;-Ay@B4 z@(ryQpX*>iX(ujdvilkNz4++a)Fu$vq{Cs|qZzBXHAxDAU5r@pnb^c5yMeSh~cwuy+-(CUovTQGP<5r5z4 zK*Mkar)G$2`i#gAI4_dqXXwTpb0Y59_t9K=!BRcQoq?gqp~`{Cnk}bZ|BYA>!9L>`rn!bxxf__0bR7~+PSiKlYyvM}gyfDR>Ye2v#6yUd;X4Ki zUH=(9V0Ta$9(Kn}`llU9K`sd zwjTq8I^a0A9C`(w`Z+mNvq$)Wf0$-^4pTvHn`}V`)S{DT7cS7VtL_T++5vzQy^_vl z%rFVe1Cn3A1c^c(IT>z+kW`7-0yP=Z3+tW~=LasU&YkBk7)V?3y@6^v*1%zjm!#l2 z2IVOa-2z(wJ+{8i(6=QUbN5U?_Ioz^Da7~!nK3l8HrRIkzQ0=O@E|xi2DKMm#=$Z$ zKterGa&Iv~AC<2zIv0F!W<1ZpYSWKc_V;da;Ozra-DVqf*Kv;9+yg{6B}8Y}c6X-j zo^)+y73|kJ=0cRvL%x?;?1&B%`J5nxw4Wjc_sncs9|*K$HNQnwI*k|iys#bVLi}Mc zJtg^;wDcgqFRFwhc>769qR#BaJz~+S8=u0V0CEj`@yZ|Qn7Hp#Ozyoid{$%{DPuzZ z;XV1Z;*8N(io6tp8K7*tKOPZx9!V0I*L1 ztwU?TMSp=Bw%w5p&%6vCFeC0dMmj9_P5}MFrstNKo9I@Yo`u9vd$?3u%PA0!9|VWwb~#ahTVgr zj*bqGH%_xMRfEBZNg27pGr|o5nIBtw!^8?lt`#4Cy0KP-O{vf@&&5+nYa$42E59v7oD+2smd!L&5_}E#r=ft#JVrjye~k&eF{9 z$%RWb|7?S&6t{C&KZ=|5|DL)L@QbtpKABAGh%PUmppF3{_P>HQ@R)SXBWeK+2lhHY_MS(d@Y<6@8w#>fBBjK z@a{nNyI=aT2L~)S)SR)JrqzC$et-T#E@YSV4T!{dMS4+9Z5Rk_B}Q>%f(EYUZ5TOM zLBc=qU_35hvd15U*9VfE*X2bj*c=c`s+K+{GHMODaI?2J3nFqPkqp zSu$dFio(ZK5fQLdrQf49uA+x|>;aJ+pw^aw)w3r<(=(hy``% z3hIqBO8z|1w9S<38^+q3#UGc*^2Q^3r6crgpD#_EH-tcg1c0LdvobS(M0JYEAr0CZ zE0(WJXBi*|dzhfsLCD~=A z(>WlQjq}3S1f!q*M5g>DhN-RD{A^9aN^-od_|KMVJN6t?U*@Pqw93Uc{Xn^`MYOg> ztgXfA=_?j~K#Oa{v(%EmXdMfitVv5*_0Pai9S-!8&68mt;()ca;)B#`B zzxFL&L`y)Ja7cxJXAY_=X8qGG|sp@8+a%96EH9cAW(? zQU0|Tx1{h3xc-;lw0a3DzBaa8tu<_!o=YR`m0x>u?8oG zdZ@}CDVpVKq7zXjt=Mi%p2#*P2fc@Fqb0p^d?8FiBqAxWCnV>NO@?^ePTRAM=S?MO z02bzY@KZ`HQx;2&;Bp-oSTWrEB>t;Fm;?6?i|+>csXC#(vV0iMl2b^h+E*@wkKynz z@6o4gPDp2%%q*SI&}Oa=O1 zX}ZZx_@xnM7z+1kq_O!do7ZF6lOKBLL02n3TeBKr;TMPB@7CXus&=TbaGWSEPITrf zuQ~|9C~Je1jfwFpfOUqrD+xr&JZtshAHB;R+lSM7Y>?93DS!9b{zPbl%AXUPUYj&U z@GD^wV_Rg!=&lr4!c&5JTOdcpw)WTn$Mc-czJP+9Pu60d=zMr4#X@kU?fTMd)8dY zq3(j4mLLvM?WXgb{&5GChb^H}!LZ`YSa5^DuQ=g9 z7!ftR_|~z<nNc;O9GJo7ROJ_UQki7Z9TS6-<3K_K4d^)>?anTsvmO0<9I5R)yJ$9-YdX-wC zO54o+nqeJ*wPjt<^f7TFX1hB8J#u6i!*g`YBh`1h3J_l&0f}GTA&X~}?No>ffw@BN_z4PKA>h6lR#;1LSQm8&X{)gOS=#x7VCot%i!c6c{ryR$p zX8_@dzZ=zzgLLz%rQltseDt4TQy~xD0yGvnB1v{Fy>l=|9#9B=ou)8k?I`6VEx#Z7 zux)0x8m-B88}Dmd(Ru+;hKs36>B#uafg%B0s5Xk2+5q2sGhkr`LP8Kuaw1M(N&S+%PS)nuyS=XnC&-F=M(RbrNoYlZ?LFZBC<^X*`US%bu9 z(2Lv@oHzH5^#ZBi?$?;vIcceoyI$+g!!4@RlPuFj1(>I-P*%@pJ@=BwPWy?I4^?y}XfyPSZuyf^p( z6VqB*ZaUzN8Zl^=?SU69tF`A449}p znRWITn=%W((GH=vo&{s;{~h#z@}=K4q?N!1r+)q}{( zwJsF>6O~e3!hRxJJ*V2KL)#41Y+jDlN4gr+n#NI0HE=%F3Jie4)xk1YJ);JWqy*sl z{FRbg-`;Mrw+lXee>RyT?p%{Q^#&lz2f&PjX0NH9A)(%!$JWzA>LOkpgOBl$();= zYb5r|zoRG2Uf(w3ymo1R|GVqSfDtoW9gKX@T&lmBORscC8~4p zx0k3}4;jt87^c#pTXUPLd1&{+szV{ntO}vD%-llB_>Y;L?0Ajd%hnVePBYFr_)jl%40U_QRX!A>0bu38mPm(WfK2Cq#=EM~Yg=+=M=?^d87CLx*J41IjoOuy`<<11(owzbv0ePGWCq2{VfJNutNxEJD_A)MB{lSIla+~IzA6=g zDX7~rwUUm_Q#XWMphed0Y9tRYQ$kKwK~Z-W83&JD={l#U)9#x(cb&xaOK1ZsEKy7P zyRtWl7R>)X{0fyfc4{Jw#|#1J6ZMg+a3G5@`M0>GqYJev&x&c;kU9OA?c4?5v70k& z20uro7RXEsY+hz8J<;%k(QJv`iOxgn>3}N^SG@*u>2^m(cL)Q3tk)N3RWAi+gR?T4 zS<5vZC7DkRO`QHRIj}aoAB$^L{V+} zgShg*p2&#TaRj<}AHo^iPtLm`MijMVsQJSR_!o zw5DN|9$s74n$+6QA7{D4K)huYTTn11Oz{dl_4R)iv=+H-3E^KK2JOq{eEv+12&BS| zxX2$%z+$JvGP2}+t-ZlW=A5!9XQH3Tto(I`^}Q_mifJkDjhe|_Wt70{d{(TIhVP-n zt26@f_{-9kYD?_7t3*DPUe8?US6y9QD`8+=FLtCw7|XRX9hVli@8cH6t?NH~0e;2! zuNADOLO28TUXsj#PQ8mqjy zEPlhy`R^PCun+g2>ZKU(qITM4C5jS)`7@A?p2U|HZ+6uv;)uDu5yiPms($lLx+f6J zL@&SJxtjH7?hh0;h2-kyz0Ml#zH-6?CKkG2>2@o8AFgH1eIg|Ty z{^Pe_=n)o3Z-D~v#sA}336K)i1uV4!XNUUKW=vOz+9g%dFe) zvgTdWNJt4`LhQL? z-S7MiYg3B~Bm+2%N7h;X1AFm9Xu1aG(fF1mXqsg7WYsPjiPkPk0YDW|G92?>4xKhH zWmZYsD?O99M9VFSsU2p@y3Xz(bwu+wiA3gjuj9yVR+%bWCfGKVGJ1c{9!1ilh0n z-6MY^cu}}q&y0I&iJ489O;Hk`-(1^8SyNXx(93!Sv%&;O{b!dPt$Z66fbNmUtA8OT zo(b(6gtaX<2tg8eDXE)v5J$}<7M~*wx=Fg{ z@<@q0oR7H?)d<$Nt!P;U!?&ePQBR&dC0Cr0;&f5_M0Il)!JFO1A+-a4bM)I+iTcNU zR!Yx(Ee4ul-VNR^4aMk%fao2TL(<*|c8}M8p{^937Lb>j-V}BJR57Dy0J;TYFv7Un zQi0c(k1pHjjPCq5SH#*XXqXb=FVrb-JUhKrl${Ug5J$3(#dpET>ol3;Y{C9L42iN7 z*+U%j5c1kME!X!DLcO#a1~z5qZ?!zJsf3%%QCCb&{5yIv03f1tUUW=4LK~gc@}J0( zmVnpKh@OtDKk<(ggh|4KghhNl`cTNgV8nQnk?e<1aobKZQ_iqB=t8`3l|OYtR=PgH zczR^pR1v>UJ`F$ZF(>)L^Bg4Tz-T+dSz$xVk=3O0UZdp`7^hrH-1d$&44v4DiY2w< zc{%iM-MEK?adBg z2`lY)>ttGq*rEX&QcPp&$%)ne-=6ClZQgC=#DdpT(5H*`T6u8hZ=%Y5o|?o{F~J5g z=3V_7W?;*73>^!wI6z=63a#S+R`n<(p+Sil+F? z14&WNmg}ck@>VW?Hhxr8O0>Rg@S#!CPWl24U)f2uS056p=#Z%=wx=C zI{Nm1U{(`p5MaR*{IB1n_37J)A&qmYVztik@`+u_eFDlO#22$K#99$Nk6Ku2Vn>cs zye55F+VRZ{wo5vNv9kQ=D%zV_?wa^-Uim9s5GN2a4O#9fq4rtl+tcW9*bqPYDIA3s zO{91cakN;smeL1Wd;G+=?EP`dyGiilH;y4=udHW)0A`3)+#gQ`D#CM*8vQ%@zkJA= z80dyrQCyB*;*u^mGGwx7Dz8cX0DtO)0O&nN3tl3HlrT2?NP2aJ`$A1s z><>6@PYs0%*Yhu9<9a&T#J6-b`5JXKw9F*Rv+hwPJEJm6HJ{J0e!b-L-VR*PwmR6| zmBwoeFny?dfKk)^aSXTcj3y0b}9{`BeX9JP@2%ZFW|iu*`%MCLvV1zq*y?SjxU z1}a7j<+-KE82DR!Y}QYr^47sFZ#H?ElC2k(>fBw^L!{#}sSd_bc>?)RU{+iI1ELlL zaEGNKMZWk=X00)S3^TY(KSzr~HP--6#Uir&i_HUQt&65^{$gy@W;mGMG`wcn{zB{7 zp|Gf4kl0n{{Kd#oT5!EGKYN9fCYL>pYytiAwuVCG>Q62+I-|s2*WTUh$VQIfbQU_$ zT#kr|6`%dNW)+8 zOLFRFQdE-Uis4YX;w_e8WikC~IGcZ29*PoZTYw~L`MNaXRibvShJA)6pPKV+dTy9A zJ$(#)owMG3NKeEa?C$m!0tJ2PffdB>f1I8C6E^j>_`Ha1YT_4(MuXO1y zhy6sLF>`xjax{}A`t;eVL*BB~M+3ietqZ4=qED*m#QwFd%tU7iedb96mN7YuYnS#N zp(xjJWug^~Fv-P5Cm78H7hn@1hjupg4^Z-=BM1PV26yuRflBnCmKL*}y@Pky%6+*6 z>OEq4`HM-g_{#3|uH{Nw&V)$#A?JQ&4u*0`q+Azx!M`&k>2t`qjeW6ZMuR9?4qiqV zQvRgYe;HJ2n2k;>1fu83HKftQWuYzopgFde9G}_PY|tx|7I+dCL@j!}v_vfg;Jwa9 z2Aqrh=d`qFI9M`UJs16r3Ghw>3~v2aQ@h*Zl-LoU?mK>nR>9IoXQ_rDOKI697kw`- zx)c%rO=zCKif{?FT4H4@1w_Wg)A6qT>+1td;7W1mjh*vBrivvY55pHi3KX_qHpR`1 zChA7__SZkG<4k@>n2C#tskexe3!#Ncw_U<~EB}j}r?PNJN}{d8`prh|WpnE4Nag|D zAql~6d=C32t+2+OEj+ifCt?>3R)r$oD=KS=+SBCr=GNEO+8?nuUJjG4aD*#hWG6Yj zn5RXylQx+NN?coiRi$t6Q7wTU7yp5JN)7XJ>;B0EGNf3P}IMily1%Gt4j@M>U4 z4{^gBI&XPXTnDk!)@vja_FX>V9sr%}9x>DnVo*N_X{!z_7-(v}khi-wHtFf{^&aVxNf0MHJw4+N?D2US8@ggp`4J?Vy9cO+?2F;#i zTBk=d_9i9AmfF4sL`*Qt4Yosi>SMYc^)VTKE#-L@{pfzH4`7_#8%47OSxJJ|%(`xq z9V$At8dGfp);-swX9x!AQuT8qMX<6mE}#45nd>xik0zr3XhoQ`%ddQzxnq;Ka%CKwq4w>~!QHV+)nX1xs?VQ0QSMQ*zFZH_TNxatn9v`iGQef489$${r* zO`IFVt{cqq=IBc(SI75G0)KVZOCMhG7FH;me)_M9uqQdCUZ6;hT6g%vQHB$h@&;8- zUDfp~Im*w6Y%0UwtOnjE27UWQbhsq+ZGJaqYG@gv{?BevQO~bMd;p!%0EE71niAaV zo*!&Bp5vD-DaKKSNGwd%f;7vyzNghr7x}ZQr%(FQZK*kUtKQXL-u7~GJx@7~Z8%|y z?8>EnMsO2Vs~W!+9=ZSXpt-1sGCTZrd>IMG$}Xtf$|}$2i=44BW;BA=CLiE`iH-`~ zOT0|-`hS>(F`kXRUE%;XHou4+e<5f(4EK8qr#tu=uVbYou~KdijCdpl%`BI~KfH{5OYI*7Ly<&#Z&XC> zQ}e^4=f4V@i$+pjVqPJ{tyL=A(Ilns+KGBzmPWUc@(S|9UvU0X@Bg2g)255Ip8JDF zU9YeIw~<&ur7{4MB*h*+TFCedRd-ClNb<Y$p6B|EKMQSq*!M5(^yuoiPZ|FtU1ljLGTAKC*h~)#ZgHMNd2yHm?V}zu6H@^ir|@TvVaCsbC{70-*chA9Y2`7UD)O^?Fzr-5FRswJI(k@9 zaa@E{H@uBne7<$qyjb|E6)$n~>OIL()cwRd0hb1=2Q^xdrpb>bLiXFlQ2RGDhWIm& z?T=n4xURll2f)S>v`P=-deO@7GeDmD!z&Zh6C5GDXjoV{{o6B2ysykYoBnYhTvew6 z-oG0F&Hhc4ppO_q_e~OPoSexwXPbT18v`$fc5C=cnkd(o%jyI~XpJ~3hOte5^5%@( z?-e(&TEZ_70oVn$@7#N znoQQanYNa5G6Q?#cE+OfBDO(dV%+|VlH-$$Or}%^KK53g26c^h0%)|@fCZRF9QOa_ zza-LiMQmql-$ar{&7TDdq98(m;tviDB{lhx0-duD7fPFlJo+G^juL7vci&(rHuH$GH@(61SjK%LTuUqIh;R8kwaD2@ps7R91 z8uiokRGY;#tT%Y?^KU~APj9HEXk|Pl`ABfxXe?x93^{D@2Ow(s8AHb%q!`h|py4+} zya1;cSxEjw*?dfU!!g<3YhKirQu@c?&iUEz_HoGsfzmjj4w27QU;vBI`PG2Pc`l_7 z;xU@^k^uMrR_!z?;QecwyRT9Yn^Qmj6x8|?d@S!euGvawY$P2Y7SH{=+|5{R0q-zZX=t1pYh*&sBW2G}##o>?Rzy?5;+jsrf zHJBY_ju2(3How0C+C$Jv1!ydgX{x;{vH;1EuY3sC+bY{6$cdHiYbd|AH8$7@wuS75 zU`C@p9UM6+xkwk7G&lvFo&W4{X@1OHr5~)(s6mgDI4qx75r#nEndtFzn%KYmG--4~ zQ(80>pp1=H)br{{vTRwLJYhugneN&wECA9|6=Hx z1S6m?SwwfBO2&zMbm%*|e*8B+NHzoY)t#t90HiFWWcQ)OM7PFy*Nbd7N%yD(kFrPR z(?U#d6*1PY$<4}JKOeTM{8hf?AU^aEn7@nU9q;Uag*pd~k>8U<21MvIlbD4x%@kCb zl;Qg$s}@%`UDGiT{_qM7Az6(&$K0Pv3jcGETY3oerTMbd)4v}4cRumQpB89MBWNat z1)*2ox>L>nefoF8_|MmO(#6wUS>yg^iUpcAIxxCQQ!r0g!zhA+z=Hz|`?7DlSIMMS z^6#(C#==>0wSU+fzdyeSA33y@Mj@Y8wA}lDsIz_|0p!K@#Q>ES((Hi{!YC<4A7Z~^z(1w9G4y{K-SVB!H zRsFjv55L5bBa+jpivNPk1dL<>(4>$Ky)c#t+{68T@jE7u+kZ8jG=tuJW&e{3(4j(j}0Hcx!!h|S~_5avQ`zwep+5dh=nDiqC$kc6K4`4HN7+@sfK#~6E|KKJ2 zrHyrWy8N~^P+C2dNlhMDL*|aiC%JJWO*ycu9k_C>7yK*3s9hIc-b5h!A)k z+te|A7ZbTUwDRQcvZLlN89okxPbLDd5Z(7Cenm$RE-SF1p+Q^MkhMuY&|)i45IZiq z_j)ER+EP8)P!NhDj>)FhFymW4>=nrw)T8`leO)4s@lx(G<%+SN1Er1ieJ@fp6K znW>Kk)@ea{)+1OQ1ALg_Ta|&k@`Eo)IAM^LBNe?V)qgQ_d~%7? zKl6YeXW>7_bi@K*A}`QbUCTe7zXs4&`rWuRyt(r*YWAr~PEA$C>1!phtylg%Ktk9y$~^>vC+3=qXdVeI$+h zz*5d6!DsYDK*f6RA+E3NN|K%9@j?8m_Ena*etDxMwecQLf5FvK0--NVS-thU@D$X} zLByU)%nHFITpn?t%oA)_dl;bo-m%40rGE>!)|A#2Wc9IaMvP~AZ$`c4qPi)3Bw{*DaL*OJ_>@n;T>ox1+fHmfhyP%Ybfon?FDda!0zJ)`W3GfBM$q z{0{9U1Ej~n^@jlv1S6#9L&U3or6#T$*?st*XEGBJ%B^wZqE*f|23#zbr9=Z(k(z*& zX6u^;`+xQV?4=dde%Ci=)Wem!j<=t!Hi~-ps>tD|7P{4X#ryAXajXdW#l$c=I*SA! z3-*blUJmSheWm5U+PGaug_1Py*eZw3d=v0ilGIOL5;;);uqy<7P-@c17Gn#?X~EaRqc>nVilIz^mI93x*Z^7KNpD`8w z#Je^VvZPKP;N8^q%N`Kd*G+ECAIk7Y0N4FN=YnKZWQhs6GPcFdw0GICFO*&@;s&LY z8OZO}-+`gH+EvysD04S_p*66zGne(4)QqZL4&Ip8)Yc1kRbXaM|Me|voCx;-8MV3q6`62~XZxu;G;HC2z+TNx4PQR<^9e;V zqf6i;X^*%l1Kqx{fWEo7jU<{a`xhOg-_u%91C00+9{(!}^FPV?^hq|$YZcw7>iOHj z4AF@)eFfG>1|04mNJHNuWm`vva?u=KF^Ue1l|MIoYd>47XXbyQS6opMJ}r&2@Ua5h zdm(UgFPz#(X>;%c=Bat9zwdJuf0xR{0UGY@F9DB z6-vH}cS6R_=8e|H`%4djoJA(IOiWDd2F^XBnGW?q-15O9o2%gpm`rQ5>rb9M(U#hC zFlzBD*k3$r6ciM!KQS%9f2)vzO6`T`!=;-FYYSb&!fW@ty>RTpGD8roKGtb+`;a`6 z#nlr_onqA!+jq>1MVN3U)8mP3ZhQ#VrG_>vCwr?JSagBk#|khrTQ)5v$!}HJgb}Uk zRG&O9HmrX-wb-I+c6|h9EK|d-+MH;#G{1HdSLHmpVehUF=xIKk*#a9pDm7$a`nvg) zoT6tfhBCn3kGm~O9Ks&79V#$^QV;l5b`-)W2+x=MYXt7-huYEvw6{(-0O8N>ji zB6M}UI!(R!HfIaCJSNdZv$k40ng8YWAK6!!8EB}U0BYjX6E6FmL7(5XeOCLp&Omb$ z(Ri2CHoj;c$zf!NV@p#c6oG+G_<_SK&@6?6?qkWrg0H!*38U-QaLS7rskW4>&Cf5( zJZm~n;1{nUCb%PgTu*Lvs!89~dW>GPStYz)JXb$Tp5ve7<;)|c-?sH5u+r<~`Od*X z%H`!{8iz!Qx$<1g!((r}u*fdeMCPCK@IuctVB zje?1HD9Fq5v$Te%OrxVEcpT$rsbwi$uN_mS z(%Ep9Cilq;hYIOH$?Hf-lW`!@-Bbx`nb{rY0vd zQL2y+l`8K`m+2RWu*c_|Y{l&I%Y0!1ARdi}xz>cq`6HR9Kp!)ruJh;)IvEulEWoR! zfG2h%Kfbd>lq6_&QU6{C2Pe30<`kllQ|$Pw)t3H@w%{@U=5)p?j*X2Oe=;S2DI9{L zqDy7T81!?)Jzk-i$(^xejlm&J?NllC{=>Y|B>WXfBE8f zH=*=&n>Ilgg98)2T;?yRUz2+)P2LqTfc&J5NrBr?DNH_WcJ@tWuw(WalGF3g7nzv3 zb<0&c9tU$wUoCZ={GF2bqy5==)tRf4?HJxsW0d!%=-?1aGTF$pv2ne1ASP$6BvuII zP{w@38Q((wfI(qco*w#7-Mao$)UpvMMKzZUuG z1&aQT5VF4x)D0VOx zv?o77FvNztJQ!A3(&TQH+`W4@-)8Y99SaW$N?@ubK%~5N!c60j*lUdouj9R04c`*} zVMg%;K^J?|0}~n`uCvXd39-i85-hyXXzLV?Em|}|tj==7q2VC-`w;YOr3?g&_^}-c zz17^3=t}aw-+lA*zRE@VHtKa-t2oS7>rn?>TP`NHx$G7;=6DLRA^F=N^eP`X|3o>1iRM*>iIcn&FW549cJy1ek zC8Vknm+D)sM>l}B!+)E1bksP+ckD!3_ghQ{t^L*}A8ydzBh{`?#M=JrZ^-tyB)U-& zwFMfRkNob9*w{WI&L-HktzWNt1@HW6<|3={8pOi`?2!ivUfgTXl*$9oqnLw%zc%T$Cj~n~&VEBRw z-|`zwJ-+p__VG@)B*RS7s|0&H>$4n5aV8_p@kkF9>#gC00VkTHy(2{cAD+tNL0YYf z!Ym&QU#QHu=5mre|6>A1g{lz_XiYXzOe37a2P`YDi~@Uj#T=Xc}BK zPz5a!bjo2<1Z6dzs_(xXj2|EWz^f^UcocBJf;h82EPj-z_EGq|^B%i+lb9}FI8d2G z$1!fA1XXb#zXFKo-pvRxJU7*J*hUk%;E-KFcF-y+ZYh!h8u283BMgE{-8U@bDcoz= ze>y|MB6ZISIu;}Ua?-$9=1!7dcu|ezR>L9ngh`-1H;CAvjA4=8!E1Sw^V#Rq5t;zG zstgrja=>9Af<-r{FgSqH&)~BaV8-u=;q;mZMoqtE!0Ip-;BG$}V?{wh^?vxXs#r^H z=>RH^0=(OT95)yu6_l1+Q~q2X7AuG`MVlufD=e z4q@vgl^f5)cGG5tFA#MA$3tBv^|;Z*Rle)(nCtscgZ1&9ywS1e0LJGwBmeZ<)`-AI zNW2s;$GZP%ucR@M>f@lfs5C?bMvDClQf}k8r&0tu3T71*B^_Gs*yC6PbEuv-x$Ow1 z4@^d!TwNHT%WzkaWZWvl$*WHi1SGGJ@QgxT6mpLOPMCJc_dK)?YhLd1kW(KvUzz15 z1V@kHb10V5ncS@=gj@)@(;lgfN9o-M#9O0$8F>4hKLly`hxgvu=E#I3Jl0tnCi2#u zb58#^ub7BeTk}v=82_48Z9pQP)>nn#Cci!&yRgn8yPcy-*Ufspr-GZ`) zCv#$RKUw*rdvBk*k!80Vq8n($?I}e_zJ9@M8HuZ;Y z<4JutmB`ybs~4szs>Cv!4NO62a~PTFc-EEJC%Ct_K2;Uqr%@PD)>9cSi?vmx{siDG zO-Kw&#ynrATak%j#>)caP8iPPayuC})iy&4M!s8!PF3dRM+E{XWAB2jD0Je2 zsCWf`W{T1~!XOm4I94-cOm%t;Mg6Iuj&Bw_D&E^)&4Dr%SlyeoPF`|))JkV~-P)ep zm4f=2@tdl8{AgAK5b134Asf7vu|Q0NMf%rx=M~Rq$-Tly*M2z0w9Qx$(ef>SyF-sY zC~CSKYLz#8$*{KIIC~MgaMfp?47``ZV_|-fY|~ptAAC(6kZLqFKgDUv<=#ev@~vHp z)H>_}jB;N#&>S-hEA>!D>t0I=*wPY>AI1 zMiV!2W_g-t%jwZQTm0&7x+*OfA~_(o1kCu}A=gDV3PRrUyh~-a+8s0ET!Bt>YSLY- zQSLKKDTSuKYt^&7z9gsE;HE;=68*BoH}kdPz$j?ji=4tFMFQ1oaCy{irhMnU7#Yxr zZf6ri>W=Zr>YV#*DZf#jM`mfySQv*h2B4YP4J6@~XAC8kAn?k7Jnob!LbRlz+DHgv zuvMNqs9WYP(Jvow$PfH#+PS!_bvfOnmd@#sG7Qd zzN6!E@&j4uJ#SHVHbZc2j!TRE(l@=SQu9KE6{96`Y%-!W);4+}}K>0*6N7O{JG z{!lLHqwn*sXOzYc0lE7=mj>(m;=Tos(q1I88IP?bJOV=0yU;!(l2SL9BomW1~J)dm*go z484Jgq&9p&m+|pA_DK?+V3y6@D9Jix&G+Sk!P4Jvq6#NJaAxN}&a9H{iKK7Qn} zn)FA}U*vF$HhEw~oHzjR0tbIMduCE)?mCP(SNm5BQe0$tZxXVHh-lIjxYcic5$%JG zF@$f7wug|LIHlFg@B}pBx9xRHDBKoa$+GG9HuzMW0;jrC3~Jd>az}caes)O9$SJZf zVpJvGiCjYO-cYE6V<)_y{*o`CbxYcEs9Q;C36KekwN2fh19{XJ7<}Qx5tuTL$ik^m zDrbdk>Ui+;{wo%}RV|OW0H`M_n0ELTP7}_e-|YHpXJt1`X+!lz z^(HBItU#vM!hJok4R9bTVhq>HOa>n|3p2zzSh)2BuJ>KF0D0n3$R?|b5i!nP*2Yg{ z3|dg#X(45_%dYIs=c~a?y8$%2BUctrUk3J0yoL}3pE#?J7szH*9@F;1J}+uCCQ7i76{W&fD~2a8maySB-IwDY6KXG8jYhgqHan{3wNInXIZou zBR6-M3=Wl@lG_sVSJu#FXe5x#ZVSP|CAU&rVYo&r(M73=8Csq2cd1IIA=kq73KOI8 z>|D>j;ayDG@O8$cpMvbZa9pyiq&NW{u%s*KwuM9lk@&?wS>;sGeWp1qW-xv%B-Doq zg7WEaXuK9hkDti=jCG%LICU`pf|>sKtoOTa-Gx%?&uDq(u{Xds)7onfv+YCagLj7Wy3ACvT>oKx`odtOQzCfz7p1T^f z?QQo7ONKaqXS46$#Wtwy8Eg~*py7?t(aL_No4C~{ae!52za2}N^qpu*FJ;|FeI>p9 zlOQ#8x366MM&e%Jl|Tgi`L=ui|9oY z&{-an?g9jN3B0nT-uV>Q7@xaNbL4K|+PwcT2Tt$|ICqc6KEp*MjN!^~CC|E_5mDb9 z1GJH1lUPE$ZaBc4aHfO z->!Gh3Xk$EgQ4D}h~$|nG7OFV6GJ{w;J%P~wYQJ2@#S$k<4(#H13zbTRTeWaE8TWklD@NUKVa_S1T*9G4o^7Eg7^ zH1va#M#v+7YmzT;Icl%jQu#NFP-c2K+e{(QNJj+kL4k0luqD54cV_ z>i053z#^uFW<;LvKdalNbcwsmD{nTyv_#1Suf?@st_xxW4HT`ietjIeiEnN~Gg z|4dSxCTQDoz*uvIC1=*}a>$@rJwwe^uPPD)5s*44x_8}~*O~Ao%D_z zcKu&$086cT^l<~N89#;v84E9c;qo&9O2y|3Xg{>nE$PYym)~--*KebtjB=XJxrTs~d0AbkhlYNSd+coWwuugiTXNJlQvW5z$L$4f?AZ%DF z&?@>&^ggT1#~IhsJOJhxjW!A@VI^h>eD;+w87u47Km zyP(rk&lgxdt1;Hw`eqRi4<&VrY}t2L=I<3-j>VnAc?^K+4Q7ukpz={q_Ud|{%5P?u zntrOq*-OhPX2u?>Yb$F3bmw$d@fn(5R6SH5-I=FEHpwzgey}jrG-Tv>?2!5jb_Gge zX}JzZ^Dz{)wRh_py(ad;6{$6HC8HGZP8ao!-S^rz`XFuE!VzHKR4B#bG`Nyg0Yk>ofwxa`x7*Fu+19>QDd7 z!q8hepRfl;PAub&n=r_G z73p%vGte5hgEXEjLG81-oK;9S9<8W+y<}IQ`Oh~uQ7MgEX6~vMaTGZeJvmmgA6%Z8 zC|_!1ducH2;uxQ}!_=EJs1WBa&AcrKWW_gb3b^z=0F7)se|(n@KhvbW-ga zX1?%-BW$$dk}`qWFd-XrVOwv7*NUzWluco`mrrO6AdL&G=2tr>vXBTwus^a0X089S zS2nz8kEcd19ic3^!Cf2vvJPg{J=Wc9mDEF!@?_S;8GKF> zpxScW1Lk=*+_3JKGDq8cJBqz74)#r2(tyJ2o4ixkPbg^8xzg)d+A8Vj3= z999{Rb3U=ZeZgT+t_$ot+jezPTJOM_vZ4`B5}?chaL+RCFbZr9XK9^kJe2j0V6HK)Shr8oR$htPXaV8ttqVJ3WqsqZz8)qB^ za5h~80Fu}LbX_`w7&$}RIL4hDsJqdS?2(ps2)3Rd)PCRS8tg2qmq!;b%=@%wGcb&roGF%Oud6n! z;J7$SF|KVMQ#Ez~dYFk==0_s%yH$nhzjxfUr6m2>O$f2cAvs%!v79h+u*y<0CA!J z?(%}4GU@N{&(F_iB#p@f`O%IwIzcn2FM1+wqp`p>KXYjA4&rD)+*cMLFzcW)S2r6H zG3KLQJpI&Wx*u|b{`--U<);@l7j~MES|ozm5;`9Hfrn!ukuQ!LU-S|VZHUNH3sm3t z6(_M&g;V0sA$ojAJ3NdoA0g@rLn^Dvl`)v{_5sA86%+LMOq+W4HD4`OnBmxv^Kg3U zVnkHLUV4anS%5yl&eG(N4nu-uu8vrCte7u-1@Lk;zA)VG_3Zl747s`ENbqQ?9wyM(u>evg54!2??ZfG3zhvNX1 zh9nE}+pelFonbWD=VW2|XQ*aL)36@!`>9)UxIBAF>{V%PcO21w=AvV2;A(%p;w37d zt+cJt1obDivG7uQo^x_B6T0SoEMVSQ70_DBaZ$xjq#$nx5_I~RDZyF+9mUI-SYt)}l9VAs2W^A4nZVa|dHlAi5N?zQ~{6201+59z&7oPT;w}I<{5N7F| z>T2ysBhGp=-k0TqkA+O9CSTOCh*&CLVN~Y&3L{>&0|TeBgjR9ZQ>?A&umCaG7o*|% zlNUW}h^o%aVuX=+#wT)!(hSka5AfGpcqUw}6wmS_713RmrLX}G$XSP{<)pp81`QWYm1r)p*Wb>Zn8I!GfUg&$&1XLBzCE8tb~I&&uDvSCVGhNFJftf zHgPNI64oy|tE^lov!OvPh7hR>Zlx+aV@;(+;4Nuj&j9POb{x(()dFMPkxpNq(BqEv zx$jaDdQ$4Hqg;TN<(!k#7;#PEwAY#DkJfv6qw!-zZXJ`$cSwD|d^cyFHZy`<-Uyh~RPxTF}IW8-w;N2mTV{YuHF)^_}|7a`@kAF=+z7EyL zOv9OJH8p~Q1B>%oI3qF%V=2MaWspQdXRt_tQF8{j^nqdfX265&KKfN>e?zneWbkhG z3o3fPu<&3u$o$MEhxY0vMNf}QK6bUzVRx|q(8MHDl~kXg>6OsUFdCYeHE#<&Qsr4^ zs{6|)Ci^Kz{MVGbuI|m>DY$2yiZ>s>?Uc`Jm%LgixqBcx$nM5vZjA6f9rW#IM~W=e zT8FfF<`CZej!j? z(z>+PyzyOz0sVBO=>%v3g=wdAXUb&+OO@V!zY?ZGFbIk?$8QQI;jU8HZ+QMeJd0nf zmU4T-qgVyywo!XnN7?p+1TZd)3)f#>r5|4$;jD{@ief9x%F1YHtPWBRdo>=YcNahk zbTdZiFC;hK(6$(v_KI#@MhMtP&EB=TJ2y>JLAj{@y`9eK?AKYbkB-A{I^j)1{05p6 zCVck zX3bFmPK9MHtVoVd;}ZPDJ#~3=vA0(^sD(s2sOb2!yR6q$Reonsd*?|ux2LSq(hfe} zM%2#_Sx6x>hi!VZ^4j0wdmLt)?+}clb#O5(HJ$DT=z_*}A5|pF(QQ6!bgQYe@k3lqe(FGQ5zHAL8K8(t(5x};<-yd0LPT%1#_=>$!O8k% zbu*0O2pZpb&tuZ8h4D%RH?_~IV+w#2w*SU4rLHxSfneE3OYGUl%I9%h$h6Q8v2TVy zZK#84Ca;ac!+}^llJWjr*nY~8D$d_qlqg8y^5jBW(yK53o@>WKXq@5D(lu-2QEY1% zKUn;Hv2bY}Q$ZVN9ilj53#_7lMK8L+F5(`zyBo)3dYogLTMr*{Ss!PaL)Sf zv)vxPBnv*xTn{v4<;^seDmYiIL-tfpnt_7j`CjEX5wppS_$an$l=?0=U-c;Mwg#B#+2tAh=0a z?_tYjU2l>Q^|96(H=QlQxLL05mD25ol^s399at|K%*;UO1j1?+1MbyCp}SZ4CqKw` z!YmQrU8_LzZl83rG;?JcNqIl@Dh^+vYqt_CWZ%B>NT*4Y^;OD*o&`Uw*%70$^A=^Ojt0YW*(Cu=CQ9EL zglKneL_X zT%dcG%GvH5+^+KY9OWo{1yDwtR03;2o0(pokFy9l+W7)DHs;WOSfoB0D~TLc&s-bN zkFFnoO0$}emoLZ$LYwP3+v-RTkvv#bIg~tEJUJF{*;16^P@QrNAqjm~k;4r|&}1y} zMx#s%Z}V7?a@s}(vuxoWJ;`ZRe?jR=T4+3D+3o4g2TCN{fSR5prx|7NfL-ijT_R71gsXN;4F&UD+&k&hB=*Fe$ zgiT5S;f-A#wx9h?FH*x%LY%*LU@de3l=l&i2)>%U;BwQOeJT5r$B^-R_MM&)cuS6a zJC67sL#mJc=!SZo_)#BT#2#5`RQB8*!@lKmTp7VkZBW5U34dad!iqs~CjCX_43ZC1 ztQr#^jn7DiB+1wV_{n41_!Yly%(jKQHwa5!otIb^B9HkQUtK|yGQ19GHhv`36_7ZK zcs0?~37FW@pZ1-f`4`eGq+Hq^{Gax|Gpwm@>lP3x3erS+kt)(bdY3L8lny}wLFv5{ zniMIa7paO$lhCAuj`R*nm0m*+ErdWqZuFe<-Sa)q{dfPq{7QD%JK1y3wbqjBJ=e5Rc16BM zBC)yZj-yN4#_S`IH$&S~30QXepu_>_8q=+Ex>f=_Vm(8x!xxcL4vG?CmTeV*W#E>Y5bMSvzgJtBgH}Q{N zF#V@bv?-i?HPjFM6bhALQ=}~3yxlX!qT|OOqs(TK(D_>6ql6WwYT?97M@Rf8y_Fxh zF3L7J`(C&|!_i=gTdUXQuvK*zoV_n3?K^w}Vbim~8DuD=(<#&h@!QEp7Rkp+gH{xfWw-7@>EbVIwuf}b~+#F`o^mZaK>O0qV7(p&JWMZQs0LIaBYIQcrJ3Oi}~4wjX)434*;}D z$zepy-Of0jkgN%SJ+4w!eP{TY;JsplwWXVEm*O?q)sA|4C_SFHn1nG|#TDzGD0xem zz4|?t)aeQnV$i$d`vqWCWf%%B>n5cQKlMCOfK;I9pcb{EziUfAxRNd!U9Y= z--5RcAE$c?v|Pb*T`F@Jsyh&%f>1d9>Gv6O5ux4L@}nxLgdQr(7?MS(tSvyo|HTWs z9~1pyE!?_HAxLGc8;5+F(;%tui^hod$>O`3Q2@jm+GVmflb&-%Q*m!(0khPRBGw2q zj3ijXl+i$I>YJYlv|dw5q1GEeuPtikgmL#gy6+Wq*7p69H+w|z|BxMp@ zdew_PeJ4W^yq3Tw@4$AAb^V;c=v$yJ{HoEGH{u{zNS7NMYW|>h|J8p1%495)_t2*w zXU^he@UyueKomO1uJfXQYe#D(6LEpUsbO9{BI_n-dzJ^`!ChWWVZMEqIniVgwPN;o z@6M{=L*-+FUB}kXMvQh&FNeQ)HT`trB#*dzGCVq*vX$#M)Qec|ox~fQAlhHZ{}({k zIU0w9dE@x+#$VQW@}^*9ZBjIcIuaLLz%F3!ZR$5~iNh)vn0j;Fbz4D>UK=8J8y+s(rQEtPu5!#DA~z`DS5XoY;Q#P{O9M z2NRpT+EewQTwNPR-L6}L(j}q#kGJSUKSnl%rp3BS2H^?pC=&P3+Uz(mey%J1Zu!_` z`O_6CYtzbPRy(h4=VzuASOESq8D<5eqk9;nqo!|5B+N#OO7Th-c)@4Ed6re>8bzzKeHQ7S2pQ?q{a@OhB4zrn!Xdr71JWzz634UcD&kp zrcztTvt)`K!-X7k>^-9>GUVzn`ZHF7X-S&a74Bx=W1U;v zH7eO`I9ymN$K;5b9;$i+SEUj%oM*;4G87xBg$neUUafVyODGHJPB18W*k+7t=+80Uf$NY)M3K1d4 z?CeR5+!VP_oYsa&u_Wp*x!lZkv|)Bh>D;2YGXT0s~L!LjHWoyJjkUi{S|5gNTc@jlVnJe9* z`(SgWD;PZ&F%&83TYdNwn^AZ>OCD7fE-)tzo$AP(+(hFNsfVLK!7c21zshXN?b!ZL zBfN%6rz{R7MUBJX8Lk#5+zYBipUl|h_dE)G_=k9@s`cQ_=RnunO~1bfBk$x$xD_-D z5Z>31BN_C?%Gxz6h`zeoSzKmSF>AlHN~uuZV{ql9FrSSPE2~s zo3jT?(reyc`a1HZ0X4h5+V_z9eXSuVr~ zBDJ*ObpD?1y#4oiCP0TjIWte6L?lJiFLEZ3b|_cWh}rmVQD$nG1l0v^D4^)^;B8?q zFv7H9YNFF;+NJdB0u0Dvv=IJ>N)9t516CAv2%N zu5#hE4$t-*lKv6W?Q+!tuLFZym-TzVTAKJUxR5W zj^-dn73z^q1_BQIhH%cE=(Jmut;D7e_HSqZD)Nw{jGWiW=u`67I}9<k{B%$T7VY zSM@dY)1j3?t=oD$xEh3s(d^HRFA7D3?wOF2VTG3TJxt>iTIs*8p}Ruk+>t2NT6B%W z3*ApiJvDos73RVxh!`KeqW~o}x*p1o*`BHCj|O(yk4@Y%gWR>(>J#8f`Tq%n7cc*4 zx%Cw)Glc(L5z@#dL$01!4z!3B_Qa9Ia^$P{45s#a_8&IxPx|lO?tIb1tASYYE9A3o zRT(7IB%(_Mzup*XcM>q>rTaYjP&ma7X{~8nrQW;`ZYf%M#Tosqg80_;ZL@D>WnJYS z3g_K7XZWchr~%=GIPjtCR$&7vy_jSYoWV84{y6Z_`kOn+y|PQ|LZi5g9s8kjQc8o> zk8j^EC3Ls5jEIhw<{Xw47Z46u%+^~1Qw1Bnw_k0ytwIa>^CW};jd&SP2;br4t~bJK z^oGk_{2ofO$kH9(OlGHO*hxium(eb~@Rhyb$uScK*c&#`=T6Y9)GsFud#+7b&lTt^ z8s|NcN}d}7GCFq3*bk-H&izslmzE81riEpag=o)oQ-$>(duW@8Gz8O5xB}Ou@E=&- zAyKE6P!L}qw58PRK;sd}&Kt$Rblmh>S`lebG5yc|?+ydTU1(cEk7n)9+CaUb|b-|;hT=_TS zv;f(LTx2$0q;mII1uJJ6ycjYwt5{5OwIy56erYvY6Y`cXZr1K82opqaYz8I!mu)`bU z0s&7}22<-BzY5E8P%zqgJmM8!=0b$*WlbHYNs0%)%k$ro5eX|w4UN}$PQQ}#@Y@Z` z)!MARojZ=+$*R6}XlRNo+yY~86nyG%9u?&n^q;ogrT~hjTA{LYB3LHH1~m zisHY5Q1U+jeA;n?~;?G+&RPSx%+KLj5@{Wr5au6h)0{dn&D9ulLY&O_}{e$FxX= zO9Hl^WW{;RRF)JD%CA!6J42kdiaXA@YrU7gem?wV@7fF#4%qg?;7`av()H$DnLWQ$ z)iH6C1gnE6?K%c2z07*V!Tbv{bb}UAhS3!EKn$Xtja^8nsXd=$#sSd0w<@Qkk&R5xt3`ubUWDtT77*o^Tw$kBG{OZks6Iezt25`xhq|O(m zH2ji9B7}YyW#W7d>pV%`NXY@DFU-aH$-(UKKVgtJ(-aLr9 zM<-XYJzXV?;*nV|du!p{J9q4Me}17~OzK~OuiJ%re|Egcn?Fqf1*;sjGbjy{D=UJ+ zA}zOOm6Yiz{W+|al_Sq>?LBFGCKy;`mz`$78Q8`Zh$$}apdAMiOFUl^pSUeI*Z)DR zVk^N8RCVS>VcC#|_`tFnht<`{B%7 z+M)eh`(Y?t{Ed=g=Xo?~N@`BsW)0v)<5~WEOKFMnJ__06=S;)mK#b;RK=g+~eKWnx&@ZZY;kn9lm zgD?VWZ4^3g$br0Pt>B(nvqww%m=zAH#)tFrrA)g6GSQmz@D{ER>33To-mB;r!Bii_IIe?nFD8vvg?z&3^QBBy6KXzvevXcEMk zl#I{7ygfj3L%5KILt?oh{;!}<)+IP1Cbl9sUlhTDY5<|bGnGP*r-oIN7sbhsT*<8i z1=1r{Upyblcu`?I{HjMh`!@Q{WRi3W<({O{Oeuik!jh$X1|NJQ`buHEP%pz2gCqOM zxXQX%+Pyx*17FfQDQ>e0-(W_<cYRR-BL~RLczJZF3`Xn za}~d!c*f8Zi&|QB^yr6}?7Intoi(>%w}p8D-=7~{=LimcjVZ{Cmt?NKnhRxIB4no+ z;3eK0nLkrBG}$n1k+CBlI9OEW{Y-8*PZczzAJ8e^;UAqhf5t9V2csqx8cd`7`Gxo( z9!kddH0AB&wTACz=H;1pcyU#*p0RU_#df8spsf(?t_+!bt8l6F^3!=_&G_K&7KNxo z^6M}3B~0E=rnLZmyvvbKdGf6udS!h}wijaKTk>v6s%-i`l1RAXVaxmBAiQ6DYeBFRaa{){_Rd!T8rijYn?Z3)5#CVo;%V%kY8k|X( z4T><7dRw65uY76N+H?HU($dZ$ZwO!ijW?wqXAvtm#68EMQ-&T-!!So9KOH~KY9pMt zmV=gGh>@{t_m&kAj${IQkYkjG>YdF#&R|DsUC}4*{DSLLjWL|H4Tp<7sai@EpnuOH z$iV{qf#&{$&g3;+v19a`Rpq84BWX?Y{<*0sjuO3sbmnh+_g;d~&o|$1_`~Z>wrp9h zv+1eR$ql~J%S}-Ab*7O&-X0~KEac}k=9`^9H29|BBqVO54vJ+|WhX~9; zmN!hHe*j{8y0P^*SlAc=<+FU)xQM`KnE&81qR}T+ z!ckgDqdVO0b_4uLsC>7L_!A7|ON;*G`JHT)UaYkAEnhBMij72`3=iSWtjVUb`xox6 z*Q*0PHPjhnsY5Rq>~*&cvFLq__X5tX6N+%zgI>Wf^&t{};`?Kdd|b-(gaV|+Z|-49 zK;US4EHe=J&}zH% zdSlWL<&m;zEG3k~!7j_q4xEWoWGoNTp8V99xD^qyIq?!g z!mj$Y|AHbCi`fq_%!yPx&AP&a^>5wTG?WjTZi5OD-Ty&kV7gQ7Rj!g={2?r&d2*+# zM#w-S75ECie6rz=u2MSgSk>qv_pfBYP!H(tu(gk6$Wi!7(6|zaWc)y%5(3YCcydj6 zWC||LICF!mG>$a4si{&86WW@-Ge(D<`cKx>G%>s??$_L7Pn1kT`B{N8B-*b^etPdR zE^g4-h@AN)SQx+JnE~)|Z;|$2EElj~d;T~*p`w6^Lqe)!X{=t4hw~Hi30fhZ+Z#6W z{c4J_iDbv>w={qb6|J|s)eduto5eV%moX~y-)0wLWQ|xCwF7dNFOb+r1nB zXU%>KXA!XkQ5bGFPq@8ZrPL;EwjAc3ecJI68bv8o!VY0Fxz2dtTBlD*()+l` zvWW?z^Urlyv&z6)jo!bH4=0XOXuwT24hOtzCSan{+S{<1x_U-^ zOTu^R=LJdj04+Y2Vy(7``Smkq10y1uCpjXiAgyty)tHBNBqR3d$T_XC9i1gjworIU zvcB+=^Fzf}cvqy2)XC+&E6uWoSG|y}pzVtqzbDU!Z`^=pV@%7uk*4skF@w)vJzANK zJH@14r#ze1H74t?Y+d}(oU-<=?BwgfX;2JWPu{JG8brM*MP zOuzOs6VKC8nkhxq@yK0{o8JxM(}N2uNGH0z{mg}eo4osMp+6*-0rYg2Egv*JKggg( z%G`YZlg7yYVUTQ$=DhhE!*zbAV6Bn$-bp6#Txi?JEwhXbdwDtA4nUi54U+WpXNdJ` z@CABJF}%ARcVQa%m2p6Qr}pcAxB$aCiJqHF%AWN24Kx%7yY2FLjR)G4n!;Ps(c3b< z{B(Ap&G#w`DT*Dbj5|BeJr3WnDmLhaYFk>tdQw8w$yg?hh?|%qt~l?4p$l9s_gGn1 zy8OsKEtMWLq3@Bdt1CwaD*M;Z1B(diBt=LR;qMcvke29CrC=Oa&7HlS=ZzTAl5v{_ zm8^p7WZwl9%B=|3v~)|=%(}1o7QrYS(X`p0ro3*U*Hv~z*)BkoS=0Hr0ecv|c5MF> zDwEnA`fure5LP$#W;(4MJ)`e#h3U2)0c>1SsYgY~uJ`A;?G4o{2ecBhrP(7c z;!umNjQE6n6Rbe*GKIU{D$_Z2HAPW52Nk+s#oLIMy1VCRdrqId zyh2Iqj?;dg61$wdb0yMaqJvOj?_^l%WJV`FIDiASAJ00gt;+lBy7w}hLMm|wGwdPY z_mP)pzhg2^=zC}+kymGiA?Geu$P!$2s7yX(ipZ-CS(Ec#4^B%8D0jC?gifA}`G?Iz z;H8t#Y{yo6zx^ctLQNG5?_oJr!V4kO8tdBoOcwHe{aE2D?t24eg(&^810bEP@?run zE2dqr_rclB)l16C{(EPGbCACuip{3Y(a3)^+BZ7uxv9;o<)Gc2TtMqxl$!Tvq^n z`Zq$}=|k+E3KmAZCFJ^5_4U-yYEbtfP$jbX3&(?B`cfRH$6BQ5}Su|%L_IRtEF_g8|61RjRyy8Yjhg8zI>Y2IuhiUf6 zWx5etgUZ%TW;DQ_wKBvP^pS=U!v73&I(_5NDcSfaHY zB@_4yLRITAYgFrqevnh=`0oBgBGyI%j$cM`qJ1LKHQrXP>Ed}FfS}-xyl9JH3uRK{ zrjvWRX{fUh#wab6jhjT@?W~Y{H~{Z0mfJ@uvmrwtr6TyV`{e_!ksWD$Ua-N+mcpMe zd<)F=qZE^63xsxIIDNeVpR_{#oQl1t0O``nz@*CEbu+qt8KBsv!t;V?krBF9$uZ_d z_AK4@Vs#;bh3`h&Y#OU0Qg=Vw%~;B5;_mh6@Hk{$QDK@Q^qZFct)PU}>%;c4M`(V3 z__y&)$O`|rVk#hX%f3vuT~SkfJhL#7{rr7AMGa&4MY`o1Fkb;Q{krV21M16#7USm9?1L;s zR+}NXc?;|bkGQriK`{(v6C3ScoiD;e$sJ$2hhBCr6U`vf35hdhiT5ALPWS~vX9yS9S`bu5ZTZ~7ONjBR~ z6+#;h%w|dCR?izvMLfUgy15KGxj5_K;RRgk$PygCzxo^zCklRS+ozMHqK#5zXb^sS zaiW@HdgXXHB%QYA+|XY`M9!+XilUI@#01?u(boF=c9GbUvAEW#L^o0W_BQ)rAL$_* zGlfc2h)**x=?c4PVH*KTj5c9aq2!mtG1@+IjJx1c2?A@se$^aGa7@vuMxF{{v7r97 zRv2)#d+LEdAjK~avQU3l%p?`~VVL@>ZVr7NF4qi)YEpy)DwTb<#rLQ@+$U-5^)lN+ z#^JEak1UrJ8iT6C_hj3MMa!B7r_)UlE@pL83CnnU(wyKqmT*i`zRcbLCWXke&Vw$G zDGtAL64mx`^Bff~$b4sta6S#yFMI2kV6MI-{56n?AnOr=Y%6R968Eeg<+-_fQ!5j(!B24vMKJb`;rFMUU!@k`1PmyZ^@9L= z!Ewz<>-Mz41WA`gFUa!EFoz96|0qm3F15*TpPl&`$GBQXnaLPG)yD6>q(aIpY6om5 zjk+yC?~%q^=R^ZcK8wqHukG!3Ik8RE%eVNyb}yU+C^*PCvGgGBuESK9BX=n~wrBNT zjDNO1;!O5ZY(Mf1+3N{?s2GN=6LBSD#uY9R=)C-?xPLt~N?PWLZ3U9<+4Nb2h6V-d6(c@EIDnb@j0do#xePRwp*)&3^ zx%xxEq$o(D33N()-v^F9PTQ0^TlCnL1srxC4`D*44X;a?WkB-Jv1gF}eqq5Bmljwc zd8~ga>yNnff%>R2tpAKT3a{G13X1}cN`Ci!OI)_h%3>%Q9I2Jr|P( zKHJf?EZ>I1auxi3fchZE(?rAZ)2_Pu>4zW|PN@9m2#5+@h|Vhh1yC*v@kX@*y4Rcl zv)p=&3jS^UAa2GzEwPjnxaC4tTfxU`v9}?K%zy?RdA%?kTs)|;BHrp^pbP^p9)2@9 zEweMwigb(=t(%~Hk8Hc6lXzV9x?NFJ_bi3PF2-8^=I}}3iQ%2Rj*!dgtCEZBRj$jo zF^0L=>);dR`GgDJkmS{cz9r=NbCYguifUQ_ug}4QoLT8u6e|D4p6v3@WbwHF$jL^3 zR*h|c!3laike!7(`&u{;to^>^-X{DJ{vSucp8WuqIP8I#&!2Zi4B^97O`l|uk=(;y z5^<5c0_R;Z%mR)4O=xeo=~>r~jU-Q48zTSj)gn?X?}CJ`7} zI@}nae+(u&i0AUyTgBQ=_s*2g zs_xD2X+0n1mT^Z90o*FhBtb}H*Rk@w6?NC+tBC+xSd{=y7U(rL237ghQ-YTKRdTXnSoC9c(K#~VyltQU0 z+#n0D7sVUhoZZhIWh2+_I5ih8<$q@u`lghB+V%gE&dj500)@ydmbE!38tM*M+25}ADihUNq zxWReZ(mDvc)9f#l#n4ukmGwPFN&SM5Z9n^8F)TAyNWu3hb1g7P)ky1UdG=GF0n+Bz z*V7-LphIA}pmJ!F$Hwq2GWqBG%!x&Z?^N#&vnIDbk_YxP`DN_8H9h<-T>H(szBZxB zy(i8Wiu<4^6svFf8UY zjU3|K5xcdqf+1H=UpUrif1s!;b`*S6GfOqco2sj*rIC9nu}V`f85zJ44i6V%HUYiSakfKxC75q~R#(r?*W&Gef8VW%T08Od@IOepvAkS_ z4fjvR7=6{|k+1|R(@|fuSc*DWo88PX*c-O`F179tuPMh2=}3$UVi1L))?9iY44DHr zQ$${$mpVdIPWLJVvl>@ITdY?=K$OE4O~)lv(hRpBH$w}8h6f~p%WfU_x|MQRpw{}=$El}Xgt2i#jj72tAcuAGxEc0pgsz)D+? z-ZSd}fr4PyE5KImeDO-gSUQq%LG$Ovm4S`zh@E0krV}{dD2Z9>feY{p-(67a7iJ(T zt~L}MEnT#A%+Z3GXP!Lc)LWBuAYN=Y@P`I84%-~OsWA*Q*;a!9*0%_cONxsbG zE-TG0PIRKLwIOFoGW%`Pm~D&UAMeI9?T44Io)VYpSw#WCoF_4J&~f5Kg3>>PR7+4Uv`D3Sk2l{{RONI6Yj|o0hX|~Fu%3U zU5I*#+}xS0eG<`ni|`_=<*20?VXfCvW#2nL9>)E8G{tb*l}0S zsctSB;L)8Zk&(-e1E5k`xJw}kO4wL*-#}5al+GtsR6)KjKEU1iO@smjuOUTTuIy7t znu?Dogj^S!PF23!&R!hWTfwRuLtxT$`)ithrG{af0O2e_~+I80rrwKf`6faQcD zp#AwueoeZ~kIRo=i0Z0ZYZsa0@-twqR4&0Si=M-NLuil0VUt!X>m-g|u}Qaim>D>6 zV-u_ObAF;FC;(=7B2S^@pDDc7z)H!TV`|Q*nWBv^%QzUPCog5ZYz1LU)nOR^n#eFz zE3v|NjR*;R(9KzsvZ0)Uf(YF-I8;uLJB9ZYN-;`acJ zzPD4(JQ&9og1>#UYWcbh`^Ek-H7c>w*@*!fBB}>Mgtx~aV9S85X*kS)OT2yHAPu{p)nE743LnP^CI|>>6=P?8#no1t z*h|S043sN`J9;Qa>}ss#=y5KaO|UQ?7)|lqC0_C5s0GIVi~V?%Vlk2sk>&RaKhOm~ zPWe}XL%JBO&BVAJ;hMk&v16rx63KigvrqGUBw*>kGY>Y|_b!8{D`Rr$&{wlm# z5b^3u$Sw$JO3IUmx2&Y=P^7xsF*km7>puIp73pa?pA{=#F;W_(3~AT5AhUI>pL_8@IN7v!o99a@B9L z8`QE7YAwK>PvXCT`dwZbIxS_dMuBcVP7Ya6%MHtj_Bdb>KpJG zdwZ$MM2z83>y^kf$!a&h*FSJw?**M%4GLg%LY~@F!Qe(XDiRK#I$4?%&XDCJDj$ra2ImUkGiw_CF3;d!Cba99kI ze{bt7sDPGGs3;tsXG|+rAnTWFWaHE2Pvg>yTfHtnMF0^UdvYy-@Y3Iy9GvD2aL~}o z%{azb{_3*W+$ESpw^lCazLf8#qfU8itDPn-Gs6dBs=*?Aw>Gm(7hnZyXB_isdEZRf z;dugfNL7Wx{kCipZlEg-9jJ7GV zXzb~cT+1FT*H#)ikeyUmIIJ_-;Id#iqgI{P1_SX+BLsiG*O9ex=vp(F4 zC3{_zJ4}C}a$IO1f?q1dCM(%~1@T?974(65*3dvy#-|0Y|DP&lc%$wL4;vdg% zGuX~|Ez<6er@n?*+SuVAKsH|~XWL<~u+f*eRlZR?owE)R%2erTj=i!@`U>^FA!K=< z0;?WSs0Z{XCDM^tyrSzlsufWCLAVvM0VkMEtzt>Uk#r#a>~=F~#z>>~X?4nz?~3pG zmAliU0+PCD(t^zd#OC~po#BwoE@cu zt8=iwEeHQ;!N?c30H9@Xu&;*B6rF6z&6$5^3E$(jpy zIrt1-E2fs>pb}Ql;jo&?8QE=FCm*~i4PanIm?ro`V`0asN?rtBG@vHQ^}3I%PfD7h zJ5IWl%MYBIyu6=`3lrTTgoD(CB#HJs+km02{$=}6P~+hbN#7euBHuI9_<|ttK|CEv zz|G<#SAQwS4&W)LpW2A+cHzUik7l@VsI0r>HiYntfMAmiE0tz~DXgGQ=$;Cty)*t= z32(r+^O4ERhtt~S&iqbnO=GjCi`^kH7{(V)8K_Lowpu%xTB~^nUUuRXcKB{exUUW^ zi3TCHQ{_iNPzWN(r{i5-ZNdJ9sFLsw=p{=9t``?K!ItUBJ=*3}M?>$Su5RUPq0MV# z5J5M$mcU6YMisMF=xiilFu*FakbljwS;MVD$x#LL*R0~Z)wl*D4IR_7Wb7XfI-3$< zW2}{vV*h+$LPt?&B%X2T0dq*@1hoJ$gZt&8vg>Ecv%Zvkz>Y^r8KZO*hyZ5Zacn*4 zy|fW$Rq=(@^7x%UiE1z}J_k-a_0jm>Xf@^6_vGX*yW&ENgIf+$@w|mC@zYG<$>=!&4axJ5gM;b|pvOXK1_xh*>Yyd9J!9 z0dye?pK{X+etmV0or6M?N-;`tPFkRYekF+9h2~`yW(!*aN2+`1S(<~1VWJsIsg677 zEB8Js7P)|)4MEb5*bTw0P)ex^+v|(Ut#{eGDV(tS`5L>Ihypob3wGB{1<8q%p~4gX z3g@Nf%A<$LxhM8)?8BFHbuSl^Dr=Abl@=x z2}PbRSBUm&bhBt6c(jmee+bl93IuzNzd=ix1B$aGb(0>?uEe}6KyHT76ZJZ%tA}M6 zl@-5YlFAQS^07C;_sMMxw!G-uc7(8B$<^R4%D}$GmR-}Nx4@cPT9b2YU4HA&_N+(( zLldT0DqHr(dEJDQ-HjJ_;L&Ph4>tK5TTu-uL}phXL7JL9ibdATB+~>1Aw`^lkOBmR%kTW6666Nq5 zROGS}39rLO($X>;ADqBE#r;W1A&jrpC~dUcxNCn*#0FHFF9^vtjf#i7CHPS-4h;$b zkPaooCNxl2@climaAbP4cGRZ#b?}|uYgh+hp9JjVzl4%=X2!NNG}1%0Q!Llu8-b<;IYEZMaS%3fF7v?J>xIGzaY`; zI~q8_qSwxUNHjcMQ2SMaiR!=jOF^qL z-pB6F6Blo#yf@uLTFvCI1l1+$HXnt!Qc9S{6c+bNB`U0phw=J>Km(4BG3a;!FlgZ# z{i`EBEX0k2_LblHT;k1I3=1z}38To=HO_R6=n2J>%8>JG8_(Z>#WHP*HZ9U?Mw-}i z$f_ToT|!RGUHSYh@cX5FWDpPiImO`%KpOy4{aBF%i(A%g3dQe_$}w2@AL>M&pL@)2 zdFc!h^bIbQakFkaYGfP8Wp23y25vT6zqWFcH!bdvOC=_}0F}i>prmHMko|llB_>zW z?=a7(1T9Ax&v27*%)Z}pQ&p6@Keugr<+*hIo9O13v%z=HSqMPd_n-uCIvC4XrYRHz z$zLsb0_jyfw~9du31(!<&^g1|BN)?LyWk~iCC{UpWX^m~-yZ&xY=}XPH73Ua$O1)% zgz(vdx5jB@CC-P(w{{SOHI2&P3YK(dld)(1$6e~{<58z)Kvc}tTxZaRM@Z186+}M~ zdXMNmVYrX$L{_-p^Y}MMxqAf3k+v>LZ7ipgv1alK+;=xaL?6v#r9_dxkLJkThf6;? z4UD3&P@2AL2Rdml*kF-x{N`rYTrBdStNvb61_RuFaGnOjW9QoAhe4BNuH0PAa{tbO z!Q!t43!{#0vY~1*0V`FpI#g$SG`(L_R<4&3!+z|ggYt zaOGb3N6cJ83^5K4<(Q_5(({WeU(1S$zhLW`;%YnXn~uYV+deLyDzajZOcd-rPP5Vuu4of<=Q!W(`X+DNWdn0>oP$Rs$WBM$a z9g?FVS)Tx+xMXx0O+gvW`aspZke8jo-pe0}8oXTKHs(Rh+>z^yUE_-4CB3r^cK1I3 zKWz?Nd_JKX9`na|LklR2JFeNXmsp%m>g)_TZZ#VXAJ5iRVo4gmc$6LJugv>ve<3cB z+-f+v3Q%O-rlX&E!I1*Kt`EazPRR3EB`k+Sw2?LcYd>Y8i%09C(L*g)=4>Fy zx5qOHb^YZJ9^Kh!wCasH0?Ke&iv7j9jj%jQ<`2?x=XwSN84wn8-5h4-sls1sQgnYl z{*%u#@Uh|^lO9=SsbSIVvlpz9XvT-*u*lR~(^4Pui(4WM_Pc`Gss3Qye`69KECO1E zl|}x0^1qJ#D=U_SygLY3c~1K0G5`D8e_xnmVQcfPDQt-O--nrqHE_JA%sxE(Uq|u( z`R9L3hxdEG@z0|9 o-$UXbYy4x4e?o}=FBAf$uwi#%Be@GY#lik*s_LqMpV~zHA5J^8CjbBd From 1ebb205d64919e9a242ed16cade3771e2c54cb34 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Thu, 18 Jun 2015 15:38:33 -0500 Subject: [PATCH 11/29] installer: fix menu display, log file function remove unused menu item, which breaks view log function create empty log file, so view log function works prior to install Signed-off-by: Matt DeVillier --- packages/tools/installer/scripts/installer | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/tools/installer/scripts/installer b/packages/tools/installer/scripts/installer index cda54db6b5..b953397754 100755 --- a/packages/tools/installer/scripts/installer +++ b/packages/tools/installer/scripts/installer @@ -611,8 +611,7 @@ menu_main() { --title "$MSG_TITLE" --menu "$MSG_MENU" 20 70 5 \ 1 "Quick Install of OpenELEC" \ 2 "Repair / Upgrade" \ - 3 "Setup OpenELEC" \ - 4 "Show logfile" 2> $TMPDIR/mainmenu + 3 "Show logfile" 2> $TMPDIR/mainmenu case $? in 0) @@ -664,6 +663,9 @@ LOGFILE="$TMPDIR/install.log" rm -rf $TMPDIR mkdir -p $TMPDIR +#create log file +touch "$LOGFILE" + # main while true; do From 9e5a61725a5b14af15205a7ee864c5d800dc67f3 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 19 Jun 2015 12:04:16 +0200 Subject: [PATCH 12/29] projects/RPi*: switch to kernel 4.1, update RPi support patches Signed-off-by: Stephan Raue --- projects/RPi/linux/linux.arm.conf | 115 +- projects/RPi/options | 2 +- .../patches/linux/linux-01-RPi_support.patch | 58373 +++++----------- projects/RPi2/linux/linux.arm.conf | 119 +- projects/RPi2/options | 2 +- .../patches/linux/linux-01-RPi_support.patch | 58373 +++++----------- 6 files changed, 36196 insertions(+), 80788 deletions(-) diff --git a/projects/RPi/linux/linux.arm.conf b/projects/RPi/linux/linux.arm.conf index de549daf9a..8b0b08ecfc 100644 --- a/projects/RPi/linux/linux.arm.conf +++ b/projects/RPi/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.0.5 Kernel Configuration +# Linux/arm 4.1.0-rc8 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -21,6 +21,7 @@ CONFIG_NEED_MACH_IO_H=y CONFIG_NEED_MACH_MEMORY_H=y CONFIG_PHYS_OFFSET=0x0 CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -61,13 +62,13 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # # Timers subsystem @@ -97,6 +98,7 @@ CONFIG_SRCU=y # CONFIG_RCU_STALL_COMMON is not set # CONFIG_TREE_RCU_TRACE is not set CONFIG_RCU_KTHREAD_PRIO=0 +# CONFIG_RCU_EXPEDITE_BOOT is not set CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y @@ -133,6 +135,7 @@ CONFIG_HAVE_UID16=y CONFIG_BPF=y CONFIG_EXPERT=y # CONFIG_UID16 is not set +CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set # CONFIG_SYSFS_SYSCALL is not set CONFIG_SYSCTL_SYSCALL=y @@ -199,6 +202,7 @@ CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y @@ -274,11 +278,11 @@ CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y # System Type # CONFIG_MMU=y +CONFIG_ARCH_BCM2708=y +# CONFIG_ARCH_BCM2709 is not set # CONFIG_ARCH_MULTIPLATFORM is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_AT91 is not set -CONFIG_ARCH_BCM2708=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set @@ -297,7 +301,6 @@ CONFIG_ARCH_BCM2708=y # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE_LEGACY is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set @@ -305,7 +308,6 @@ CONFIG_ARCH_BCM2708=y # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set -# CONFIG_ARCH_BCM2709 is not set # # Broadcom BCM2708 Implementations @@ -401,6 +403,7 @@ CONFIG_CLEANCACHE=y CONFIG_FRONTSWAP=y CONFIG_CMA=y # CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set CONFIG_CMA_AREAS=7 # CONFIG_ZSWAP is not set # CONFIG_ZPOOL is not set @@ -458,6 +461,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y # CONFIG_CPUFREQ_DT is not set # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set CONFIG_ARM_BCM2835_CPUFREQ=y +# CONFIG_QORIQ_CPUFREQ is not set # # CPU Idle @@ -469,6 +473,7 @@ CONFIG_CPU_IDLE_GOV_MENU=y # # ARM CPU Idle Drivers # +# CONFIG_ARM_CPUIDLE is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # @@ -484,7 +489,6 @@ CONFIG_VFP=y # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -772,7 +776,7 @@ CONFIG_DNS_RESOLVER=y # CONFIG_VSOCKETS is not set # CONFIG_NETLINK_MMAP is not set # CONFIG_NETLINK_DIAG is not set -# CONFIG_NET_MPLS_GSO is not set +# CONFIG_MPLS is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set # CONFIG_CGROUP_NET_PRIO is not set @@ -796,11 +800,15 @@ CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_HIDP=m CONFIG_BT_LE=y # CONFIG_BT_SELFTEST is not set +# CONFIG_BT_DEBUGFS is not set # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set CONFIG_BT_HCIBCM203X=m @@ -922,6 +930,7 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_PMEM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set @@ -1058,13 +1067,7 @@ CONFIG_TUN=y # Distributed Switch Architecture drivers # # CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6060 is not set # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -# CONFIG_NET_DSA_MV88E6171 is not set -# CONFIG_NET_DSA_MV88E6352 is not set -# CONFIG_NET_DSA_BCM_SF2 is not set # CONFIG_ETHERNET is not set CONFIG_PHYLIB=y @@ -1073,7 +1076,6 @@ CONFIG_PHYLIB=y # # CONFIG_AT803X_PHY is not set # CONFIG_AMD_PHY is not set -# CONFIG_AMD_XGBE_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -1378,8 +1380,8 @@ CONFIG_HW_RANDOM_BCM2708=m # CONFIG_TCG_TPM is not set CONFIG_BRCM_CHAR_DRIVERS=y CONFIG_BCM_VC_CMA=y -# CONFIG_BCM_VC_SM is not set CONFIG_BCM2708_VCMEM=y +# CONFIG_BCM_VC_SM is not set # CONFIG_XILLYBUS is not set # @@ -1496,8 +1498,9 @@ CONFIG_PINCTRL=y CONFIG_PINMUX=y CONFIG_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set -CONFIG_PINCTRL_BCM2835=y +# CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_BCM2835=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y @@ -1507,55 +1510,44 @@ CONFIG_OF_GPIO=y CONFIG_GPIO_SYSFS=y # -# Memory mapped GPIO drivers: +# Memory mapped GPIO drivers # # CONFIG_GPIO_74XX_MMIO is not set -# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_ALTERA is not set # CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_EM is not set -# CONFIG_GPIO_ZEVIO is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_SCH311X is not set -# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_ZEVIO is not set # -# I2C GPIO expanders: +# I2C GPIO expanders # -CONFIG_GPIO_ARIZONA=m +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set -# CONFIG_GPIO_ADNP is not set # -# PCI GPIO expanders: +# MFD GPIO expanders # +CONFIG_GPIO_ARIZONA=m # -# SPI GPIO expanders: +# SPI GPIO expanders # +# CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_MAX7301 is not set # CONFIG_GPIO_MCP23S08 is not set # CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set # -# AC97 GPIO expanders: -# - -# -# LPC GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# - -# -# USB GPIO expanders: +# USB GPIO expanders # CONFIG_W1=m @@ -1684,6 +1676,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT15 is not set @@ -1819,10 +1812,12 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_VIPERBOARD is not set @@ -1838,6 +1833,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set # CONFIG_MFD_STMPE is not set @@ -2139,7 +2135,6 @@ CONFIG_MEDIA_TUNER_FC0013=m CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88TS2022=m CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m @@ -2396,6 +2391,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m # CONFIG_SND_SOC_FSL_SPDIF is not set # CONFIG_SND_SOC_FSL_ESAI is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_QCOM is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -2459,6 +2455,8 @@ CONFIG_SND_SOC_WM8731=m # CONFIG_SND_SOC_WM8770 is not set # CONFIG_SND_SOC_WM8776 is not set CONFIG_SND_SOC_WM8804=m +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set # CONFIG_SND_SOC_WM8903 is not set # CONFIG_SND_SOC_WM8962 is not set # CONFIG_SND_SOC_WM8978 is not set @@ -2499,7 +2497,6 @@ CONFIG_DRAGONRISE_FF=y CONFIG_HID_EZKEY=y # CONFIG_HID_HOLTEK is not set # CONFIG_HID_GT683R is not set -# CONFIG_HID_HUION is not set # CONFIG_HID_KEYTOUCH is not set CONFIG_HID_KYE=y # CONFIG_HID_UCLOGIC is not set @@ -2728,6 +2725,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set # CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set # # USB Physical Layer drivers @@ -2802,6 +2800,7 @@ CONFIG_LEDS_GPIO=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers @@ -2843,6 +2842,7 @@ CONFIG_RTC_INTF_DEV=y # I2C RTC drivers # # CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set CONFIG_RTC_DRV_DS1307=m # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set @@ -2923,7 +2923,6 @@ CONFIG_DMADEVICES=y # DMA Devices # # CONFIG_AMBA_PL08X is not set -# CONFIG_DW_DMAC_CORE is not set # CONFIG_DW_DMAC is not set # CONFIG_PL330_DMA is not set CONFIG_DMA_BCM2708=y @@ -2988,6 +2987,7 @@ CONFIG_LIRC_XBOX=m # CONFIG_GS_FPGABOOT is not set # CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_FB_TFT is not set +# CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3000,7 +3000,6 @@ CONFIG_COMMON_CLK=y # CONFIG_CLK_QORIQ is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_CDCE706 is not set -# CONFIG_COMMON_CLK_QCOM is not set # # Hardware Spinlock drivers @@ -3014,9 +3013,9 @@ CONFIG_COMMON_CLK=y # CONFIG_SH_TIMER_MTU2 is not set # CONFIG_SH_TIMER_TMU is not set # CONFIG_EM_TIMER_STI is not set -# CONFIG_CLKSRC_VERSATILE is not set CONFIG_MAILBOX=y CONFIG_BCM2708_MBOX=y +# CONFIG_ARM_MHU is not set # CONFIG_PL320_MBOX is not set # CONFIG_ALTERA_MBOX is not set # CONFIG_IOMMU_SUPPORT is not set @@ -3045,6 +3044,7 @@ CONFIG_EXTCON_ARIZONA=m # CONFIG_EXTCON_GPIO is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set # CONFIG_MEMORY is not set # CONFIG_IIO is not set # CONFIG_PWM is not set @@ -3066,6 +3066,11 @@ CONFIG_IRQCHIP=y # # CONFIG_ANDROID is not set +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set + # # File systems # @@ -3076,6 +3081,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set @@ -3103,6 +3109,10 @@ CONFIG_BTRFS_FS=m # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set # CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +# CONFIG_F2FS_FS_XATTR is not set +CONFIG_F2FS_CHECK_FS=y CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y CONFIG_FILE_LOCKING=y @@ -3190,10 +3200,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_F2FS_FS=y -CONFIG_F2FS_STAT_FS=y -# CONFIG_F2FS_FS_XATTR is not set -CONFIG_F2FS_CHECK_FS=y CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3346,6 +3352,7 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_TIMER_STATS is not set # @@ -3373,6 +3380,7 @@ CONFIG_PANIC_TIMEOUT=0 # # RCU Debugging # +# CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set @@ -3410,6 +3418,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -3508,7 +3517,6 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA1_ARM=m CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3518,7 +3526,6 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_ARM=m # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -3553,6 +3560,10 @@ CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_USER_API_RNG is not set # CONFIG_CRYPTO_HW is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_SHA256_ARM=m +CONFIG_CRYPTO_AES_ARM=m # CONFIG_BINARY_PRINTF is not set # diff --git a/projects/RPi/options b/projects/RPi/options index ff8d9084ee..ce23603dc8 100644 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -57,7 +57,7 @@ # Kernel to use. values can be: # default: default mainline kernel - LINUX="4.0" + LINUX="default" # NOOBS supported hex versions NOOBS_HEX="2,3,4,5,6,7,8,9,d,e,f,10,11,12,14,19" diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index c1f57bb01c..0008aa8b30 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support.patch @@ -1,52 +1,77 @@ -From 0e7aaf92061593060fc62957aeec745534add9a4 Mon Sep 17 00:00:00 2001 +From 8e2bdce040b3459de0954cb2f212dea47549131c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 001/216] Main bcm2708 linux port +Subject: [PATCH 01/77] Main bcm2708/bcm2709 linux port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix +Signed-off-by: Noralf Trønnes --- - arch/arm/Kconfig | 17 + + arch/arm/Kconfig | 39 ++ arch/arm/Kconfig.debug | 8 + - arch/arm/Makefile | 1 + + arch/arm/Makefile | 2 + + arch/arm/kernel/head.S | 8 + arch/arm/kernel/process.c | 10 + - arch/arm/mach-bcm2708/Kconfig | 26 + - arch/arm/mach-bcm2708/Makefile | 6 + + arch/arm/mach-bcm2708/Kconfig | 30 + + arch/arm/mach-bcm2708/Makefile | 5 + arch/arm/mach-bcm2708/Makefile.boot | 3 + - arch/arm/mach-bcm2708/armctrl.c | 208 +++++++ + arch/arm/mach-bcm2708/armctrl.c | 304 +++++++++ arch/arm/mach-bcm2708/armctrl.h | 27 + - arch/arm/mach-bcm2708/bcm2708.c | 662 +++++++++++++++++++++++ + arch/arm/mach-bcm2708/bcm2708.c | 622 ++++++++++++++++++ arch/arm/mach-bcm2708/bcm2708.h | 49 ++ - arch/arm/mach-bcm2708/clock.c | 61 +++ - arch/arm/mach-bcm2708/clock.h | 24 + - arch/arm/mach-bcm2708/dma.c | 399 ++++++++++++++ - arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 ++++++++++++++ - arch/arm/mach-bcm2708/include/mach/arm_power.h | 62 +++ + arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 ++++++++++++ arch/arm/mach-bcm2708/include/mach/clkdev.h | 7 + arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 + - arch/arm/mach-bcm2708/include/mach/dma.h | 88 +++ - arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 +++ + arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 ++ arch/arm/mach-bcm2708/include/mach/frc.h | 38 ++ arch/arm/mach-bcm2708/include/mach/hardware.h | 28 + arch/arm/mach-bcm2708/include/mach/io.h | 27 + - arch/arm/mach-bcm2708/include/mach/irqs.h | 196 +++++++ + arch/arm/mach-bcm2708/include/mach/irqs.h | 196 ++++++ arch/arm/mach-bcm2708/include/mach/memory.h | 57 ++ - arch/arm/mach-bcm2708/include/mach/platform.h | 228 ++++++++ - arch/arm/mach-bcm2708/include/mach/power.h | 26 + + arch/arm/mach-bcm2708/include/mach/platform.h | 228 +++++++ arch/arm/mach-bcm2708/include/mach/system.h | 38 ++ arch/arm/mach-bcm2708/include/mach/timex.h | 23 + arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 +++ - arch/arm/mach-bcm2708/include/mach/vc_mem.h | 35 ++ - arch/arm/mach-bcm2708/include/mach/vcio.h | 165 ++++++ arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + - arch/arm/mach-bcm2708/power.c | 197 +++++++ - arch/arm/mach-bcm2708/vc_mem.c | 431 +++++++++++++++ - arch/arm/mach-bcm2708/vcio.c | 474 ++++++++++++++++ + arch/arm/mach-bcm2709/Kconfig | 42 ++ + arch/arm/mach-bcm2709/Makefile | 6 + + arch/arm/mach-bcm2709/Makefile.boot | 3 + + arch/arm/mach-bcm2709/armctrl.c | 361 ++++++++++ + arch/arm/mach-bcm2709/armctrl.h | 27 + + arch/arm/mach-bcm2709/bcm2708_gpio.c | 426 ++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 801 +++++++++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.h | 49 ++ + arch/arm/mach-bcm2709/delay.S | 21 + + arch/arm/mach-bcm2709/include/mach/arm_control.h | 493 ++++++++++++++ + arch/arm/mach-bcm2709/include/mach/barriers.h | 3 + + arch/arm/mach-bcm2709/include/mach/clkdev.h | 7 + + arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 + + arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 ++++ + arch/arm/mach-bcm2709/include/mach/frc.h | 38 ++ + arch/arm/mach-bcm2709/include/mach/gpio.h | 17 + + arch/arm/mach-bcm2709/include/mach/hardware.h | 28 + + arch/arm/mach-bcm2709/include/mach/io.h | 27 + + arch/arm/mach-bcm2709/include/mach/irqs.h | 225 +++++++ + arch/arm/mach-bcm2709/include/mach/memory.h | 57 ++ + arch/arm/mach-bcm2709/include/mach/platform.h | 225 +++++++ + arch/arm/mach-bcm2709/include/mach/system.h | 38 ++ + arch/arm/mach-bcm2709/include/mach/timex.h | 23 + + arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 +++ + arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 + + arch/arm/mach-bcm2709/include/mach/vc_support.h | 69 ++ + arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 + + arch/arm/mach-bcm2709/vc_mem.c | 431 ++++++++++++ + arch/arm/mach-bcm2709/vc_support.c | 318 +++++++++ arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 15 +- - arch/arm/tools/mach-types | 1 + + arch/arm/mm/proc-v7.S | 1 + + arch/arm/tools/mach-types | 2 + + drivers/clocksource/arm_arch_timer.c | 36 + drivers/tty/serial/amba-pl011.c | 2 +- include/linux/mmc/host.h | 1 + - 41 files changed, 4251 insertions(+), 5 deletions(-) + 62 files changed, 6436 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-bcm2708/Kconfig create mode 100644 arch/arm/mach-bcm2708/Makefile create mode 100644 arch/arm/mach-bcm2708/Makefile.boot @@ -54,14 +79,9 @@ Signed-off-by: popcornmix create mode 100644 arch/arm/mach-bcm2708/armctrl.h create mode 100644 arch/arm/mach-bcm2708/bcm2708.c create mode 100644 arch/arm/mach-bcm2708/bcm2708.h - create mode 100644 arch/arm/mach-bcm2708/clock.c - create mode 100644 arch/arm/mach-bcm2708/clock.h - create mode 100644 arch/arm/mach-bcm2708/dma.c create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_control.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/clkdev.h create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h create mode 100644 arch/arm/mach-bcm2708/include/mach/entry-macro.S create mode 100644 arch/arm/mach-bcm2708/include/mach/frc.h create mode 100644 arch/arm/mach-bcm2708/include/mach/hardware.h @@ -69,57 +89,102 @@ Signed-off-by: popcornmix create mode 100644 arch/arm/mach-bcm2708/include/mach/irqs.h create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h create mode 100644 arch/arm/mach-bcm2708/include/mach/timex.h create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2708/power.c - create mode 100644 arch/arm/mach-bcm2708/vc_mem.c - create mode 100644 arch/arm/mach-bcm2708/vcio.c + create mode 100644 arch/arm/mach-bcm2709/Kconfig + create mode 100644 arch/arm/mach-bcm2709/Makefile + create mode 100644 arch/arm/mach-bcm2709/Makefile.boot + create mode 100644 arch/arm/mach-bcm2709/armctrl.c + create mode 100644 arch/arm/mach-bcm2709/armctrl.h + create mode 100644 arch/arm/mach-bcm2709/bcm2708_gpio.c + create mode 100644 arch/arm/mach-bcm2709/bcm2709.c + create mode 100644 arch/arm/mach-bcm2709/bcm2709.h + create mode 100644 arch/arm/mach-bcm2709/delay.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_control.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/barriers.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/clkdev.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/frc.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/gpio.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/hardware.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/irqs.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/timex.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h + create mode 100755 arch/arm/mach-bcm2709/include/mach/vc_support.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h + create mode 100644 arch/arm/mach-bcm2709/vc_mem.c + create mode 100644 arch/arm/mach-bcm2709/vc_support.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index cf4c0c9..6876ae8 100644 +index 45df48b..bd9b2f3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -369,6 +369,22 @@ config ARCH_AT91 - This enables support for systems based on Atmel - AT91RM9200, AT91SAM9 and SAMA5 processors. +@@ -314,6 +314,42 @@ choice + default ARCH_VERSATILE if !MMU + default ARCH_MULTIPLATFORM if MMU +config ARCH_BCM2708 + bool "Broadcom BCM2708 family" + select CPU_V6 + select ARM_AMBA -+ select HAVE_CLK + select HAVE_SCHED_CLOCK + select NEED_MACH_GPIO_H + select NEED_MACH_MEMORY_H -+ select CLKDEV_LOOKUP ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ + select GENERIC_CLOCKEVENTS + select ARM_ERRATA_411920 + select MACH_BCM2708 + select VC4 ++ select FIQ + help + This enables support for Broadcom BCM2708 boards. + - config ARCH_CLPS711X - bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" - select ARCH_REQUIRE_GPIOLIB -@@ -967,6 +983,7 @@ source "arch/arm/plat-versatile/Kconfig" - source "arch/arm/mach-vt8500/Kconfig" - - source "arch/arm/mach-w90x900/Kconfig" ++config ARCH_BCM2709 ++ bool "Broadcom BCM2709 family" ++ select ARCH_HAS_BARRIERS if SMP ++ select CPU_V7 ++ select HAVE_SMP ++ select ARM_AMBA ++ select MIGHT_HAVE_CACHE_L2X0 ++ select HAVE_SCHED_CLOCK ++ select NEED_MACH_MEMORY_H ++ select NEED_MACH_IO_H ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ ++ select GENERIC_CLOCKEVENTS ++ select MACH_BCM2709 ++ select VC4 ++ select FIQ ++ help ++ This enables support for Broadcom BCM2709 boards. ++ + config ARCH_MULTIPLATFORM + bool "Allow multiple platforms to be selected" + depends on MMU +@@ -823,6 +859,9 @@ config ARCH_VIRT + # Kconfigs may be included either alphabetically (according to the + # plat- suffix) or along side the corresponding mach-* source. + # +source "arch/arm/mach-bcm2708/Kconfig" ++source "arch/arm/mach-bcm2709/Kconfig" ++ + source "arch/arm/mach-mvebu/Kconfig" - source "arch/arm/mach-zynq/Kconfig" - + source "arch/arm/mach-alpine/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 970de75..eaadbe8 100644 +index 0c12ffb..18db6c4 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -1209,6 +1209,14 @@ choice +@@ -1197,6 +1197,14 @@ choice options; the platform specific options are deprecated and will be soon removed. @@ -135,22 +200,42 @@ index 970de75..eaadbe8 100644 config DEBUG_AT91_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index eb7bb51..27c0f92 100644 +index 985227c..e5df9a5 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile -@@ -146,6 +146,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 +@@ -142,6 +142,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 + + # Machine directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. ++machine-$(CONFIG_ARCH_BCM2708) += bcm2708 ++machine-$(CONFIG_ARCH_BCM2709) += bcm2709 + machine-$(CONFIG_ARCH_ALPINE) += alpine machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_AXXIA) += axxia - machine-$(CONFIG_ARCH_BCM) += bcm -+machine-$(CONFIG_ARCH_BCM2708) += bcm2708 - machine-$(CONFIG_ARCH_BERLIN) += berlin - machine-$(CONFIG_ARCH_CLPS711X) += clps711x - machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 3637973..380430a 100644 +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -680,6 +680,14 @@ ARM_BE8(rev16 ip, ip) + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 1b + ret lr ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop + #endif + ENDPROC(__fixup_a_pv_table) + diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 2bf1a16..2915516 100644 +index f192a2a..f638dae 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c -@@ -172,6 +172,16 @@ void arch_cpu_idle_dead(void) +@@ -98,6 +98,16 @@ void arch_cpu_idle_dead(void) } #endif @@ -164,15 +249,15 @@ index 2bf1a16..2915516 100644 + +__setup("reboot=", reboot_setup); + - /* - * Called by kexec, immediately prior to machine_kexec(). - * + void __show_regs(struct pt_regs *regs) + { + unsigned long flags; diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig new file mode 100644 -index 0000000..1f11478 +index 0000000..4955422 --- /dev/null +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -0,0 +1,26 @@ +@@ -0,0 +1,30 @@ +menu "Broadcom BCM2708 Implementations" + depends on ARCH_BCM2708 + @@ -184,12 +269,16 @@ index 0000000..1f11478 + help + Include support for the Broadcom(R) BCM2708 platform. + -+config BCM2708_VCMEM -+ bool "Videocore Memory" ++config BCM2708_DT ++ bool "BCM2708 Device Tree support" + depends on MACH_BCM2708 -+ default y -+ help -+ Helper for videocore memory access and total size allocation. ++ default n ++ select USE_OF ++ select ARCH_REQUIRE_GPIOLIB ++ select PINCTRL ++ select PINCTRL_BCM2835 ++ help ++ Enable Device Tree support for BCM2708 + +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" @@ -201,16 +290,15 @@ index 0000000..1f11478 +endmenu diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile new file mode 100644 -index 0000000..c76f39bc +index 0000000..e7d5a29 --- /dev/null +++ b/arch/arm/mach-bcm2708/Makefile -@@ -0,0 +1,6 @@ +@@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + -+obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o ++obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot new file mode 100644 index 0000000..67039c3 @@ -222,10 +310,10 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c new file mode 100644 -index 0000000..ef1c8d5 +index 0000000..cd252fa --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -0,0 +1,208 @@ +@@ -0,0 +1,304 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * @@ -251,6 +339,8 @@ index 0000000..ef1c8d5 +#include +#include +#include ++#include ++#include + +#include +#include @@ -297,6 +387,99 @@ index 0000000..ef1c8d5 + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); +} + ++#ifdef CONFIG_OF ++ ++#define NR_IRQS_BANK0 21 ++#define NR_BANKS 3 ++#define IRQS_PER_BANK 32 ++ ++/* from drivers/irqchip/irq-bcm2835.c */ ++static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ if (WARN_ON(intsize != 2)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[0] >= NR_BANKS)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) ++ return -EINVAL; ++ ++ if (intspec[0] == 0) ++ *out_hwirq = ARM_IRQ0_BASE + intspec[1]; ++ else if (intspec[0] == 1) ++ *out_hwirq = ARM_IRQ1_BASE + intspec[1]; ++ else ++ *out_hwirq = ARM_IRQ2_BASE + intspec[1]; ++ ++ /* reverse remap_irqs[] */ ++ switch (*out_hwirq) { ++ case INTERRUPT_VC_JPEG: ++ *out_hwirq = INTERRUPT_JPEG; ++ break; ++ case INTERRUPT_VC_USB: ++ *out_hwirq = INTERRUPT_USB; ++ break; ++ case INTERRUPT_VC_3D: ++ *out_hwirq = INTERRUPT_3D; ++ break; ++ case INTERRUPT_VC_DMA2: ++ *out_hwirq = INTERRUPT_DMA2; ++ break; ++ case INTERRUPT_VC_DMA3: ++ *out_hwirq = INTERRUPT_DMA3; ++ break; ++ case INTERRUPT_VC_I2C: ++ *out_hwirq = INTERRUPT_I2C; ++ break; ++ case INTERRUPT_VC_SPI: ++ *out_hwirq = INTERRUPT_SPI; ++ break; ++ case INTERRUPT_VC_I2SPCM: ++ *out_hwirq = INTERRUPT_I2SPCM; ++ break; ++ case INTERRUPT_VC_SDIO: ++ *out_hwirq = INTERRUPT_SDIO; ++ break; ++ case INTERRUPT_VC_UART: ++ *out_hwirq = INTERRUPT_UART; ++ break; ++ case INTERRUPT_VC_ARASANSDIO: ++ *out_hwirq = INTERRUPT_ARASANSDIO; ++ break; ++ } ++ ++ *out_type = IRQ_TYPE_NONE; ++ return 0; ++} ++ ++static struct irq_domain_ops armctrl_ops = { ++ .xlate = armctrl_xlate ++}; ++ ++void __init armctrl_dt_init(void) ++{ ++ struct device_node *np; ++ struct irq_domain *domain; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); ++ if (!np) ++ return; ++ ++ domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, ++ IRQ_ARMCTRL_START, 0, ++ &armctrl_ops, NULL); ++ WARN_ON(!domain); ++} ++#else ++void __init armctrl_dt_init(void) { } ++#endif /* CONFIG_OF */ ++ +#if defined(CONFIG_PM) + +/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ @@ -432,6 +615,7 @@ index 0000000..ef1c8d5 + } + + armctrl_pm_register(base, irq_start, resume_sources); ++ armctrl_dt_init(); + return 0; +} diff --git a/arch/arm/mach-bcm2708/armctrl.h b/arch/arm/mach-bcm2708/armctrl.h @@ -469,10 +653,10 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 -index 0000000..9b4e709 +index 0000000..d6659b0 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -0,0 +1,662 @@ +@@ -0,0 +1,622 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * @@ -502,10 +686,14 @@ index 0000000..9b4e709 +#include +#include +#include ++#include ++#include +#include +#include +#include +#include ++#include ++#include + +#include +#include @@ -523,15 +711,12 @@ index 0000000..9b4e709 +#include + +#include -+#include -+#include +#include + +#include + +#include "bcm2708.h" +#include "armctrl.h" -+#include "clock.h" + +#ifdef CONFIG_BCM_VC_CMA +#include @@ -552,11 +737,13 @@ index 0000000..9b4e709 + +/* command line parameters */ +static unsigned boardrev, serial; -+static unsigned uart_clock; ++static unsigned uart_clock = UART0_CLOCK; +static unsigned disk_led_gpio = 16; +static unsigned disk_led_active_low = 1; +static unsigned reboot_part = 0; + ++static unsigned use_dt = 0; ++ +static void __init bcm2708_init_led(void); + +void __init bcm2708_init_irq(void) @@ -662,44 +849,40 @@ index 0000000..9b4e709 + } +} + ++struct clk __init *bcm2708_clk_register(const char *name, unsigned long fixed_rate) ++{ ++ struct clk *clk; + -+/* -+ * These are fixed clocks. -+ */ -+static struct clk ref24_clk = { -+ .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */ -+}; ++ clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, ++ fixed_rate); ++ if (IS_ERR(clk)) ++ pr_err("%s not registered\n", name); + -+static struct clk osc_clk = { -+#ifdef CONFIG_ARCH_BCM2708_CHIPIT -+ .rate = 27000000, -+#else -+ .rate = 500000000, /* ARM clock is set from the VideoCore booter */ -+#endif -+}; ++ return clk; ++} + -+/* warning - the USB needs a clock > 34MHz */ ++void __init bcm2708_register_clkdev(struct clk *clk, const char *name) ++{ ++ int ret; + -+#ifdef CONFIG_MMC_BCM2708 -+static struct clk sdhost_clk = { -+#ifdef CONFIG_ARCH_BCM2708_CHIPIT -+ .rate = 4000000, /* 4MHz */ -+#else -+ .rate = 250000000, /* 250MHz */ -+#endif -+}; -+#endif ++ ret = clk_register_clkdev(clk, NULL, name); ++ if (ret) ++ pr_err("%s alias not registered\n", name); ++} + -+static struct clk_lookup lookups[] = { -+ { /* UART0 */ -+ .dev_id = "dev:f1", -+ .clk = &ref24_clk, -+ }, -+ { /* USB */ -+ .dev_id = "bcm2708_usb", -+ .clk = &osc_clk, -+ } -+}; ++void __init bcm2708_init_clocks(void) ++{ ++ struct clk *clk; ++ ++ clk = bcm2708_clk_register("uart0_clk", uart_clock); ++ bcm2708_register_clkdev(clk, "dev:f1"); ++ ++ clk = bcm2708_clk_register("sdhost_clk", 250000000); ++ bcm2708_register_clkdev(clk, "mmc-bcm2835.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_spi.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); ++} + +#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } +#define UART0_DMA { 15, 14 } @@ -710,21 +893,6 @@ index 0000000..9b4e709 + &uart0_device, +}; + -+static struct resource bcm2708_dmaman_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_dmaman_device = { -+ .name = BCM_DMAMAN_DRIVER_NAME, -+ .id = 0, /* first bcm2708_dma */ -+ .resource = bcm2708_dmaman_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), -+}; -+ +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { @@ -738,38 +906,17 @@ index 0000000..9b4e709 + }, +}; + -+static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -+ { -+ .mapbase = UART1_BASE + 0x40, -+ .irq = IRQ_AUX, -+ .uartclk = 125000000, -+ .regshift = 2, -+ .iotype = UPIO_MEM, -+ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_8250, -+ }, -+ {}, -+}; -+ -+static struct platform_device bcm2708_uart1_device = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = bcm2708_uart1_platform_data, -+ }, -+}; -+ +static struct resource bcm2708_usb_resources[] = { + [0] = { -+ .start = USB_BASE, -+ .end = USB_BASE + SZ_128K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ .start = USB_BASE, ++ .end = USB_BASE + SZ_128K - 1, ++ .flags = IORESOURCE_MEM, ++ }, + [1] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, -+ .flags = IORESOURCE_IRQ, -+ }, ++ .start = IRQ_USB, ++ .end = IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); @@ -786,17 +933,21 @@ index 0000000..9b4e709 +}; + +static struct resource bcm2708_vcio_resources[] = { -+ [0] = { /* mailbox/semaphore/doorbell access */ -+ .start = MCORE_BASE, -+ .end = MCORE_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ { ++ .start = ARMCTRL_0_MAIL0_BASE, ++ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_MAILBOX, ++ .end = IRQ_ARM_MAILBOX, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { -+ .name = BCM_VCIO_DRIVER_NAME, ++ .name = "bcm2708_vcio", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), @@ -806,53 +957,6 @@ index 0000000..9b4e709 + }, +}; + -+static struct resource bcm2708_systemtimer_resources[] = { -+ [0] = { /* system timer access */ -+ .start = ST_BASE, -+ .end = ST_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IRQ_TIMER3, -+ .end = IRQ_TIMER3, -+ .flags = IORESOURCE_IRQ, -+ } -+ -+}; -+ -+static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_systemtimer_device = { -+ .name = "bcm2708_systemtimer", -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_systemtimer_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -+ .dev = { -+ .dma_mask = &systemtimer_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ -+static struct resource bcm2708_powerman_resources[] = { -+ [0] = { -+ .start = PM_BASE, -+ .end = PM_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+struct platform_device bcm2708_powerman_device = { -+ .name = "bcm2708_powerman", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -+ .resource = bcm2708_powerman_resources, -+ .dev = { -+ .dma_mask = &powerman_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+ +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; @@ -865,6 +969,16 @@ index 0000000..9b4e709 + return ret; +} + ++/* ++ * Use these macros for platform and i2c devices that are present in the ++ * Device Tree. This way the devices are only added on non-DT systems. ++ */ ++#define bcm_register_device_dt(pdev) \ ++ if (!use_dt) bcm_register_device(pdev) ++ ++#define i2c_register_board_info_dt(busnum, info, n) \ ++ if (!use_dt) i2c_register_board_info(busnum, info, n) ++ +int calc_rsts(int partition) +{ + return PM_PASSWORD | @@ -930,6 +1044,35 @@ index 0000000..9b4e709 + } +} + ++static void __init bcm2708_init_uart1(void) ++{ ++ struct device_node *np; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); ++ if (of_device_is_available(np)) { ++ pr_info("bcm2708: Mini UART enabled\n"); ++ writel(1, __io_address(UART1_BASE + 0x4)); ++ } ++} ++ ++#ifdef CONFIG_OF ++static void __init bcm2708_dt_init(void) ++{ ++ int ret; ++ ++ of_clk_init(NULL); ++ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++ if (ret) { ++ pr_err("of_platform_populate failed: %d\n", ret); ++ /* Proceed as if CONFIG_OF was not defined */ ++ } else { ++ use_dt = 1; ++ } ++} ++#else ++static void __init bcm2708_dt_init(void) { } ++#endif /* CONFIG_OF */ ++ +void __init bcm2708_init(void) +{ + int i; @@ -940,25 +1083,24 @@ index 0000000..9b4e709 + printk("bcm2708.uart_clock = %d\n", uart_clock); + pm_power_off = bcm2708_power_off; + -+ if (uart_clock) -+ lookups[0].clk->rate = uart_clock; ++ bcm2708_init_clocks(); ++ bcm2708_dt_init(); + -+ for (i = 0; i < ARRAY_SIZE(lookups); i++) -+ clkdev_add(&lookups[i]); -+ -+ bcm_register_device(&bcm2708_dmaman_device); + bcm_register_device(&bcm2708_vcio_device); -+ bcm_register_device(&bcm2708_systemtimer_device); -+ bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device(&bcm2708_uart1_device); -+ bcm_register_device(&bcm2708_powerman_device); ++#ifdef CONFIG_BCM2708_GPIO ++ bcm_register_device_dt(&bcm2708_gpio_device); ++#endif ++ bcm_register_device_dt(&bcm2708_fb_device); ++ bcm_register_device_dt(&bcm2708_usb_device); + + bcm2708_init_led(); ++ bcm2708_init_uart1(); + -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); ++ if (!use_dt) { ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } + } + system_rev = boardrev; + system_serial_low = serial; @@ -1041,10 +1183,6 @@ index 0000000..9b4e709 + bcm2708_clocksource_init(); + + /* -+ * Initialise to a known state (all timers off) -+ */ -+ writel(0, __io_address(ARM_T_CONTROL)); -+ /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER3, &bcm2708_timer_irq); @@ -1091,9 +1229,9 @@ index 0000000..9b4e709 + +static void __init bcm2708_init_led(void) +{ -+ bcm2708_leds[0].gpio = disk_led_gpio; -+ bcm2708_leds[0].active_low = disk_led_active_low; -+ platform_device_register(&bcm2708_led_device); ++ bcm2708_leds[0].gpio = disk_led_gpio; ++ bcm2708_leds[0].active_low = disk_led_active_low; ++ bcm_register_device_dt(&bcm2708_led_device); +} +#else +static inline void bcm2708_init_led(void) @@ -1118,6 +1256,11 @@ index 0000000..9b4e709 +#endif +} + ++static const char * const bcm2708_compat[] = { ++ "brcm,bcm2708", ++ NULL ++}; ++ +MACHINE_START(BCM2708, "BCM2708") + /* Maintainer: Broadcom Europe Ltd. */ + .map_io = bcm2708_map_io, @@ -1127,6 +1270,7 @@ index 0000000..9b4e709 + .init_early = bcm2708_init_early, + .reserve = board_reserve, + .restart = bcm2708_restart, ++ .dt_compat = bcm2708_compat, +MACHINE_END + +module_param(boardrev, uint, 0644); @@ -1190,508 +1334,6 @@ index 0000000..e339a93 +} + +#endif -diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c -new file mode 100644 -index 0000000..4fc556e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/clock.c -@@ -0,0 +1,61 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clock.h" -+ -+int clk_enable(struct clk *clk) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(clk_enable); -+ -+void clk_disable(struct clk *clk) -+{ -+} -+EXPORT_SYMBOL(clk_disable); -+ -+unsigned long clk_get_rate(struct clk *clk) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_get_rate); -+ -+long clk_round_rate(struct clk *clk, unsigned long rate) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_round_rate); -+ -+int clk_set_rate(struct clk *clk, unsigned long rate) -+{ -+ return -EIO; -+} -+EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h -new file mode 100644 -index 0000000..5f9d725 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/clock.h -@@ -0,0 +1,24 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+struct module; -+ -+struct clk { -+ unsigned long rate; -+}; -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -new file mode 100644 -index 0000000..51d147a ---- /dev/null -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -0,0 +1,399 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/dma.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/*****************************************************************************\ -+ * * -+ * Configuration * -+ * * -+\*****************************************************************************/ -+ -+#define CACHE_LINE_MASK 31 -+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -+ -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -+ -+ -+/*****************************************************************************\ -+ * * -+ * DMA Auxilliary Functions * -+ * * -+\*****************************************************************************/ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+ -+extern int -+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void -+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+ -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int -+bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Device Methods * -+ * * -+\*****************************************************************************/ -+ -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+}; -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (chans) { -+ int chan = 0; -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ return chan; -+ } else -+ return -ENOMEM; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ else if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ else { -+ dmaman->chan_available |= (1 << chan); -+ return 0; -+ } -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA IRQs * -+ * * -+\*****************************************************************************/ -+ -+static unsigned char bcm_dma_irqs[] = { -+ IRQ_DMA0, -+ IRQ_DMA1, -+ IRQ_DMA2, -+ IRQ_DMA3, -+ IRQ_DMA4, -+ IRQ_DMA5, -+ IRQ_DMA6, -+ IRQ_DMA7, -+ IRQ_DMA8, -+ IRQ_DMA9, -+ IRQ_DMA10, -+ IRQ_DMA11, -+ IRQ_DMA12 -+}; -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Monitor * -+ * * -+\*****************************************************************************/ -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ if (!dmaman_dev) -+ return -ENODEV; -+ else { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (rc >= 0) { -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -+ rc); -+ *out_dma_irq = bcm_dma_irqs[rc]; -+ } -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ if (dmaman_dev) { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int dev_dmaman_register(const char *dev_name, struct device *dev) -+{ -+ int rc = dmaman_dev ? -EINVAL : 0; -+ dmaman_dev = dev; -+ return rc; -+} -+ -+static void dev_dmaman_deregister(const char *dev_name, struct device *dev) -+{ -+ dmaman_dev = NULL; -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA Device * -+ * * -+\*****************************************************************************/ -+ -+static int dmachans = -1; /* module parameter */ -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_dmaman *dmaman; -+ struct resource *dma_res = NULL; -+ void __iomem *dma_base = NULL; -+ int have_dma_region = 0; -+ -+ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -+ if (NULL == dmaman) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "DMA management memory\n"); -+ ret = -ENOMEM; -+ } else { -+ -+ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (dma_res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ } else if (!request_mem_region(dma_res->start, -+ resource_size(dma_res), -+ DRIVER_NAME)) { -+ dev_err(&pdev->dev, "cannot obtain DMA region\n"); -+ ret = -EBUSY; -+ } else { -+ have_dma_region = 1; -+ dma_base = ioremap(dma_res->start, -+ resource_size(dma_res)); -+ if (!dma_base) { -+ dev_err(&pdev->dev, "cannot map DMA region\n"); -+ ret = -ENOMEM; -+ } else { -+ /* use module parameter if one was provided */ -+ if (dmachans > 0) -+ vc_dmaman_init(dmaman, dma_base, -+ dmachans); -+ else -+ vc_dmaman_init(dmaman, dma_base, -+ DEFAULT_DMACHAN_BITMAP); -+ -+ platform_set_drvdata(pdev, dmaman); -+ dev_dmaman_register(DRIVER_NAME, &pdev->dev); -+ -+ printk(KERN_INFO DRIVER_NAME ": DMA manager " -+ "at %p\n", dma_base); -+ } -+ } -+ } -+ if (ret != 0) { -+ if (dma_base) -+ iounmap(dma_base); -+ if (dma_res && have_dma_region) -+ release_mem_region(dma_res->start, -+ resource_size(dma_res)); -+ if (dmaman) -+ kfree(dmaman); -+ } -+ return ret; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -+ kfree(dmaman); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_dmaman_driver = { -+ .probe = bcm_dmaman_probe, -+ .remove = bcm_dmaman_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+/*****************************************************************************\ -+ * * -+ * Driver init/exit * -+ * * -+\*****************************************************************************/ -+ -+static int __init bcm_dmaman_drv_init(void) -+{ -+ int ret; -+ -+ ret = platform_driver_register(&bcm_dmaman_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_dmaman_drv_exit(void) -+{ -+ platform_driver_unregister(&bcm_dmaman_driver); -+} -+ -+module_init(bcm_dmaman_drv_init); -+module_exit(bcm_dmaman_drv_exit); -+ -+module_param(dmachans, int, 0644); -+ -+MODULE_AUTHOR("Gray Girling "); -+MODULE_DESCRIPTION("DMA channel manager driver"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); diff --git a/arch/arm/mach-bcm2708/include/mach/arm_control.h b/arch/arm/mach-bcm2708/include/mach/arm_control.h new file mode 100644 index 0000000..a82bb92b @@ -2117,74 +1759,6 @@ index 0000000..a82bb92b +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h -new file mode 100644 -index 0000000..d3bf245 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/arm_power.h -@@ -0,0 +1,62 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _ARM_POWER_H -+#define _ARM_POWER_H -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/clkdev.h b/arch/arm/mach-bcm2708/include/mach/clkdev.h new file mode 100644 index 0000000..04b37a8 @@ -2226,100 +1800,6 @@ index 0000000..b24304a + .endm + +#include -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -new file mode 100644 -index 0000000..f2568d4 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -0,0 +1,88 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef _MACH_BCM2708_DMA_H -+#define _MACH_BCM2708_DMA_H -+ -+#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE (1 << 0) -+#define BCM2708_DMA_INT (1 << 2) -+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR (1 << 8) -+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN (1 << 0) -+#define BCM2708_DMA_TDMODE (1 << 1) -+#define BCM2708_DMA_WAIT_RESP (1 << 3) -+#define BCM2708_DMA_D_INC (1 << 4) -+#define BCM2708_DMA_D_WIDTH (1 << 5) -+#define BCM2708_DMA_D_DREQ (1 << 6) -+#define BCM2708_DMA_S_INC (1 << 8) -+#define BCM2708_DMA_S_WIDTH (1 << 9) -+#define BCM2708_DMA_S_DREQ (1 << 10) -+ -+#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block); -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_FAST (1< -+#include -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h new file mode 100644 index 0000000..2d0b821 @@ -3200,218 +2648,6 @@ index 0000000..d634813 + * nothing to do + */ +#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -new file mode 100644 -index 0000000..4a4a338 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#if !defined( VC_MEM_H ) -+#define VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -new file mode 100644 -index 0000000..8e11d67e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -0,0 +1,165 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vcio.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef _MACH_BCM2708_VCIO_H -+#define _MACH_BCM2708_VCIO_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); -+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); -+extern int /*rc*/ bcm_mailbox_property(void *data, int size); -+ -+#include -+ -+/* -+ * The major device number. We can't rely on dynamic -+ * registration any more, because ioctls need to know -+ * it. -+ */ -+#define MAJOR_NUM 100 -+ -+/* -+ * Set the message of the device driver -+ */ -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+/* -+ * _IOWR means that we're creating an ioctl command -+ * number for passing information from a user process -+ * to the kernel module and from the kernel module to user process -+ * -+ * The first arguments, MAJOR_NUM, is the major device -+ * number we're using. -+ * -+ * The second argument is the number of the command -+ * (there could be several with different meanings). -+ * -+ * The third argument is the type we want to get from -+ * the process to the kernel. -+ */ -+ -+/* -+ * The name of the device file -+ */ -+#define DEVICE_FILE_NAME "vcio" -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h new file mode 100644 index 0000000..502c617 @@ -3438,1370 +2674,12 @@ index 0000000..502c617 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -new file mode 100644 -index 0000000..2696be9 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/power.c -@@ -0,0 +1,197 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+ -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+arch_initcall(bcm_power_init); /* Initialize early */ -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -new file mode 100644 -index 0000000..2982af7 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -0,0 +1,431 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_ARCH_KONA -+#include -+#elif CONFIG_ARCH_BCM2708 -+#else -+#include -+#endif -+ -+#include "mach/vc_mem.h" -+#include -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -new file mode 100644 -index 0000000..5e43e85 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -0,0 +1,474 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -+#define SUPPORT_SYSRQ -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+ -+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* offsets from a mail box base address */ -+#define MAIL_WRT 0x00 /* write - and next 4 words */ -+#define MAIL_RD 0x00 /* read - and next 4 words */ -+#define MAIL_POL 0x10 /* read without popping the fifo */ -+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL_STA 0x18 /* status */ -+#define MAIL_CNF 0x1C /* configuration */ -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+struct vc_mailbox { -+ struct device *dev; /* parent device */ -+ void __iomem *status; -+ void __iomem *config; -+ void __iomem *read; -+ void __iomem *write; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -+ uint32_t addr_mbox) -+{ -+ int i; -+ -+ mbox_out->dev = dev; -+ mbox_out->status = __io_address(addr_mbox + MAIL_STA); -+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -+ mbox_out->read = __io_address(addr_mbox + MAIL_RD); -+ /* Write to the other mailbox */ -+ mbox_out->write = -+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -+ MAIL_WRT); -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ rc = 0; -+ } -+ return rc; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ rc = 0; -+ } -+ return rc; -+} -+ -+static irqreturn_t mbox_irq(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ int status = readl(mbox->status); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->read); -+ int chan = MBOX_CHAN(msg); -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ /* Overflow */ -+ printk(KERN_ERR DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ printk(KERN_ERR DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->status); -+ } -+ return ret; -+} -+ -+static struct irqaction mbox_irqaction = { -+ .name = "ARM Mailbox IRQ", -+ .flags = IRQF_DISABLED | IRQF_IRQPOLL, -+ .handler = mbox_irq, -+}; -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox Methods -+ * -------------------------------------------------------------------- */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_write(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_read(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static void dev_mbox_register(const char *dev_name, struct device *dev) -+{ -+ mbox_dev = dev; -+} -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)src < TASK_SIZE) -+ { -+ return copy_from_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)dst < TASK_SIZE) -+ { -+ return copy_to_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) { -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ } -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* ---------------------------------------------------------------------- -+ * Platform Device for Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static int Device_Open = 0; -+ -+/* -+ * This is called whenever a process attempts to open the device file -+ */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* -+ * We don't want to talk to two processes at the same time -+ */ -+ if (Device_Open) -+ return -EBUSY; -+ -+ Device_Open++; -+ /* -+ * Initialize the message -+ */ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * We're now ready for our next caller -+ */ -+ Device_Open--; -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -+ unsigned int ioctl_num, /* number and param for ioctl */ -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ /* -+ * Switch according to the ioctl called -+ */ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ break; -+ default: -+ printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_mailbox *mailbox; -+ -+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -+ if (NULL == mailbox) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ ret = -ENOMEM; -+ } else { -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ kfree(mailbox); -+ } else { -+ /* should be based on the registers from res really */ -+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -+ -+ platform_set_drvdata(pdev, mailbox); -+ dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ -+ mbox_irqaction.dev_id = mailbox; -+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); -+ } -+ } -+ -+ if (ret == 0) { -+ /* -+ * Register the character device -+ */ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ -+ /* -+ * Negative values signify an error -+ */ -+ if (ret < 0) { -+ printk(KERN_ERR DRIVER_NAME -+ "Failed registering the character device %d\n", ret); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ kfree(mailbox); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ -+ ret = platform_driver_register(&bcm_mbox_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm-mbox"); -diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 9b4f29e5..0c5d4ac 100644 ---- a/arch/arm/mm/Kconfig -+++ b/arch/arm/mm/Kconfig -@@ -358,7 +358,7 @@ config CPU_PJ4B - - # ARMv6 - config CPU_V6 -- bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX) -+ bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708) - select CPU_32v6 - select CPU_ABRT_EV6 - select CPU_CACHE_V6 -diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S -index d0390f4..a042de8 100644 ---- a/arch/arm/mm/proc-v6.S -+++ b/arch/arm/mm/proc-v6.S -@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) - * - * IRQs are already disabled. - */ -+ -+/* See jira SW-5991 for details of this workaround */ - ENTRY(cpu_v6_do_idle) -- mov r1, #0 -- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode -- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt -+ .align 5 -+ mov r1, #2 -+1: subs r1, #1 -+ nop -+ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode -+ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt -+ nop -+ nop -+ nop -+ bne 1b - ret lr - - ENTRY(cpu_v6_dcache_clean_area) -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index a10297d..c9ddd87 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,6 +522,7 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 -+bcm2708 MACH_BCM2708 BCM2708 3138 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 8d94c19..16ca535 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -84,7 +84,7 @@ struct vendor_data { - - static unsigned int get_fifosize_arm(struct amba_device *dev) - { -- return amba_rev(dev) < 3 ? 16 : 32; -+ return 16; //TODO: fix: amba_rev(dev) < 3 ? 16 : 32; - } - - static struct vendor_data vendor_arm = { -diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 0c8cbe5..c3b84a2 100644 ---- a/include/linux/mmc/host.h -+++ b/include/linux/mmc/host.h -@@ -291,6 +291,7 @@ struct mmc_host { - MMC_CAP2_HS400_1_2V) - #define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) - #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) -+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ - - mmc_pm_flag_t pm_caps; /* supported pm features */ - - -From 6763b931593e5ce8e1b5e45de482527d61390f56 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 7 May 2013 14:32:27 +0100 -Subject: [PATCH 002/216] Add 2709 platform for Raspberry Pi 2 - ---- - arch/arm/Kconfig | 21 + - arch/arm/Makefile | 1 + - arch/arm/kernel/head.S | 8 + - arch/arm/mach-bcm2709/Kconfig | 49 + - arch/arm/mach-bcm2709/Makefile | 7 + - arch/arm/mach-bcm2709/Makefile.boot | 3 + - arch/arm/mach-bcm2709/armctrl.c | 361 +++++++ - arch/arm/mach-bcm2709/armctrl.h | 27 + - arch/arm/mach-bcm2709/bcm2708_gpio.c | 426 ++++++++ - arch/arm/mach-bcm2709/bcm2709.c | 1263 ++++++++++++++++++++++ - arch/arm/mach-bcm2709/bcm2709.h | 49 + - arch/arm/mach-bcm2709/clock.c | 61 ++ - arch/arm/mach-bcm2709/clock.h | 24 + - arch/arm/mach-bcm2709/delay.S | 21 + - arch/arm/mach-bcm2709/dma.c | 409 +++++++ - arch/arm/mach-bcm2709/include/mach/arm_control.h | 493 +++++++++ - arch/arm/mach-bcm2709/include/mach/arm_power.h | 62 ++ - arch/arm/mach-bcm2709/include/mach/barriers.h | 3 + - arch/arm/mach-bcm2709/include/mach/clkdev.h | 7 + - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 + - arch/arm/mach-bcm2709/include/mach/dma.h | 94 ++ - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 +++ - arch/arm/mach-bcm2709/include/mach/frc.h | 38 + - arch/arm/mach-bcm2709/include/mach/gpio.h | 17 + - arch/arm/mach-bcm2709/include/mach/hardware.h | 28 + - arch/arm/mach-bcm2709/include/mach/io.h | 27 + - arch/arm/mach-bcm2709/include/mach/irqs.h | 225 ++++ - arch/arm/mach-bcm2709/include/mach/memory.h | 57 + - arch/arm/mach-bcm2709/include/mach/platform.h | 225 ++++ - arch/arm/mach-bcm2709/include/mach/power.h | 26 + - arch/arm/mach-bcm2709/include/mach/system.h | 38 + - arch/arm/mach-bcm2709/include/mach/timex.h | 23 + - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 ++ - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 + - arch/arm/mach-bcm2709/include/mach/vc_support.h | 69 ++ - arch/arm/mach-bcm2709/include/mach/vcio.h | 165 +++ - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 + - arch/arm/mach-bcm2709/power.c | 195 ++++ - arch/arm/mach-bcm2709/vc_mem.c | 431 ++++++++ - arch/arm/mach-bcm2709/vc_support.c | 318 ++++++ - arch/arm/mach-bcm2709/vcio.c | 474 ++++++++ - arch/arm/mm/proc-v7.S | 1 + - arch/arm/tools/mach-types | 1 + - drivers/clocksource/arm_arch_timer.c | 36 + - 44 files changed, 6067 insertions(+) - create mode 100644 arch/arm/mach-bcm2709/Kconfig - create mode 100644 arch/arm/mach-bcm2709/Makefile - create mode 100644 arch/arm/mach-bcm2709/Makefile.boot - create mode 100644 arch/arm/mach-bcm2709/armctrl.c - create mode 100644 arch/arm/mach-bcm2709/armctrl.h - create mode 100644 arch/arm/mach-bcm2709/bcm2708_gpio.c - create mode 100644 arch/arm/mach-bcm2709/bcm2709.c - create mode 100644 arch/arm/mach-bcm2709/bcm2709.h - create mode 100644 arch/arm/mach-bcm2709/clock.c - create mode 100644 arch/arm/mach-bcm2709/clock.h - create mode 100644 arch/arm/mach-bcm2709/delay.S - create mode 100644 arch/arm/mach-bcm2709/dma.c - create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_control.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_power.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/barriers.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/clkdev.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/dma.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/frc.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/gpio.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/hardware.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/irqs.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/power.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/timex.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - create mode 100755 arch/arm/mach-bcm2709/include/mach/vc_support.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vcio.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/power.c - create mode 100644 arch/arm/mach-bcm2709/vc_mem.c - create mode 100755 arch/arm/mach-bcm2709/vc_support.c - create mode 100644 arch/arm/mach-bcm2709/vcio.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 6876ae8..4018fea 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -793,6 +793,26 @@ config ARCH_OMAP1 - help - Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx) - -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select ARCH_HAS_BARRIERS if SMP -+ select CPU_V7 -+ select HAVE_SMP -+ select ARM_AMBA -+ select MIGHT_HAVE_CACHE_L2X0 -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MACH_BCM2709 -+ select VC4 -+ select FIQ -+# select ZONE_DMA -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - endchoice - - menu "Multiple platform selection" -@@ -984,6 +1004,7 @@ source "arch/arm/mach-vt8500/Kconfig" - - source "arch/arm/mach-w90x900/Kconfig" - source "arch/arm/mach-bcm2708/Kconfig" -+source "arch/arm/mach-bcm2709/Kconfig" - - source "arch/arm/mach-zynq/Kconfig" - -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 27c0f92..21ba7f3 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -147,6 +147,7 @@ machine-$(CONFIG_ARCH_AT91) += at91 - machine-$(CONFIG_ARCH_AXXIA) += axxia - machine-$(CONFIG_ARCH_BCM) += bcm - machine-$(CONFIG_ARCH_BCM2708) += bcm2708 -+machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_BERLIN) += berlin - machine-$(CONFIG_ARCH_CLPS711X) += clps711x - machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx -diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S -index 0196327..e4d6030 100644 ---- a/arch/arm/kernel/head.S -+++ b/arch/arm/kernel/head.S -@@ -680,6 +680,14 @@ ARM_BE8(rev16 ip, ip) - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - ret lr -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - #endif - ENDPROC(__fixup_a_pv_table) - diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig new file mode 100644 -index 0000000..4fb6e1b +index 0000000..d61ade0 --- /dev/null +++ b/arch/arm/mach-bcm2709/Kconfig -@@ -0,0 +1,49 @@ +@@ -0,0 +1,42 @@ +menu "Broadcom BCM2709 Implementations" + depends on ARCH_BCM2709 + @@ -4829,13 +2707,6 @@ index 0000000..4fb6e1b + help + Include support for the Broadcom(R) BCM2709 gpio. + -+config BCM2708_VCMEM -+ bool "Videocore Memory" -+ depends on MACH_BCM2709 -+ default y -+ help -+ Helper for videocore memory access and total size allocation. -+ +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" + depends on MACH_BCM2709 @@ -4853,17 +2724,16 @@ index 0000000..4fb6e1b +endmenu diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile new file mode 100644 -index 0000000..2a803bb +index 0000000..1ae8b80 --- /dev/null +++ b/arch/arm/mach-bcm2709/Makefile -@@ -0,0 +1,7 @@ +@@ -0,0 +1,6 @@ +# +# Makefile for the linux kernel. +# + -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o dma.o ++obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot new file mode 100644 index 0000000..67039c3 @@ -4875,7 +2745,7 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c new file mode 100644 -index 0000000..2815b64 +index 0000000..2fcfab9 --- /dev/null +++ b/arch/arm/mach-bcm2709/armctrl.c @@ -0,0 +1,361 @@ @@ -5230,7 +3100,7 @@ index 0000000..2815b64 + set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); + } else { + irq_set_chip_and_handler(irq, &armctrl_chip, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + irq_set_chip_data(irq, (void *)data); + } @@ -5275,7 +3145,7 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2709/bcm2708_gpio.c b/arch/arm/mach-bcm2709/bcm2708_gpio.c new file mode 100644 -index 0000000..c1e9254 +index 0000000..e33265d --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2708_gpio.c @@ -0,0 +1,426 @@ @@ -5587,7 +3457,7 @@ index 0000000..c1e9254 + +static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, +}; + @@ -5707,10 +3577,10 @@ index 0000000..c1e9254 +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c new file mode 100644 -index 0000000..f8679bb +index 0000000..19d0601 --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -0,0 +1,1263 @@ +@@ -0,0 +1,801 @@ +/* + * linux/arch/arm/mach-bcm2709/bcm2709.c + * @@ -5747,9 +3617,7 @@ index 0000000..f8679bb +#include +#include +#include -+#include +#include -+#include + +#include +#include @@ -5768,8 +3636,6 @@ index 0000000..f8679bb +#include + +#include -+#include -+#include +#include + +#include @@ -5795,19 +3661,12 @@ index 0000000..f8679bb + */ +#define DMA_MASK_BITS_COMMON 32 + -+// use GPIO 4 for the one-wire GPIO pin, if enabled -+#define W1_GPIO 4 -+// ensure one-wire GPIO pullup is disabled by default -+#define W1_PULLUP -1 -+ +/* command line parameters */ +static unsigned boardrev, serial; +static unsigned uart_clock = UART0_CLOCK; +static unsigned disk_led_gpio = 16; +static unsigned disk_led_active_low = 1; +static unsigned reboot_part = 0; -+static unsigned w1_gpio_pin = W1_GPIO; -+static unsigned w1_gpio_pullup = W1_PULLUP; + +static unsigned use_dt = 0; + @@ -5953,6 +3812,7 @@ index 0000000..f8679bb + bcm2709_register_clkdev(clk, "dev:f1"); + + clk = bcm2709_clk_register("sdhost_clk", 250000000); ++ bcm2709_register_clkdev(clk, "mmc-bcm2835.0"); + bcm2709_register_clkdev(clk, "bcm2708_spi.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.1"); @@ -5967,35 +3827,6 @@ index 0000000..f8679bb + &uart0_device, +}; + -+static struct resource bcm2708_dmaman_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_dmaman_device = { -+ .name = BCM_DMAMAN_DRIVER_NAME, -+ .id = 0, /* first bcm2708_dma */ -+ .resource = bcm2708_dmaman_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), -+}; -+ -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+static struct w1_gpio_platform_data w1_gpio_pdata = { -+ .pin = W1_GPIO, -+ .ext_pullup_enable_pin = W1_PULLUP, -+ .is_open_drain = 0, -+}; -+ -+static struct platform_device w1_device = { -+ .name = "w1-gpio", -+ .id = -1, -+ .dev.platform_data = &w1_gpio_pdata, -+}; -+#endif -+ +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { @@ -6009,27 +3840,6 @@ index 0000000..f8679bb + }, +}; + -+static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -+ { -+ .mapbase = UART1_BASE + 0x40, -+ .irq = IRQ_AUX, -+ .uartclk = 125000000, -+ .regshift = 2, -+ .iotype = UPIO_MEM, -+ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_8250, -+ }, -+ {}, -+}; -+ -+static struct platform_device bcm2708_uart1_device = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = bcm2708_uart1_platform_data, -+ }, -+}; -+ +static struct resource bcm2708_usb_resources[] = { + [0] = { + .start = USB_BASE, @@ -6078,17 +3888,21 @@ index 0000000..f8679bb +}; + +static struct resource bcm2708_vcio_resources[] = { -+ [0] = { /* mailbox/semaphore/doorbell access */ -+ .start = MCORE_BASE, -+ .end = MCORE_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ { ++ .start = ARMCTRL_0_MAIL0_BASE, ++ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_MAILBOX, ++ .end = IRQ_ARM_MAILBOX, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { -+ .name = BCM_VCIO_DRIVER_NAME, ++ .name = "bcm2708_vcio", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), @@ -6098,360 +3912,6 @@ index 0000000..f8679bb + }, +}; + -+#ifdef CONFIG_BCM2708_GPIO -+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" -+ -+static struct resource bcm2708_gpio_resources[] = { -+ [0] = { /* general purpose I/O */ -+ .start = GPIO_BASE, -+ .end = GPIO_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_gpio_device = { -+ .name = BCM_GPIO_DRIVER_NAME, -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_gpio_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), -+ .dev = { -+ .dma_mask = &gpio_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+#endif -+ -+#ifdef SYSTEM_TIMER -+static struct resource bcm2708_systemtimer_resources[] = { -+ [0] = { /* system timer access */ -+ .start = ST_BASE, -+ .end = ST_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IRQ_TIMER3, -+ .end = IRQ_TIMER3, -+ .flags = IORESOURCE_IRQ, -+ } -+ -+}; -+ -+static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_systemtimer_device = { -+ .name = "bcm2708_systemtimer", -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_systemtimer_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -+ .dev = { -+ .dma_mask = &systemtimer_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+#endif -+ -+#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ -+static struct resource bcm2835_emmc_resources[] = { -+ [0] = { -+ .start = EMMC_BASE, -+ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ -+ /* the memory map actually makes SZ_4K available */ -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_ARASANSDIO, -+ .end = IRQ_ARASANSDIO, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 bcm2835_emmc_dmamask = 0xffffffffUL; -+ -+struct platform_device bcm2835_emmc_device = { -+ .name = "mmc-bcm2835", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), -+ .resource = bcm2835_emmc_resources, -+ .dev = { -+ .dma_mask = &bcm2835_emmc_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+#endif /* CONFIG_MMC_BCM2835 */ -+ -+static struct resource bcm2708_powerman_resources[] = { -+ [0] = { -+ .start = PM_BASE, -+ .end = PM_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+struct platform_device bcm2708_powerman_device = { -+ .name = "bcm2708_powerman", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -+ .resource = bcm2708_powerman_resources, -+ .dev = { -+ .dma_mask = &powerman_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+ -+ -+static struct platform_device bcm2708_alsa_devices[] = { -+ [0] = { -+ .name = "bcm2835_AUD0", -+ .id = 0, /* first audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [1] = { -+ .name = "bcm2835_AUD1", -+ .id = 1, /* second audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [2] = { -+ .name = "bcm2835_AUD2", -+ .id = 2, /* third audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [3] = { -+ .name = "bcm2835_AUD3", -+ .id = 3, /* forth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [4] = { -+ .name = "bcm2835_AUD4", -+ .id = 4, /* fifth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [5] = { -+ .name = "bcm2835_AUD5", -+ .id = 5, /* sixth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [6] = { -+ .name = "bcm2835_AUD6", -+ .id = 6, /* seventh audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [7] = { -+ .name = "bcm2835_AUD7", -+ .id = 7, /* eighth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+}; -+ -+static struct resource bcm2708_spi_resources[] = { -+ { -+ .start = SPI0_BASE, -+ .end = SPI0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_SPI, -+ .end = IRQ_SPI, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+ -+static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+static struct platform_device bcm2708_spi_device = { -+ .name = "bcm2708_spi", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_spi_resources), -+ .resource = bcm2708_spi_resources, -+ .dev = { -+ .dma_mask = &bcm2708_spi_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, -+}; -+ -+#ifdef CONFIG_BCM2708_SPIDEV -+static struct spi_board_info bcm2708_spi_devices[] = { -+#ifdef CONFIG_SPI_SPIDEV -+ { -+ .modalias = "spidev", -+ .max_speed_hz = 500000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = SPI_MODE_0, -+ }, { -+ .modalias = "spidev", -+ .max_speed_hz = 500000, -+ .bus_num = 0, -+ .chip_select = 1, -+ .mode = SPI_MODE_0, -+ } -+#endif -+}; -+#endif -+ -+static struct resource bcm2708_bsc0_resources[] = { -+ { -+ .start = BSC0_BASE, -+ .end = BSC0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc0_device = { -+ .name = "bcm2708_i2c", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), -+ .resource = bcm2708_bsc0_resources, -+}; -+ -+ -+static struct resource bcm2708_bsc1_resources[] = { -+ { -+ .start = BSC1_BASE, -+ .end = BSC1_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc1_device = { -+ .name = "bcm2708_i2c", -+ .id = 1, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), -+ .resource = bcm2708_bsc1_resources, -+}; -+ -+static struct platform_device bcm2835_hwmon_device = { -+ .name = "bcm2835_hwmon", -+}; -+ -+static struct platform_device bcm2835_thermal_device = { -+ .name = "bcm2835_thermal", -+}; -+ -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+static struct resource bcm2708_i2s_resources[] = { -+ { -+ .start = I2S_BASE, -+ .end = I2S_BASE + 0x20, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = PCM_CLOCK_BASE, -+ .end = PCM_CLOCK_BASE + 0x02, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_i2s_device = { -+ .name = "bcm2708-i2s", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), -+ .resource = bcm2708_i2s_resources, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+static struct platform_device snd_hifiberry_dac_device = { -+ .name = "snd-hifiberry-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm5102a_codec_device = { -+ .name = "pcm5102a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+static struct platform_device snd_rpi_hifiberry_dacplus_device = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4d) -+ }, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+static struct platform_device snd_hifiberry_digi_device = { -+ .name = "snd-hifiberry-digi", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("wm8804", 0x3b) -+ }, -+}; -+ -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+static struct platform_device snd_hifiberry_amp_device = { -+ .name = "snd-hifiberry-amp", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("tas5713", 0x1b) -+ }, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+static struct platform_device snd_rpi_dac_device = { -+ .name = "snd-rpi-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm1794a_codec_device = { -+ .name = "pcm1794a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+static struct platform_device snd_rpi_iqaudio_dac_device = { -+ .name = "snd-rpi-iqaudio-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+// Use the actual device name rather than generic driver name -+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4c) -+ }, -+}; -+#endif -+ +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; @@ -6539,6 +3999,17 @@ index 0000000..f8679bb + } +} + ++static void __init bcm2709_init_uart1(void) ++{ ++ struct device_node *np; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); ++ if (of_device_is_available(np)) { ++ pr_info("bcm2709: Mini UART enabled\n"); ++ writel(1, __io_address(UART1_BASE + 0x4)); ++ } ++} ++ +#ifdef CONFIG_OF +static void __init bcm2709_dt_init(void) +{ @@ -6570,85 +4041,24 @@ index 0000000..f8679bb + bcm2709_init_clocks(); + bcm2709_dt_init(); + -+ bcm_register_device(&bcm2708_dmaman_device); + bcm_register_device(&bcm2708_vcio_device); +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +#endif -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+ w1_gpio_pdata.pin = w1_gpio_pin; -+ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -+ bcm_register_device_dt(&w1_device); -+#endif -+#ifdef SYSTEM_TIMER -+ bcm_register_device(&bcm2708_systemtimer_device); -+#endif -+ bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device(&bcm2708_uart1_device); -+ bcm_register_device(&bcm2708_powerman_device); ++ bcm_register_device_dt(&bcm2708_fb_device); ++ bcm_register_device_dt(&bcm2708_usb_device); + -+#ifdef CONFIG_MMC_BCM2835 -+ bcm_register_device(&bcm2835_emmc_device); -+#endif -+ bcm2709_init_led(); -+ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -+ bcm_register_device(&bcm2708_alsa_devices[i]); ++ bcm2708_init_led(); ++ bcm2708_init_uart1(); + -+ bcm_register_device_dt(&bcm2708_spi_device); -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ bcm_register_device(&bcm2835_hwmon_device); -+ bcm_register_device(&bcm2835_thermal_device); -+ -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+ bcm_register_device_dt(&bcm2708_i2s_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_dac_device); -+ bcm_register_device_dt(&snd_pcm5102a_codec_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_digi_device); -+ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_amp_device); -+ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_dac_device); -+ bcm_register_device_dt(&snd_pcm1794a_codec_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); -+#endif -+ -+ -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); ++ if (!use_dt) { ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } + } + system_rev = boardrev; + system_serial_low = serial; -+ -+#ifdef CONFIG_BCM2708_SPIDEV -+ if (!use_dt) -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); -+#endif +} + +#ifdef SYSTEM_TIMER @@ -6972,8 +4382,6 @@ index 0000000..f8679bb +module_param(disk_led_gpio, uint, 0644); +module_param(disk_led_active_low, uint, 0644); +module_param(reboot_part, uint, 0644); -+module_param(w1_gpio_pin, uint, 0644); -+module_param(w1_gpio_pullup, uint, 0644); diff --git a/arch/arm/mach-bcm2709/bcm2709.h b/arch/arm/mach-bcm2709/bcm2709.h new file mode 100644 index 0000000..e339a93 @@ -7029,103 +4437,6 @@ index 0000000..e339a93 +} + +#endif -diff --git a/arch/arm/mach-bcm2709/clock.c b/arch/arm/mach-bcm2709/clock.c -new file mode 100644 -index 0000000..4fc556e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/clock.c -@@ -0,0 +1,61 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clock.h" -+ -+int clk_enable(struct clk *clk) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(clk_enable); -+ -+void clk_disable(struct clk *clk) -+{ -+} -+EXPORT_SYMBOL(clk_disable); -+ -+unsigned long clk_get_rate(struct clk *clk) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_get_rate); -+ -+long clk_round_rate(struct clk *clk, unsigned long rate) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_round_rate); -+ -+int clk_set_rate(struct clk *clk, unsigned long rate) -+{ -+ return -EIO; -+} -+EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2709/clock.h b/arch/arm/mach-bcm2709/clock.h -new file mode 100644 -index 0000000..5f9d725 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/clock.h -@@ -0,0 +1,24 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+struct module; -+ -+struct clk { -+ unsigned long rate; -+}; diff --git a/arch/arm/mach-bcm2709/delay.S b/arch/arm/mach-bcm2709/delay.S new file mode 100644 index 0000000..06f4780 @@ -7153,421 +4464,6 @@ index 0000000..06f4780 + bhi bcm2708_delay + mov pc, lr +ENDPROC(bcm2708_delay) -diff --git a/arch/arm/mach-bcm2709/dma.c b/arch/arm/mach-bcm2709/dma.c -new file mode 100644 -index 0000000..a5e58d1 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/dma.c -@@ -0,0 +1,409 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/dma.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/*****************************************************************************\ -+ * * -+ * Configuration * -+ * * -+\*****************************************************************************/ -+ -+#define CACHE_LINE_MASK 31 -+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -+ -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -+ -+ -+/*****************************************************************************\ -+ * * -+ * DMA Auxilliary Functions * -+ * * -+\*****************************************************************************/ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+ -+extern int -+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void -+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+ -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int -+bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Device Methods * -+ * * -+\*****************************************************************************/ -+ -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+}; -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (chans) { -+ int chan = 0; -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ return chan; -+ } else -+ return -ENOMEM; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ else if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ else { -+ dmaman->chan_available |= (1 << chan); -+ return 0; -+ } -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA IRQs * -+ * * -+\*****************************************************************************/ -+ -+static unsigned char bcm_dma_irqs[] = { -+ IRQ_DMA0, -+ IRQ_DMA1, -+ IRQ_DMA2, -+ IRQ_DMA3, -+ IRQ_DMA4, -+ IRQ_DMA5, -+ IRQ_DMA6, -+ IRQ_DMA7, -+ IRQ_DMA8, -+ IRQ_DMA9, -+ IRQ_DMA10, -+ IRQ_DMA11, -+ IRQ_DMA12 -+}; -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Monitor * -+ * * -+\*****************************************************************************/ -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ if (!dmaman_dev) -+ return -ENODEV; -+ else { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (rc >= 0) { -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -+ rc); -+ *out_dma_irq = bcm_dma_irqs[rc]; -+ } -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ if (dmaman_dev) { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int dev_dmaman_register(const char *dev_name, struct device *dev) -+{ -+ int rc = dmaman_dev ? -EINVAL : 0; -+ dmaman_dev = dev; -+ return rc; -+} -+ -+static void dev_dmaman_deregister(const char *dev_name, struct device *dev) -+{ -+ dmaman_dev = NULL; -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA Device * -+ * * -+\*****************************************************************************/ -+ -+static int dmachans = -1; /* module parameter */ -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_dmaman *dmaman; -+ struct resource *dma_res = NULL; -+ void __iomem *dma_base = NULL; -+ int have_dma_region = 0; -+ -+ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -+ if (NULL == dmaman) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "DMA management memory\n"); -+ ret = -ENOMEM; -+ } else { -+ -+ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (dma_res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ } else if (!request_mem_region(dma_res->start, -+ resource_size(dma_res), -+ DRIVER_NAME)) { -+ dev_err(&pdev->dev, "cannot obtain DMA region\n"); -+ ret = -EBUSY; -+ } else { -+ have_dma_region = 1; -+ dma_base = ioremap(dma_res->start, -+ resource_size(dma_res)); -+ if (!dma_base) { -+ dev_err(&pdev->dev, "cannot map DMA region\n"); -+ ret = -ENOMEM; -+ } else { -+ /* use module parameter if one was provided */ -+ if (dmachans > 0) -+ vc_dmaman_init(dmaman, dma_base, -+ dmachans); -+ else -+ vc_dmaman_init(dmaman, dma_base, -+ DEFAULT_DMACHAN_BITMAP); -+ -+ platform_set_drvdata(pdev, dmaman); -+ dev_dmaman_register(DRIVER_NAME, &pdev->dev); -+ -+ printk(KERN_INFO DRIVER_NAME ": DMA manager " -+ "at %p\n", dma_base); -+ } -+ } -+ } -+ if (ret != 0) { -+ if (dma_base) -+ iounmap(dma_base); -+ if (dma_res && have_dma_region) -+ release_mem_region(dma_res->start, -+ resource_size(dma_res)); -+ if (dmaman) -+ kfree(dmaman); -+ } -+ return ret; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -+ kfree(dmaman); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_dmaman_driver = { -+ .probe = bcm_dmaman_probe, -+ .remove = bcm_dmaman_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+/*****************************************************************************\ -+ * * -+ * Driver init/exit * -+ * * -+\*****************************************************************************/ -+ -+static int __init bcm_dmaman_drv_init(void) -+{ -+ int ret; -+ -+ ret = platform_driver_register(&bcm_dmaman_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_dmaman_drv_exit(void) -+{ -+ platform_driver_unregister(&bcm_dmaman_driver); -+} -+ -+module_init(bcm_dmaman_drv_init); -+module_exit(bcm_dmaman_drv_exit); -+ -+module_param(dmachans, int, 0644); -+ -+MODULE_AUTHOR("Gray Girling "); -+MODULE_DESCRIPTION("DMA channel manager driver"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); diff --git a/arch/arm/mach-bcm2709/include/mach/arm_control.h b/arch/arm/mach-bcm2709/include/mach/arm_control.h new file mode 100644 index 0000000..e346caf @@ -8067,74 +4963,6 @@ index 0000000..e346caf +#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) + +#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/arm_power.h b/arch/arm/mach-bcm2709/include/mach/arm_power.h -new file mode 100644 -index 0000000..d3bf245 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/arm_power.h -@@ -0,0 +1,62 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _ARM_POWER_H -+#define _ARM_POWER_H -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/barriers.h b/arch/arm/mach-bcm2709/include/mach/barriers.h new file mode 100644 index 0000000..723cdad @@ -8185,106 +5013,6 @@ index 0000000..b24304a + .endm + +#include -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -new file mode 100644 -index 0000000..d03e7b5 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/dma.h -@@ -0,0 +1,94 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef _MACH_BCM2708_DMA_H -+#define _MACH_BCM2708_DMA_H -+ -+#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE (1 << 0) -+#define BCM2708_DMA_INT (1 << 2) -+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR (1 << 8) -+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN (1 << 0) -+#define BCM2708_DMA_TDMODE (1 << 1) -+#define BCM2708_DMA_WAIT_RESP (1 << 3) -+#define BCM2708_DMA_D_INC (1 << 4) -+#define BCM2708_DMA_D_WIDTH (1 << 5) -+#define BCM2708_DMA_D_DREQ (1 << 6) -+#define BCM2708_DMA_S_INC (1 << 8) -+#define BCM2708_DMA_S_WIDTH (1 << 9) -+#define BCM2708_DMA_S_DREQ (1 << 10) -+ -+#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+struct scatterlist; -+ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block); -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); -+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 -+#define BCM_DMA_FEATURE_FAST (1< -+#include -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h new file mode 100644 index 0000000..2d0b821 @@ -9384,177 +6080,6 @@ index 0000000..70e809f + unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5); + +#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/vcio.h b/arch/arm/mach-bcm2709/include/mach/vcio.h -new file mode 100644 -index 0000000..8e11d67e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vcio.h -@@ -0,0 +1,165 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vcio.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef _MACH_BCM2708_VCIO_H -+#define _MACH_BCM2708_VCIO_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); -+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); -+extern int /*rc*/ bcm_mailbox_property(void *data, int size); -+ -+#include -+ -+/* -+ * The major device number. We can't rely on dynamic -+ * registration any more, because ioctls need to know -+ * it. -+ */ -+#define MAJOR_NUM 100 -+ -+/* -+ * Set the message of the device driver -+ */ -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+/* -+ * _IOWR means that we're creating an ioctl command -+ * number for passing information from a user process -+ * to the kernel module and from the kernel module to user process -+ * -+ * The first arguments, MAJOR_NUM, is the major device -+ * number we're using. -+ * -+ * The second argument is the number of the command -+ * (there could be several with different meanings). -+ * -+ * The third argument is the type we want to get from -+ * the process to the kernel. -+ */ -+ -+/* -+ * The name of the device file -+ */ -+#define DEVICE_FILE_NAME "vcio" -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h new file mode 100644 index 0000000..6aa6826 @@ -9581,210 +6106,9 @@ index 0000000..6aa6826 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xff000000) -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -new file mode 100644 -index 0000000..3421057 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/power.c -@@ -0,0 +1,195 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+arch_initcall(bcm_power_init); /* Initialize early */ -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c new file mode 100644 -index 0000000..ac578db +index 0000000..d2adfd1 --- /dev/null +++ b/arch/arm/mach-bcm2709/vc_mem.c @@ -0,0 +1,431 @@ @@ -9812,6 +6136,7 @@ index 0000000..ac578db +#include +#include +#include ++#include + +#ifdef CONFIG_ARCH_KONA +#include @@ -9821,7 +6146,6 @@ index 0000000..ac578db +#endif + +#include "mach/vc_mem.h" -+#include + +#define DRIVER_NAME "vc-mem" + @@ -10220,8 +6544,8 @@ index 0000000..ac578db +module_param(mem_size, uint, 0644); +module_param(mem_base, uint, 0644); diff --git a/arch/arm/mach-bcm2709/vc_support.c b/arch/arm/mach-bcm2709/vc_support.c -new file mode 100755 -index 0000000..0bc41c4 +new file mode 100644 +index 0000000..c4dc7d6 --- /dev/null +++ b/arch/arm/mach-bcm2709/vc_support.c @@ -0,0 +1,318 @@ @@ -10233,7 +6557,7 @@ index 0000000..0bc41c4 + */ + +#include -+#include ++#include + +#ifdef ECLIPSE_IGNORE + @@ -10543,491 +6867,51 @@ index 0000000..0bc41c4 + return 1; + } +} -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -new file mode 100644 -index 0000000..5e43e85 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/vcio.c -@@ -0,0 +1,474 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -+#define SUPPORT_SYSRQ -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+ -+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* offsets from a mail box base address */ -+#define MAIL_WRT 0x00 /* write - and next 4 words */ -+#define MAIL_RD 0x00 /* read - and next 4 words */ -+#define MAIL_POL 0x10 /* read without popping the fifo */ -+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL_STA 0x18 /* status */ -+#define MAIL_CNF 0x1C /* configuration */ -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+struct vc_mailbox { -+ struct device *dev; /* parent device */ -+ void __iomem *status; -+ void __iomem *config; -+ void __iomem *read; -+ void __iomem *write; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -+ uint32_t addr_mbox) -+{ -+ int i; -+ -+ mbox_out->dev = dev; -+ mbox_out->status = __io_address(addr_mbox + MAIL_STA); -+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -+ mbox_out->read = __io_address(addr_mbox + MAIL_RD); -+ /* Write to the other mailbox */ -+ mbox_out->write = -+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -+ MAIL_WRT); -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ rc = 0; -+ } -+ return rc; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ rc = 0; -+ } -+ return rc; -+} -+ -+static irqreturn_t mbox_irq(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ int status = readl(mbox->status); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->read); -+ int chan = MBOX_CHAN(msg); -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ /* Overflow */ -+ printk(KERN_ERR DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ printk(KERN_ERR DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->status); -+ } -+ return ret; -+} -+ -+static struct irqaction mbox_irqaction = { -+ .name = "ARM Mailbox IRQ", -+ .flags = IRQF_DISABLED | IRQF_IRQPOLL, -+ .handler = mbox_irq, -+}; -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox Methods -+ * -------------------------------------------------------------------- */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_write(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_read(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static void dev_mbox_register(const char *dev_name, struct device *dev) -+{ -+ mbox_dev = dev; -+} -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)src < TASK_SIZE) -+ { -+ return copy_from_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)dst < TASK_SIZE) -+ { -+ return copy_to_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) { -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ } -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* ---------------------------------------------------------------------- -+ * Platform Device for Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static int Device_Open = 0; -+ -+/* -+ * This is called whenever a process attempts to open the device file -+ */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* -+ * We don't want to talk to two processes at the same time -+ */ -+ if (Device_Open) -+ return -EBUSY; -+ -+ Device_Open++; -+ /* -+ * Initialize the message -+ */ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * We're now ready for our next caller -+ */ -+ Device_Open--; -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -+ unsigned int ioctl_num, /* number and param for ioctl */ -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ /* -+ * Switch according to the ioctl called -+ */ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ break; -+ default: -+ printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_mailbox *mailbox; -+ -+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -+ if (NULL == mailbox) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ ret = -ENOMEM; -+ } else { -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ kfree(mailbox); -+ } else { -+ /* should be based on the registers from res really */ -+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -+ -+ platform_set_drvdata(pdev, mailbox); -+ dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ -+ mbox_irqaction.dev_id = mailbox; -+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); -+ } -+ } -+ -+ if (ret == 0) { -+ /* -+ * Register the character device -+ */ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ -+ /* -+ * Negative values signify an error -+ */ -+ if (ret < 0) { -+ printk(KERN_ERR DRIVER_NAME -+ "Failed registering the character device %d\n", ret); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ kfree(mailbox); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ -+ ret = platform_driver_register(&bcm_mbox_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm-mbox"); +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index b4f92b9..bb263d8 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -358,7 +358,7 @@ config CPU_PJ4B + + # ARMv6 + config CPU_V6 +- bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX) ++ bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708) + select CPU_32v6 + select CPU_ABRT_EV6 + select CPU_CACHE_V6 +diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S +index 06d890a..30d96e8 100644 +--- a/arch/arm/mm/proc-v6.S ++++ b/arch/arm/mm/proc-v6.S +@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) + * + * IRQs are already disabled. + */ ++ ++/* See jira SW-5991 for details of this workaround */ + ENTRY(cpu_v6_do_idle) +- mov r1, #0 +- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode +- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ .align 5 ++ mov r1, #2 ++1: subs r1, #1 ++ nop ++ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode ++ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ nop ++ nop ++ nop ++ bne 1b + ret lr + + ENTRY(cpu_v6_dcache_clean_area) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S -index 8b4ee5e..80fa74b 100644 +index 3d1054f..7615bbf 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S -@@ -441,6 +441,7 @@ __v7_setup: +@@ -456,6 +456,7 @@ __v7_setup: orr r0, r0, r6 @ set them THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions ret lr @ return to head.S:__ret @@ -11036,25 +6920,26 @@ index 8b4ee5e..80fa74b 100644 .align 2 diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index c9ddd87..bfc397c 100644 +index 2ed1b8a..b52d949 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types -@@ -523,6 +523,7 @@ prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 +@@ -522,6 +522,8 @@ torbreck MACH_TORBRECK TORBRECK 3090 + prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 - bcm2708 MACH_BCM2708 BCM2708 3138 ++bcm2708 MACH_BCM2708 BCM2708 3138 +bcm2709 MACH_BCM2709 BCM2709 3139 ag5evm MACH_AG5EVM AG5EVM 3189 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c -index a3025e7..4a2a601 100644 +index 0aa135d..89dbcb9 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c -@@ -804,3 +804,39 @@ static void __init arch_timer_mem_init(struct device_node *np) +@@ -882,3 +882,39 @@ void __init acpi_generic_timer_init(void) + acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); } - CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", - arch_timer_mem_init); + #endif + +int __init dc4_arch_timer_init(void) +{ @@ -11091,11 +6976,396 @@ index a3025e7..4a2a601 100644 + arch_timer_common_init(); + return 0; +} +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 763eb20..ad45801 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -85,7 +85,7 @@ struct vendor_data { + + static unsigned int get_fifosize_arm(struct amba_device *dev) + { +- return amba_rev(dev) < 3 ? 16 : 32; ++ return 16; //TODO: fix: amba_rev(dev) < 3 ? 16 : 32; + } + + static struct vendor_data vendor_arm = { +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index b5bedae..b0258e8 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -285,6 +285,7 @@ struct mmc_host { + MMC_CAP2_HS400_1_2V) + #define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) + #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) ++#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ + + mmc_pm_flag_t pm_caps; /* supported pm features */ + -From ade70caa2a108d3a2257a32ce6873758ae968f97 Mon Sep 17 00:00:00 2001 +From aa090a771afa15310eb10d3209c190441f3ecefd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 16 Jun 2015 23:48:09 +0100 +Subject: [PATCH 02/77] power: Add power driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +BCM270x: power: Change initcall level to subsys + +Load ordering of modules are determined by the initcall used. +If it's the same initcall level, makefile ordering decides. +Now that the mailbox driver is being moved, it's no longer +placed before the power driver by the linker. +So use a later initcall level to let the mailbox driver +load first. + +Signed-off-by: Noralf Trønnes + +BCM270x: Move power module + +Make the power module available on ARCH_BCM2835 by moving it. +The module turns on USB power making it possible to boot +ARCH_BCM2835 directly with the VC bootloader. + +Signed-off-by: Noralf Trønnes +--- + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/bcm2835/Kconfig | 9 ++ + drivers/soc/bcm2835/Makefile | 1 + + drivers/soc/bcm2835/bcm2708-power.c | 200 ++++++++++++++++++++++++++++++++++++ + include/soc/bcm2835/power.h | 61 +++++++++++ + 6 files changed, 273 insertions(+) + create mode 100644 drivers/soc/bcm2835/Kconfig + create mode 100644 drivers/soc/bcm2835/Makefile + create mode 100644 drivers/soc/bcm2835/bcm2708-power.c + create mode 100644 include/soc/bcm2835/power.h + +diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig +index d8bde82..595c9cd 100644 +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -1,5 +1,6 @@ + menu "SOC (System On Chip) specific Drivers" + ++source "drivers/soc/bcm2835/Kconfig" + source "drivers/soc/mediatek/Kconfig" + source "drivers/soc/qcom/Kconfig" + source "drivers/soc/ti/Kconfig" +diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile +index 70042b2..9ad449c 100644 +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -2,6 +2,7 @@ + # Makefile for the Linux Kernel SOC specific device drivers. + # + ++obj-y += bcm2835/ + obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ + obj-$(CONFIG_ARCH_QCOM) += qcom/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ +diff --git a/drivers/soc/bcm2835/Kconfig b/drivers/soc/bcm2835/Kconfig +new file mode 100644 +index 0000000..c2980f3 +--- /dev/null ++++ b/drivers/soc/bcm2835/Kconfig +@@ -0,0 +1,9 @@ ++# ++# BCM2835 Soc drivers ++# ++config BCM2708_POWER ++ tristate "BCM2708 legacy power driver" ++ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX ++ default y ++ help ++ Turns on USB power and provides an API for controlling power. +diff --git a/drivers/soc/bcm2835/Makefile b/drivers/soc/bcm2835/Makefile +new file mode 100644 +index 0000000..3614ad9 +--- /dev/null ++++ b/drivers/soc/bcm2835/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_BCM2708_POWER) += bcm2708-power.o +diff --git a/drivers/soc/bcm2835/bcm2708-power.c b/drivers/soc/bcm2835/bcm2708-power.c +new file mode 100644 +index 0000000..e7931a9 +--- /dev/null ++++ b/drivers/soc/bcm2835/bcm2708-power.c +@@ -0,0 +1,200 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/power.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "bcm2708_power" ++ ++#define BCM_POWER_MAXCLIENTS 4 ++#define BCM_POWER_NOCLIENT (1<<31) ++ ++/* Some drivers expect there devices to be permanently powered */ ++ ++#ifdef CONFIG_USB ++#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) ++#endif ++ ++#if 1 ++#define DPRINTK printk ++#else ++#define DPRINTK if (0) printk ++#endif ++ ++struct state_struct { ++ uint32_t global_request; ++ uint32_t client_request[BCM_POWER_MAXCLIENTS]; ++ struct semaphore client_mutex; ++ struct semaphore mutex; ++} g_state; ++ ++int bcm_power_open(BCM_POWER_HANDLE_T *handle) ++{ ++ BCM_POWER_HANDLE_T i; ++ int ret = -EBUSY; ++ ++ down(&g_state.client_mutex); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { ++ g_state.client_request[i] = BCM_POWER_NONE; ++ *handle = i; ++ ret = 0; ++ break; ++ } ++ } ++ ++ up(&g_state.client_mutex); ++ ++ DPRINTK("bcm_power_open() -> %d\n", *handle); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(bcm_power_open); ++ ++int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) ++{ ++ int rc = 0; ++ ++ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); ++ ++ if ((handle < BCM_POWER_MAXCLIENTS) && ++ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { ++ if (down_interruptible(&g_state.mutex) != 0) { ++ DPRINTK("bcm_power_request -> interrupted\n"); ++ return -EINTR; ++ } ++ ++ if (request != g_state.client_request[handle]) { ++ uint32_t others_request = 0; ++ uint32_t global_request; ++ BCM_POWER_HANDLE_T i; ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (i != handle) ++ others_request |= ++ g_state.client_request[i]; ++ } ++ others_request &= ~BCM_POWER_NOCLIENT; ++ ++ global_request = request | others_request; ++ if (global_request != g_state.global_request) { ++ uint32_t actual; ++ ++ /* Send a request to VideoCore */ ++ bcm_mailbox_write(MBOX_CHAN_POWER, ++ global_request << 4); ++ ++ /* Wait for a response during power-up */ ++ if (global_request & ~g_state.global_request) { ++ rc = bcm_mailbox_read(MBOX_CHAN_POWER, ++ &actual); ++ DPRINTK ++ ("bcm_mailbox_read -> %08x, %d\n", ++ actual, rc); ++ actual >>= 4; ++ } else { ++ rc = 0; ++ actual = global_request; ++ } ++ ++ if (rc == 0) { ++ if (actual != global_request) { ++ printk(KERN_ERR ++ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", ++ __func__, ++ g_state.global_request, ++ global_request, actual, request, others_request); ++ /* A failure */ ++ BUG_ON((others_request & actual) ++ != others_request); ++ request &= actual; ++ rc = -EIO; ++ } ++ ++ g_state.global_request = actual; ++ g_state.client_request[handle] = ++ request; ++ } ++ } ++ } ++ up(&g_state.mutex); ++ } else { ++ rc = -EINVAL; ++ } ++ DPRINTK("bcm_power_request -> %d\n", rc); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_request); ++ ++int bcm_power_close(BCM_POWER_HANDLE_T handle) ++{ ++ int rc; ++ ++ DPRINTK("bcm_power_close(%d)\n", handle); ++ ++ rc = bcm_power_request(handle, BCM_POWER_NONE); ++ if (rc == 0) ++ g_state.client_request[handle] = BCM_POWER_NOCLIENT; ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_close); ++ ++static int __init bcm_power_init(void) ++{ ++#if defined(BCM_POWER_ALWAYS_ON) ++ BCM_POWER_HANDLE_T always_on_handle; ++#endif ++ int rc = 0; ++ int i; ++ ++ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); ++ bcm_mailbox_write(MBOX_CHAN_POWER, 0); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) ++ g_state.client_request[i] = BCM_POWER_NOCLIENT; ++ ++ sema_init(&g_state.client_mutex, 1); ++ sema_init(&g_state.mutex, 1); ++ ++ g_state.global_request = 0; ++ ++#if defined(BCM_POWER_ALWAYS_ON) ++ if (BCM_POWER_ALWAYS_ON) { ++ bcm_power_open(&always_on_handle); ++ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); ++ } ++#endif ++ ++ return rc; ++} ++ ++static void __exit bcm_power_exit(void) ++{ ++ bcm_mailbox_write(MBOX_CHAN_POWER, 0); ++} ++ ++/* ++ * Load after the mailbox driver is initialized (arch_initcall), ++ * but before depending drivers (module_init). ++ */ ++subsys_initcall(bcm_power_init); ++module_exit(bcm_power_exit); ++ ++MODULE_AUTHOR("Phil Elwell"); ++MODULE_DESCRIPTION("Interface to BCM2708 power management"); ++MODULE_LICENSE("GPL"); +diff --git a/include/soc/bcm2835/power.h b/include/soc/bcm2835/power.h +new file mode 100644 +index 0000000..bf22b26 +--- /dev/null ++++ b/include/soc/bcm2835/power.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#ifndef _BCM2708_POWER_H ++#define _BCM2708_POWER_H ++ ++#include ++ ++/* Use meaningful names on each side */ ++#ifdef __VIDEOCORE__ ++#define PREFIX(x) ARM_##x ++#else ++#define PREFIX(x) BCM_##x ++#endif ++ ++enum { ++ PREFIX(POWER_SDCARD_BIT), ++ PREFIX(POWER_UART_BIT), ++ PREFIX(POWER_MINIUART_BIT), ++ PREFIX(POWER_USB_BIT), ++ PREFIX(POWER_I2C0_BIT), ++ PREFIX(POWER_I2C1_BIT), ++ PREFIX(POWER_I2C2_BIT), ++ PREFIX(POWER_SPI_BIT), ++ PREFIX(POWER_CCP2TX_BIT), ++ PREFIX(POWER_DSI_BIT), ++ ++ PREFIX(POWER_MAX) ++}; ++ ++enum { ++ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), ++ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), ++ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), ++ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), ++ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), ++ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), ++ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), ++ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), ++ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), ++ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), ++ ++ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, ++ PREFIX(POWER_NONE) = 0 ++}; ++ ++typedef unsigned int BCM_POWER_HANDLE_T; ++ ++extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); ++extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); ++extern int bcm_power_close(BCM_POWER_HANDLE_T handle); ++ ++#endif + +From 9409d45ef7d82d4f0677ea1a16bb6e87d41ed8de Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 Oct 2014 18:50:05 +0100 -Subject: [PATCH 003/216] Add bcm2708_gpio driver +Subject: [PATCH 03/77] Add bcm2708_gpio driver Signed-off-by: popcornmix @@ -11130,22 +7400,23 @@ Issue: linux #760 --- arch/arm/mach-bcm2708/Kconfig | 8 + arch/arm/mach-bcm2708/Makefile | 1 + - arch/arm/mach-bcm2708/bcm2708.c | 28 ++ + arch/arm/mach-bcm2708/bcm2708.c | 25 ++ arch/arm/mach-bcm2708/bcm2708_gpio.c | 426 ++++++++++++++++++++++++++++++ arch/arm/mach-bcm2708/include/mach/gpio.h | 17 ++ + arch/arm/mach-bcm2709/bcm2709.c | 25 ++ include/linux/platform_data/bcm2708.h | 23 ++ - 6 files changed, 503 insertions(+) + 7 files changed, 525 insertions(+) create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h create mode 100644 include/linux/platform_data/bcm2708.h diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 1f11478..9355841 100644 +index 4955422..4cbda0c 100644 --- a/arch/arm/mach-bcm2708/Kconfig +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -9,6 +9,14 @@ config MACH_BCM2708 +@@ -20,6 +20,14 @@ config BCM2708_DT help - Include support for the Broadcom(R) BCM2708 platform. + Enable Device Tree support for BCM2708 +config BCM2708_GPIO + bool "BCM2708 gpio support" @@ -11155,24 +7426,23 @@ index 1f11478..9355841 100644 + help + Include support for the Broadcom(R) BCM2708 gpio. + - config BCM2708_VCMEM - bool "Videocore Memory" + config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" depends on MACH_BCM2708 diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index c76f39bc..a722f3f 100644 +index e7d5a29..5120994 100644 --- a/arch/arm/mach-bcm2708/Makefile +++ b/arch/arm/mach-bcm2708/Makefile -@@ -3,4 +3,5 @@ +@@ -3,3 +3,4 @@ # - obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o + obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 9b4e709..7503649 100644 +index d6659b0..c606853 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -331,6 +331,31 @@ static struct platform_device bcm2708_vcio_device = { +@@ -298,6 +298,31 @@ static struct platform_device bcm2708_vcio_device = { }, }; @@ -11201,19 +7471,9 @@ index 9b4e709..7503649 100644 +}; +#endif + - static struct resource bcm2708_systemtimer_resources[] = { - [0] = { /* system timer access */ - .start = ST_BASE, -@@ -473,6 +498,9 @@ void __init bcm2708_init(void) - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_vcio_device); -+#ifdef CONFIG_BCM2708_GPIO -+ bcm_register_device(&bcm2708_gpio_device); -+#endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c new file mode 100644 index 0000000..c1e9254 @@ -11669,6 +7929,42 @@ index 0000000..7965a97 +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START) + +#endif +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 19d0601..6060a0d 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -329,6 +329,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++#ifdef CONFIG_BCM2708_GPIO ++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" ++ ++static struct resource bcm2708_gpio_resources[] = { ++ [0] = { /* general purpose I/O */ ++ .start = GPIO_BASE, ++ .end = GPIO_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_gpio_device = { ++ .name = BCM_GPIO_DRIVER_NAME, ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_gpio_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), ++ .dev = { ++ .dma_mask = &gpio_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; diff --git a/include/linux/platform_data/bcm2708.h b/include/linux/platform_data/bcm2708.h new file mode 100644 index 0000000..fb69624 @@ -11699,10 +7995,647 @@ index 0000000..fb69624 + +#endif -From 2ca472651d3e308f62709f5e2536eaba99944b11 Mon Sep 17 00:00:00 2001 +From 4b9ec02bb6738a9c29f6308c55cbcab58c2c88a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 1 May 2015 19:11:03 +0200 +Subject: [PATCH 04/77] mailbox: bcm2708: Add bcm2708-vcio +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +Copy the arch vcio.c driver to drivers/mailbox. +This is done to make it available on ARCH_BCM2835. + +Signed-off-by: Noralf Trønnes + +mailbox: bcm2708-vcio: Allocation does not need to be atomic + +No need to do atomic allocation in a context that can sleep. + +Signed-off-by: Noralf Trønnes + +mailbox: bcm2708-vcio: Check the correct status register before writing + +With the VC reader blocked and the ARM writing, MAIL0_STA reads +empty permanently while MAIL1_STA goes from empty (0x40000000) +to non-empty (0x00000001-0x00000007) to full (0x80000008). + +Suggested-by: Phil Elwell +Signed-off-by: Noralf Trønnes +--- + drivers/mailbox/Kconfig | 6 + + drivers/mailbox/Makefile | 2 + + drivers/mailbox/bcm2708-vcio.c | 427 ++++++++++++++++++++++++++ + include/linux/platform_data/mailbox-bcm2708.h | 126 ++++++++ + 4 files changed, 561 insertions(+) + create mode 100644 drivers/mailbox/bcm2708-vcio.c + create mode 100644 include/linux/platform_data/mailbox-bcm2708.h + +diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig +index 84b0a2d..7f19cb4 100644 +--- a/drivers/mailbox/Kconfig ++++ b/drivers/mailbox/Kconfig +@@ -7,6 +7,12 @@ menuconfig MAILBOX + + if MAILBOX + ++config BCM2708_MBOX ++ bool "Broadcom BCM2708 Mailbox (vcio)" ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ help ++ Broadcom BCM2708 Mailbox (vcio) ++ + config ARM_MHU + tristate "ARM MHU Mailbox" + depends on ARM_AMBA +diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile +index b18201e..cecfad3 100644 +--- a/drivers/mailbox/Makefile ++++ b/drivers/mailbox/Makefile +@@ -2,6 +2,8 @@ + + obj-$(CONFIG_MAILBOX) += mailbox.o + ++obj-$(CONFIG_BCM2708_MBOX) += bcm2708-vcio.o ++ + obj-$(CONFIG_ARM_MHU) += arm_mhu.o + + obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o +diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c +new file mode 100644 +index 0000000..d91672b +--- /dev/null ++++ b/drivers/mailbox/bcm2708-vcio.c +@@ -0,0 +1,427 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/vcio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for writing to the mailboxes, ++ * semaphores, doorbells etc. that are shared between the ARM and the ++ * VideoCore processor ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "bcm2708_vcio" ++#define DEVICE_FILE_NAME "vcio" ++ ++/* offsets from a mail box base address */ ++#define MAIL0_RD 0x00 /* read - and next 4 words */ ++#define MAIL0_POL 0x10 /* read without popping the fifo */ ++#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ ++#define MAIL0_STA 0x18 /* status */ ++#define MAIL0_CNF 0x1C /* configuration */ ++#define MAIL1_WRT 0x20 /* write - and next 4 words */ ++#define MAIL1_STA 0x38 /* status */ ++ ++/* On MACH_BCM270x these come through (arm_control.h ) */ ++#ifndef ARM_MS_EMPTY ++#define ARM_MS_EMPTY BIT(30) ++#define ARM_MS_FULL BIT(31) ++ ++#define ARM_MC_IHAVEDATAIRQEN BIT(0) ++#endif ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) ++ ++#define MBOX_MAGIC 0xd0d0c0de ++ ++#define MAJOR_NUM 100 ++#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) ++ ++static struct class *vcio_class; ++ ++struct vc_mailbox { ++ void __iomem *regs; ++ uint32_t msg[MBOX_CHAN_COUNT]; ++ struct semaphore sema[MBOX_CHAN_COUNT]; ++ uint32_t magic; ++}; ++ ++static void mbox_init(struct vc_mailbox *mbox_out) ++{ ++ int i; ++ ++ for (i = 0; i < MBOX_CHAN_COUNT; i++) { ++ mbox_out->msg[i] = 0; ++ sema_init(&mbox_out->sema[i], 0); ++ } ++ ++ /* Enable the interrupt on data reception */ ++ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); ++ ++ mbox_out->magic = MBOX_MAGIC; ++} ++ ++static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) ++{ ++ if (mbox->magic != MBOX_MAGIC) ++ return -EINVAL; ++ ++ /* wait for the mailbox FIFO to have some space in it */ ++ while (0 != (readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL)) ++ cpu_relax(); ++ ++ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); ++ ++ return 0; ++} ++ ++static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) ++{ ++ if (mbox->magic != MBOX_MAGIC) ++ return -EINVAL; ++ ++ down(&mbox->sema[chan]); ++ *data28 = MBOX_DATA28(mbox->msg[chan]); ++ mbox->msg[chan] = 0; ++ ++ return 0; ++} ++ ++static irqreturn_t mbox_irq_handler(int irq, void *dev_id) ++{ ++ /* wait for the mailbox FIFO to have some data in it */ ++ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; ++ int status = readl(mbox->regs + MAIL0_STA); ++ int ret = IRQ_NONE; ++ ++ while (!(status & ARM_MS_EMPTY)) { ++ uint32_t msg = readl(mbox->regs + MAIL0_RD); ++ int chan = MBOX_CHAN(msg); ++ ++ if (chan < MBOX_CHAN_COUNT) { ++ if (mbox->msg[chan]) { ++ pr_err(DRIVER_NAME ++ ": mbox chan %d overflow - drop %08x\n", ++ chan, msg); ++ } else { ++ mbox->msg[chan] = (msg | 0xf); ++ up(&mbox->sema[chan]); ++ } ++ } else { ++ pr_err(DRIVER_NAME ++ ": invalid channel selector (msg %08x)\n", msg); ++ } ++ ret = IRQ_HANDLED; ++ status = readl(mbox->regs + MAIL0_STA); ++ } ++ return ret; ++} ++ ++/* Mailbox Methods */ ++ ++static struct device *mbox_dev; /* we assume there's only one! */ ++ ++static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) ++{ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ int rc; ++ ++ device_lock(dev); ++ rc = mbox_write(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) ++{ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ int rc; ++ ++ device_lock(dev); ++ rc = mbox_read(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++extern int bcm_mailbox_write(unsigned chan, uint32_t data28) ++{ ++ if (!mbox_dev) ++ return -ENODEV; ++ ++ return dev_mbox_write(mbox_dev, chan, data28); ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_write); ++ ++extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) ++{ ++ if (!mbox_dev) ++ return -ENODEV; ++ ++ return dev_mbox_read(mbox_dev, chan, data28); ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_read); ++ ++static int mbox_copy_from_user(void *dst, const void *src, int size) ++{ ++ if ((uint32_t)src < TASK_SIZE) ++ return copy_from_user(dst, src, size); ++ ++ memcpy(dst, src, size); ++ ++ return 0; ++} ++ ++static int mbox_copy_to_user(void *dst, const void *src, int size) ++{ ++ if ((uint32_t)dst < TASK_SIZE) ++ return copy_to_user(dst, src, size); ++ ++ memcpy(dst, src, size); ++ ++ return 0; ++} ++ ++static DEFINE_MUTEX(mailbox_lock); ++extern int bcm_mailbox_property(void *data, int size) ++{ ++ uint32_t success; ++ dma_addr_t mem_bus; /* the memory address accessed from videocore */ ++ void *mem_kern; /* the memory address accessed from driver */ ++ int s = 0; ++ ++ mutex_lock(&mailbox_lock); ++ /* allocate some memory for the messages communicating with GPU */ ++ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, ++ GFP_KERNEL); ++ if (mem_kern) { ++ /* create the message */ ++ mbox_copy_from_user(mem_kern, data, size); ++ ++ /* send the message */ ++ wmb(); ++ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); ++ if (s == 0) ++ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); ++ if (s == 0) { ++ /* copy the response */ ++ rmb(); ++ mbox_copy_to_user(data, mem_kern, size); ++ } ++ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); ++ } else { ++ s = -ENOMEM; ++ } ++ if (s != 0) ++ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); ++ ++ mutex_unlock(&mailbox_lock); ++ return s; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_property); ++ ++/* Platform Device for Mailbox */ ++ ++/* ++ * Is the device open right now? Used to prevent ++ * concurent access into the same device ++ */ ++static bool device_is_open; ++ ++/* This is called whenever a process attempts to open the device file */ ++static int device_open(struct inode *inode, struct file *file) ++{ ++ /* We don't want to talk to two processes at the same time */ ++ if (device_is_open) ++ return -EBUSY; ++ ++ device_is_open = true; ++ try_module_get(THIS_MODULE); ++ ++ return 0; ++} ++ ++static int device_release(struct inode *inode, struct file *file) ++{ ++ /* We're now ready for our next caller */ ++ device_is_open = false; ++ ++ module_put(THIS_MODULE); ++ ++ return 0; ++} ++ ++/* ++ * This function is called whenever a process tries to do an ioctl on our ++ * device file. We get two extra parameters (additional to the inode and file ++ * structures, which all device functions get): the number of the ioctl called ++ * and the parameter given to the ioctl function. ++ * ++ * If the ioctl is write or read/write (meaning output is returned to the ++ * calling process), the ioctl call returns the output of this function. ++ * ++ */ ++static long device_ioctl(struct file *file, unsigned int ioctl_num, ++ unsigned long ioctl_param) ++{ ++ unsigned size; ++ ++ switch (ioctl_num) { ++ case IOCTL_MBOX_PROPERTY: ++ /* ++ * Receive a pointer to a message (in user space) and set that ++ * to be the device's message. Get the parameter given to ++ * ioctl by the process. ++ */ ++ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); ++ return bcm_mailbox_property((void *)ioctl_param, size); ++ default: ++ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Module Declarations */ ++ ++/* ++ * This structure will hold the functions to be called ++ * when a process does something to the device we ++ * created. Since a pointer to this structure is kept in ++ * the devices table, it can't be local to ++ * init_module. NULL is for unimplemented functios. ++ */ ++const struct file_operations fops = { ++ .unlocked_ioctl = device_ioctl, ++ .open = device_open, ++ .release = device_release, /* a.k.a. close */ ++}; ++ ++static int bcm_vcio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device *vdev; ++ struct vc_mailbox *mailbox; ++ struct resource *res; ++ int irq, ret; ++ ++ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); ++ if (!mailbox) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ mailbox->regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(mailbox->regs)) ++ return PTR_ERR(mailbox->regs); ++ ++ irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(dev, irq, mbox_irq_handler, ++ IRQF_IRQPOLL, ++ dev_name(dev), mailbox); ++ if (ret) { ++ dev_err(dev, "Interrupt request failed %d\n", ret); ++ return ret; ++ } ++ ++ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); ++ if (ret < 0) { ++ pr_err("Character device registration failed %d\n", ret); ++ return ret; ++ } ++ ++ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); ++ if (IS_ERR(vcio_class)) { ++ ret = PTR_ERR(vcio_class); ++ pr_err("Class creation failed %d\n", ret); ++ goto err_class; ++ } ++ ++ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, ++ "vcio"); ++ if (IS_ERR(vdev)) { ++ ret = PTR_ERR(vdev); ++ pr_err("Device creation failed %d\n", ret); ++ goto err_dev; ++ } ++ ++ mbox_init(mailbox); ++ platform_set_drvdata(pdev, mailbox); ++ mbox_dev = dev; ++ ++ dev_info(dev, "mailbox at %p\n", mailbox->regs); ++ ++ return 0; ++ ++err_dev: ++ class_destroy(vcio_class); ++err_class: ++ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); ++ ++ return ret; ++} ++ ++static int bcm_vcio_remove(struct platform_device *pdev) ++{ ++ mbox_dev = NULL; ++ platform_set_drvdata(pdev, NULL); ++ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); ++ class_destroy(vcio_class); ++ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm_vcio_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-vcio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); ++ ++static struct platform_driver bcm_mbox_driver = { ++ .probe = bcm_vcio_probe, ++ .remove = bcm_vcio_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_vcio_of_match_table, ++ }, ++}; ++ ++static int __init bcm_mbox_init(void) ++{ ++ return platform_driver_register(&bcm_mbox_driver); ++} ++ ++static void __exit bcm_mbox_exit(void) ++{ ++ platform_driver_unregister(&bcm_mbox_driver); ++} ++ ++arch_initcall(bcm_mbox_init); /* Initialize early */ ++module_exit(bcm_mbox_exit); ++ ++MODULE_AUTHOR("Gray Girling"); ++MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/platform_data/mailbox-bcm2708.h b/include/linux/platform_data/mailbox-bcm2708.h +new file mode 100644 +index 0000000..cc284ed +--- /dev/null ++++ b/include/linux/platform_data/mailbox-bcm2708.h +@@ -0,0 +1,126 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef _PLAT_MAILBOX_BCM2708_H ++#define _PLAT_MAILBOX_BCM2708_H ++ ++/* Routines to handle I/O via the VideoCore "ARM control" registers ++ * (semaphores, doorbells, mailboxes) ++ */ ++ ++/* Constants shared with the ARM identifying separate mailbox channels */ ++#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ ++#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ ++#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ ++#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ ++#define MBOX_CHAN_COUNT 9 ++ ++enum { ++ VCMSG_PROCESS_REQUEST = 0x00000000 ++}; ++ ++enum { ++ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, ++ VCMSG_REQUEST_FAILED = 0x80000001 ++}; ++ ++/* Mailbox property tags */ ++enum { ++ VCMSG_PROPERTY_END = 0x00000000, ++ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, ++ VCMSG_GET_BOARD_MODEL = 0x00010001, ++ VCMSG_GET_BOARD_REVISION = 0x00010002, ++ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, ++ VCMSG_GET_BOARD_SERIAL = 0x00010004, ++ VCMSG_GET_ARM_MEMORY = 0x00010005, ++ VCMSG_GET_VC_MEMORY = 0x00010006, ++ VCMSG_GET_CLOCKS = 0x00010007, ++ VCMSG_GET_COMMAND_LINE = 0x00050001, ++ VCMSG_GET_DMA_CHANNELS = 0x00060001, ++ VCMSG_GET_POWER_STATE = 0x00020001, ++ VCMSG_GET_TIMING = 0x00020002, ++ VCMSG_SET_POWER_STATE = 0x00028001, ++ VCMSG_GET_CLOCK_STATE = 0x00030001, ++ VCMSG_SET_CLOCK_STATE = 0x00038001, ++ VCMSG_GET_CLOCK_RATE = 0x00030002, ++ VCMSG_SET_CLOCK_RATE = 0x00038002, ++ VCMSG_GET_VOLTAGE = 0x00030003, ++ VCMSG_SET_VOLTAGE = 0x00038003, ++ VCMSG_GET_MAX_CLOCK = 0x00030004, ++ VCMSG_GET_MAX_VOLTAGE = 0x00030005, ++ VCMSG_GET_TEMPERATURE = 0x00030006, ++ VCMSG_GET_MIN_CLOCK = 0x00030007, ++ VCMSG_GET_MIN_VOLTAGE = 0x00030008, ++ VCMSG_GET_TURBO = 0x00030009, ++ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, ++ VCMSG_GET_STC = 0x0003000b, ++ VCMSG_SET_TURBO = 0x00038009, ++ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, ++ VCMSG_SET_LOCK_MEM = 0x0003000d, ++ VCMSG_SET_UNLOCK_MEM = 0x0003000e, ++ VCMSG_SET_RELEASE_MEM = 0x0003000f, ++ VCMSG_SET_EXECUTE_CODE = 0x00030010, ++ VCMSG_SET_EXECUTE_QPU = 0x00030011, ++ VCMSG_SET_ENABLE_QPU = 0x00030012, ++ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, ++ VCMSG_GET_EDID_BLOCK = 0x00030020, ++ VCMSG_GET_CUSTOMER_OTP = 0x00030021, ++ VCMSG_SET_CUSTOMER_OTP = 0x00038021, ++ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, ++ VCMSG_SET_RELEASE_BUFFER = 0x00048001, ++ VCMSG_SET_BLANK_SCREEN = 0x00040002, ++ VCMSG_TST_BLANK_SCREEN = 0x00044002, ++ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, ++ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, ++ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, ++ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, ++ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, ++ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, ++ VCMSG_GET_DEPTH = 0x00040005, ++ VCMSG_TST_DEPTH = 0x00044005, ++ VCMSG_SET_DEPTH = 0x00048005, ++ VCMSG_GET_PIXEL_ORDER = 0x00040006, ++ VCMSG_TST_PIXEL_ORDER = 0x00044006, ++ VCMSG_SET_PIXEL_ORDER = 0x00048006, ++ VCMSG_GET_ALPHA_MODE = 0x00040007, ++ VCMSG_TST_ALPHA_MODE = 0x00044007, ++ VCMSG_SET_ALPHA_MODE = 0x00048007, ++ VCMSG_GET_PITCH = 0x00040008, ++ VCMSG_TST_PITCH = 0x00044008, ++ VCMSG_SET_PITCH = 0x00048008, ++ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, ++ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, ++ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, ++ VCMSG_GET_OVERSCAN = 0x0004000a, ++ VCMSG_TST_OVERSCAN = 0x0004400a, ++ VCMSG_SET_OVERSCAN = 0x0004800a, ++ VCMSG_GET_PALETTE = 0x0004000b, ++ VCMSG_TST_PALETTE = 0x0004400b, ++ VCMSG_SET_PALETTE = 0x0004800b, ++ VCMSG_GET_LAYER = 0x0004000c, ++ VCMSG_TST_LAYER = 0x0004400c, ++ VCMSG_SET_LAYER = 0x0004800c, ++ VCMSG_GET_TRANSFORM = 0x0004000d, ++ VCMSG_TST_TRANSFORM = 0x0004400d, ++ VCMSG_SET_TRANSFORM = 0x0004800d, ++ VCMSG_TST_VSYNC = 0x0004400e, ++ VCMSG_SET_VSYNC = 0x0004800e, ++ VCMSG_SET_CURSOR_INFO = 0x00008010, ++ VCMSG_SET_CURSOR_STATE = 0x00008011, ++}; ++ ++int bcm_mailbox_read(unsigned chan, uint32_t *data28); ++int bcm_mailbox_write(unsigned chan, uint32_t data28); ++int bcm_mailbox_property(void *data, int size); ++ ++#endif + +From c921ec1cd21e8a8eb4e453834a205e9da5dff30a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 004/216] Add dwc_otg driver +Subject: [PATCH 05/77] Add dwc_otg driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -12117,16 +9050,38 @@ in the middle of a transaction. Make the effects less severe. Also get rid of the useless return value. squash: dwc_otg: Allow to build without SMP + +usb: core: make overcurrent messages more prominent + +Hub overcurrent messages are more serious than "debug". Increase loglevel. + +usb: dwc_otg: Don't use dma_to_virt() + +Commit 6ce0d20 changes dma_to_virt() which breaks this driver. +Open code the old dma_to_virt() implementation to work around this. + +Limit the use of __bus_to_virt() to cases where transfer_buffer_length +is set and transfer_buffer is not set. This is done to increase the +chance that this driver will also work on ARCH_BCM2835. + +transfer_buffer should not be NULL if the length is set, but the +comment in the code indicates that there are situations where this +might happen. drivers/usb/isp1760/isp1760-hcd.c also has a similar +comment pointing to a possible: 'usb storage / SCSI bug'. + +Signed-off-by: Noralf Trønnes + +dwc_otg: Fix crash when fiq_enable=0 --- - arch/arm/Kconfig | 1 + arch/arm/include/asm/irqflags.h | 16 +- arch/arm/kernel/fiqasm.S | 4 + arch/arm/mach-bcm2708/armctrl.c | 19 +- - arch/arm/mach-bcm2708/bcm2708.c | 15 +- + arch/arm/mach-bcm2708/bcm2708.c | 11 + arch/arm/mach-bcm2708/include/mach/irqs.h | 153 +- arch/arm/mach-bcm2709/armctrl.c | 10 +- drivers/usb/Makefile | 1 + drivers/usb/core/generic.c | 1 + + drivers/usb/core/hub.c | 2 +- drivers/usb/core/message.c | 79 + drivers/usb/core/otg_whitelist.h | 114 +- drivers/usb/gadget/file_storage.c | 3676 ++++++++++ @@ -12169,7 +9124,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1594 +++++ drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 705 ++ drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 117 + - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1749 +++++ + drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1756 +++++ drivers/usb/host/dwc_otg/dwc_otg_driver.h | 86 + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 1346 ++++ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 367 + @@ -12179,7 +9134,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1132 ++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 ++ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2713 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 994 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 995 +++ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 957 +++ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2712 ++++++++ @@ -12192,7 +9147,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 74 files changed, 60026 insertions(+), 97 deletions(-) + 74 files changed, 60032 insertions(+), 96 deletions(-) create mode 100644 drivers/usb/gadget/file_storage.c create mode 100644 drivers/usb/host/dwc_common_port/Makefile create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd @@ -12255,18 +9210,6 @@ squash: dwc_otg: Allow to build without SMP create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 4018fea..ee1bb5e 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -382,6 +382,7 @@ config ARCH_BCM2708 - select ARM_ERRATA_411920 - select MACH_BCM2708 - select VC4 -+ select FIQ - help - This enables support for Broadcom BCM2708 boards. - diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h index 3b763d6..5770408 100644 --- a/arch/arm/include/asm/irqflags.h @@ -12310,10 +9253,10 @@ index 8dd26e1..eef4847 100644 + mov pc, r8 +ENDPROC(__FIQ_Branch) diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index ef1c8d5..96fa9b9 100644 +index cd252fa..74bacb3 100644 --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_data *d) +@@ -54,8 +54,12 @@ static void armctrl_mask_irq(struct irq_data *d) 0 }; @@ -12328,7 +9271,7 @@ index ef1c8d5..96fa9b9 100644 } static void armctrl_unmask_irq(struct irq_data *d) -@@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct irq_data *d) +@@ -67,8 +71,14 @@ static void armctrl_unmask_irq(struct irq_data *d) 0 }; @@ -12344,38 +9287,37 @@ index ef1c8d5..96fa9b9 100644 + } } - #if defined(CONFIG_PM) -@@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, + #ifdef CONFIG_OF +@@ -299,6 +309,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, } armctrl_pm_register(base, irq_start, resume_sources); + init_FIQ(FIQ_START); + armctrl_dt_init(); return 0; } diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7503649..d9db081 100644 +index c606853..4455f34 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -291,12 +291,23 @@ static struct resource bcm2708_usb_resources[] = { - .flags = IORESOURCE_MEM, - }, +@@ -254,12 +254,23 @@ static struct resource bcm2708_usb_resources[] = { + .flags = IORESOURCE_MEM, + }, [1] = { -- .start = IRQ_USB, -- .end = IRQ_USB, + .start = MPHI_BASE, + .end = MPHI_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, -+ }, ++ }, + [2] = { -+ .start = IRQ_HOSTPORT, -+ .end = IRQ_HOSTPORT, - .flags = IORESOURCE_IRQ, - }, ++ .start = IRQ_HOSTPORT, ++ .end = IRQ_HOSTPORT, ++ .flags = IORESOURCE_IRQ, ++ }, + [3] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, -+ .flags = IORESOURCE_IRQ, -+ }, + .start = IRQ_USB, + .end = IRQ_USB, + .flags = IORESOURCE_IRQ, + }, }; + @@ -12553,7 +9495,7 @@ index 3a88a1a..45152ed 100644 #define SPARE_ALLOC_IRQS 64 #define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS) diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c -index 2815b64..fc6cb8b 100644 +index 2fcfab9..a366275 100644 --- a/arch/arm/mach-bcm2709/armctrl.c +++ b/arch/arm/mach-bcm2709/armctrl.c @@ -91,7 +91,15 @@ static void armctrl_unmask_irq(struct irq_data *d) @@ -12574,12 +9516,12 @@ index 2815b64..fc6cb8b 100644 } else if (d->irq >= IRQ_ARM_LOCAL_CNTPSIRQ && d->irq < IRQ_ARM_LOCAL_CNTPSIRQ + 4) { #if 1 diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile -index 2f1e2aa..887ca56 100644 +index d8926c6..0607af9 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile -@@ -6,6 +6,7 @@ - +@@ -7,6 +7,7 @@ obj-$(CONFIG_USB) += core/ + obj-$(CONFIG_USB_SUPPORT) += phy/ +obj-$(CONFIG_USB_DWCOTG) += host/ obj-$(CONFIG_USB_DWC3) += dwc3/ @@ -12597,6 +9539,19 @@ index 358ca8d..abaac7c 100644 } return i; } +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 3b71516..8324c14 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4922,7 +4922,7 @@ static void port_event(struct usb_hub *hub, int port1) + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + u16 status = 0, unused; + +- dev_dbg(&port_dev->dev, "over-current change\n"); ++ dev_notice(&port_dev->dev, "over-current change\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_OVER_CURRENT); + msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f368d20..2f6e3fe 100644 --- a/drivers/usb/core/message.c @@ -16527,7 +13482,7 @@ index 0000000..a896d73 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 5ad60e4..fb5b986 100644 +index 197a6a3..5496cd0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -738,6 +738,19 @@ config USB_HWA_HCD @@ -44589,10 +41544,10 @@ index 0000000..ccc24e0 +#endif diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c new file mode 100644 -index 0000000..dc7cd32 +index 0000000..53307f0 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -0,0 +1,1749 @@ +@@ -0,0 +1,1756 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ + * $Revision: #92 $ @@ -45638,9 +42593,16 @@ index 0000000..dc7cd32 +}; +MODULE_DEVICE_TABLE(platform, platform_ids); + ++static const struct of_device_id dwc_otg_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-usb", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dwc_otg_of_match_table); ++ +static struct platform_driver dwc_otg_driver = { + .driver = { + .name = (char *)dwc_driver_name, ++ .of_match_table = dwc_otg_of_match_table, + }, + .id_table = platform_ids, + @@ -48247,7 +45209,7 @@ index 0000000..ffa8d21 +END(_dwc_otg_fiq_stub) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c new file mode 100644 -index 0000000..6c53d2c +index 0000000..4d7c7bb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -0,0 +1,4252 @@ @@ -50273,7 +47235,7 @@ index 0000000..6c53d2c + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed + * cheeky devices that just hold off using NAKs + */ -+ if (nak_holdoff && qh->do_split) { ++ if (fiq_enable && nak_holdoff && qh->do_split) { + if (qh->nak_frame != 0xffff) { + uint16_t next_frame = dwc_frame_num_inc(qh->nak_frame, (qh->ep_type == UE_BULK) ? nak_holdoff : 8); + uint16_t frame = dwc_otg_hcd_get_frame_number(hcd); @@ -57653,10 +54615,10 @@ index 0000000..8a31562 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c new file mode 100644 -index 0000000..1d28459 +index 0000000..0f4ebcd --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -0,0 +1,994 @@ +@@ -0,0 +1,995 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ @@ -58195,9 +55157,9 @@ index 0000000..1d28459 + * IRQ line, and calls hcd_start method. + */ +#ifdef PLATFORM_INTERFACE -+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED | IRQF_DISABLED); ++ retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED); +#else -+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); +#endif + if (retval < 0) { + goto error2; @@ -58425,16 +55387,17 @@ index 0000000..1d28459 + !(usb_pipein(urb->pipe)))); + + buf = urb->transfer_buffer; -+ if (hcd->self.uses_dma) { ++ if (hcd->self.uses_dma && !buf && urb->transfer_buffer_length) { + /* + * Calculate virtual address from physical address, + * because some class driver may not fill transfer_buffer. + * In Buffer DMA mode virual address is used, + * when handling non DWORD aligned buffers. + */ -+ //buf = phys_to_virt(urb->transfer_dma); -+ // DMA addresses are bus addresses not physical addresses! -+ buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); ++ buf = (void *)__bus_to_virt((unsigned long)urb->transfer_dma); ++ dev_warn_once(&urb->dev->dev, ++ "USB transfer_buffer was NULL, will use __bus_to_virt(%pad)=%p\n", ++ &urb->transfer_dma, buf); + } + + if (!(urb->transfer_flags & URB_NO_INTERRUPT)) @@ -72943,24 +69906,24 @@ index 0000000..cdc9963 +test_main(); +0; -From 0876a9278a3227e3f8924b6e04c1af6c18d4e1e7 Mon Sep 17 00:00:00 2001 +From 560486db654a651cebb107628426d1705ef4cc20 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 005/216] bcm2708 watchdog driver +Subject: [PATCH 06/77] bcm2708 watchdog driver Signed-off-by: popcornmix --- - drivers/watchdog/Kconfig | 6 + + drivers/watchdog/Kconfig | 8 +- drivers/watchdog/Makefile | 1 + drivers/watchdog/bcm2708_wdog.c | 382 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 389 insertions(+) + 3 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 drivers/watchdog/bcm2708_wdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 16f2023..ca7d6463 100644 +index e5e7c55..b9c1ed5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -452,6 +452,12 @@ config RETU_WATCHDOG +@@ -451,6 +451,12 @@ config RETU_WATCHDOG To compile this driver as a module, choose M here: the module will be called retu_wdt. @@ -72973,6 +69936,15 @@ index 16f2023..ca7d6463 100644 config MOXART_WDT tristate "MOXART watchdog" depends on ARCH_MOXART +@@ -1216,7 +1222,7 @@ config BCM63XX_WDT + + config BCM2835_WDT + tristate "Broadcom BCM2835 hardware watchdog" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + select WATCHDOG_CORE + help + Watchdog driver for the built in watchdog hardware in Broadcom diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5c19294..aac60bd 100644 --- a/drivers/watchdog/Makefile @@ -73374,10 +70346,13 @@ index 0000000..8a27d68 +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); -From e32648d3db67d9954ee0a8bc13ab3f81345c50af Mon Sep 17 00:00:00 2001 +From 7014dbd386a6ce510bd6b9fa3a3fcfc2bd89d237 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 006/216] bcm2708 framebuffer driver +Date: Wed, 17 Jun 2015 17:06:34 +0100 +Subject: [PATCH 07/77] bcm2708 framebuffer driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -73423,55 +70398,40 @@ transfers, busy-waiting is still likely to be faster. Signed-off-by: Luke Diamand bcm2708: Make ioctl logging quieter + +video: fbdev: bcm2708_fb: Don't panic on error + +No need to panic the kernel if the video driver fails. +Just print a message and return an error. + +Signed-off-by: Noralf Trønnes + +fbdev: bcm2708_fb: Add ARCH_BCM2835 support + +Add Device Tree support. +Pass the device to dma_alloc_coherent() in order to get the +correct bus address on ARCH_BCM2835. +Use the new DMA legacy API header file. +Including is not necessary. + +Signed-off-by: Noralf Trønnes + +BCM270x_DT: Add bcm2708-fb device + +Add bcm2708-fb to Device Tree and don't add the +platform device when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/dma.c | 8 + - arch/arm/mach-bcm2708/include/mach/dma.h | 2 + drivers/video/fbdev/Kconfig | 14 + drivers/video/fbdev/Makefile | 1 + - drivers/video/fbdev/bcm2708_fb.c | 818 ++++++++++ + drivers/video/fbdev/bcm2708_fb.c | 824 ++++++++++ drivers/video/logo/logo_linux_clut224.ppm | 2483 ++++++++++------------------- - 6 files changed, 1724 insertions(+), 1602 deletions(-) + 4 files changed, 1720 insertions(+), 1602 deletions(-) create mode 100644 drivers/video/fbdev/bcm2708_fb.c -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -index 51d147a..1da2413 100644 ---- a/arch/arm/mach-bcm2708/dma.c -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -83,6 +83,14 @@ extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) - - EXPORT_SYMBOL_GPL(bcm_dma_start); - -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ - /* Complete an ongoing DMA (assuming its results are to be ignored) - Does nothing if there is no DMA in progress. - This routine waits for the current AXI transfer to complete before -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index f2568d4..a4aac4c 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -64,11 +64,13 @@ struct bcm2708_dma_cb { - unsigned long next; - unsigned long pad[2]; - }; -+struct scatterlist; - - extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); - extern void bcm_dma_start(void __iomem *dma_chan_base, - dma_addr_t control_block); - extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); - extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); - - /* When listing features we can ask for when allocating DMA channels give diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index b3dd417..b3768b4 100644 +index 1094623..42e6c3b 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -224,6 +224,20 @@ config FB_TILEBLITTING @@ -73480,7 +70440,7 @@ index b3dd417..b3768b4 100644 +config FB_BCM2708 + tristate "BCM2708 framebuffer support" -+ depends on FB && ARM ++ depends on FB && ARM && BCM2708_MBOX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT @@ -73509,10 +70469,10 @@ index 1979aff..57181ad 100644 obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c new file mode 100644 -index 0000000..9179291 +index 0000000..f6ac7da --- /dev/null +++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -0,0 +1,818 @@ +@@ -0,0 +1,824 @@ +/* + * linux/drivers/video/bcm2708_fb.c + * @@ -73539,16 +70499,13 @@ index 0000000..9179291 +#include +#include +#include ++#include ++#include +#include +#include +#include +#include +#include -+ -+#include -+#include -+#include -+ +#include +#include +#include @@ -73840,8 +70797,8 @@ index 0000000..9179291 + /* the console may currently be locked */ + console_trylock(); + console_unlock(); -+ -+ BUG(); /* what can we do here */ ++ pr_err("bcm2708_fb_set_par: Failed to set screen_base\n"); ++ return -EIO; + } + } + print_debug @@ -74143,7 +71100,7 @@ index 0000000..9179291 + void *mem; + + mem = -+ dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma, ++ dma_alloc_coherent(&fb->dev->dev, PAGE_ALIGN(sizeof(*fb->info)), &dma, + GFP_KERNEL); + + if (NULL == mem) { @@ -74192,7 +71149,9 @@ index 0000000..9179291 + */ + + fb_set_var(&fb->fb, &fb->fb.var); -+ bcm2708_fb_set_par(&fb->fb); ++ ret = bcm2708_fb_set_par(&fb->fb); ++ if (ret) ++ return ret; + + print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth, + fbheight, fbdepth, fbswap); @@ -74296,12 +71255,19 @@ index 0000000..9179291 + return 0; +} + ++static const struct of_device_id bcm2708_fb_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-fb", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_fb_of_match_table); ++ +static struct platform_driver bcm2708_fb_driver = { + .probe = bcm2708_fb_probe, + .remove = bcm2708_fb_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = bcm2708_fb_of_match_table, + }, +}; + @@ -76822,10 +73788,10 @@ index 3c14e43..7626beb6a 100644 +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 31a44367b5b2a156b2a45d34a1e6b65c55fe8c96 Mon Sep 17 00:00:00 2001 +From 5efe288a95d60bd10a162be79442d04b6f1d4079 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 007/216] dmaengine: Add support for BCM2708 +Subject: [PATCH 08/77] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -76874,116 +73840,277 @@ Add Device Tree support to the non ARCH_BCM2835 case. Use the same driver name regardless of architecture. Signed-off-by: Noralf Trønnes + +BCM270x_DT: add bcm2835-dma entry + +Add Device Tree entry for bcm2835-dma. +The entry doesn't contain any resources since they are handled +by the arch/arm/mach-bcm270x/dma.c driver. +In non-DT mode, don't add the device in the board file. + +Signed-off-by: Noralf Trønnes + +bcm2708-dmaengine: Add debug options + +BCM270x: Add memory and irq resources to dmaengine device and DT + +Prepare for merging of the legacy DMA API arch driver dma.c +with bcm2708-dmaengine by adding memory and irq resources both +to platform file device and Device Tree node. +Don't use BCM_DMAMAN_DRIVER_NAME so we don't have to include mach/dma.h + +Signed-off-by: Noralf Trønnes + +dmaengine: bcm2708: Merge with arch dma.c driver and disable dma.c + +Merge the legacy DMA API driver with bcm2708-dmaengine. +This is done so we can use bcm2708_fb on ARCH_BCM2835 (mailbox +driver is also needed). + +Changes to the dma.c code: +- Use BIT() macro. +- Cutdown some comments to one line. +- Add mutex to vc_dmaman and use this, since the dev lock is locked + during probing of the engine part. +- Add global g_dmaman variable since drvdata is used by the engine part. +- Restructure for readability: + vc_dmaman_chan_alloc() + vc_dmaman_chan_free() + bcm_dma_chan_free() +- Restructure bcm_dma_chan_alloc() to simplify error handling. +- Use device irq resources instead of hardcoded bcm_dma_irqs table. +- Remove dev_dmaman_register() and code it directly. +- Remove dev_dmaman_deregister() and code it directly. +- Simplify bcm_dmaman_probe() using devm_* functions. +- Get dmachans from DT if available. +- Keep 'dma.dmachans' module argument name for backwards compatibility. + +Make it available on ARCH_BCM2835 as well. + +Signed-off-by: Noralf Trønnes + +dmaengine: bcm2708: set residue_granularity field + +bcm2708-dmaengine supports residue reporting at burst level +but didn't report this via the residue_granularity field. + +Without this field set properly we get playback issues with I2S cards. --- - arch/arm/mach-bcm2708/bcm2708.c | 6 + - arch/arm/mach-bcm2708/dma.c | 2 + - arch/arm/mach-bcm2708/include/mach/dma.h | 6 +- - arch/arm/mach-bcm2709/bcm2709.c | 6 + - drivers/dma/Kconfig | 6 + - drivers/dma/Makefile | 1 + - drivers/dma/bcm2708-dmaengine.c | 989 +++++++++++++++++++++++++++++++ - 7 files changed, 1015 insertions(+), 1 deletion(-) + arch/arm/mach-bcm2708/bcm2708.c | 68 ++ + arch/arm/mach-bcm2709/bcm2709.c | 68 ++ + drivers/dma/Kconfig | 13 +- + drivers/dma/Makefile | 1 + + drivers/dma/bcm2708-dmaengine.c | 1298 +++++++++++++++++++++++++++++ + include/linux/platform_data/dma-bcm2708.h | 127 +++ + 6 files changed, 1574 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/bcm2708-dmaengine.c + create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d9db081..5d8657b 100644 +index 4455f34..6b0b6c4 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -250,6 +250,11 @@ static struct platform_device bcm2708_dmaman_device = { - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), +@@ -234,6 +234,73 @@ static struct amba_device *amba_devs[] __initdata = { + &uart0_device, }; ++static struct resource bcm2708_dmaengine_resources[] = { ++ { ++ .start = DMA_BASE, ++ .end = DMA_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_DMA0, ++ .end = IRQ_DMA0, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA1, ++ .end = IRQ_DMA1, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA2, ++ .end = IRQ_DMA2, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA3, ++ .end = IRQ_DMA3, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA4, ++ .end = IRQ_DMA4, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA5, ++ .end = IRQ_DMA5, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA6, ++ .end = IRQ_DMA6, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA7, ++ .end = IRQ_DMA7, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA8, ++ .end = IRQ_DMA8, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA9, ++ .end = IRQ_DMA9, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA10, ++ .end = IRQ_DMA10, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA11, ++ .end = IRQ_DMA11, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA12, ++ .end = IRQ_DMA12, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ +static struct platform_device bcm2708_dmaengine_device = { + .name = "bcm2708-dmaengine", + .id = -1, ++ .resource = bcm2708_dmaengine_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), +}; + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); static struct platform_device bcm2708_fb_device = { -@@ -508,6 +513,7 @@ void __init bcm2708_init(void) - clkdev_add(&lookups[i]); +@@ -463,6 +530,7 @@ void __init bcm2708_init(void) + bcm2708_init_clocks(); + bcm2708_dt_init(); - bcm_register_device(&bcm2708_dmaman_device); -+ bcm_register_device(&bcm2708_dmaengine_device); ++ bcm_register_device_dt(&bcm2708_dmaengine_device); bcm_register_device(&bcm2708_vcio_device); #ifdef CONFIG_BCM2708_GPIO - bcm_register_device(&bcm2708_gpio_device); -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -index 1da2413..a5e58d1 100644 ---- a/arch/arm/mach-bcm2708/dma.c -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -156,6 +156,8 @@ static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, - dmaman->chan_available = chans_available; - dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ - dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ - } - - static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index a4aac4c..d03e7b5 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -77,9 +77,13 @@ extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); - those with higher priority smaller ordinal numbers */ - #define BCM_DMA_FEATURE_FAST_ORD 0 - #define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 - #define BCM_DMA_FEATURE_FAST (1< +#include +#include ++#include +#include +#include +#include +#include -+ -+#ifndef CONFIG_ARCH_BCM2835 -+ -+/* dma manager */ -+#include -+ -+//#define DMA_COMPLETE DMA_SUCCESS -+ -+#endif -+ +#include +#include + +#include "virt-dma.h" + ++static unsigned dma_debug; ++ ++/* ++ * Legacy DMA API ++ */ ++ ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++ ++#define CACHE_LINE_MASK 31 ++#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ ++ ++/* valid only for channels 0 - 14, 15 has its own base address */ ++#define BCM2708_DMA_CHAN(n) ((n) << 8) /* base address */ ++#define BCM2708_DMA_CHANIO(dma_base, n) \ ++ ((void __iomem *)((char *)(dma_base) + BCM2708_DMA_CHAN(n))) ++ ++struct vc_dmaman { ++ void __iomem *dma_base; ++ u32 chan_available; /* bitmap of available channels */ ++ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ ++ struct mutex lock; ++}; ++ ++static struct device *dmaman_dev; /* we assume there's only one! */ ++static struct vc_dmaman *g_dmaman; /* DMA manager */ ++static int dmachans = -1; /* module parameter */ ++ ++/* DMA Auxiliary Functions */ ++ ++/* A DMA buffer on an arbitrary boundary may separate a cache line into a ++ section inside the DMA buffer and another section outside it. ++ Even if we flush DMA buffers from the cache there is always the chance that ++ during a DMA someone will access the part of a cache line that is outside ++ the DMA buffer - which will then bring in unwelcome data. ++ Without being able to dictate our own buffer pools we must insist that ++ DMA buffers consist of a whole number of cache lines. ++*/ ++extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) ++{ ++ int i; ++ ++ for (i = 0; i < sg_len; i++) { ++ if (sg_ptr[i].offset & CACHE_LINE_MASK || ++ sg_ptr[i].length & CACHE_LINE_MASK) ++ return 0; ++ } ++ ++ return 1; ++} ++EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); ++ ++extern void bcm_dma_start(void __iomem *dma_chan_base, ++ dma_addr_t control_block) ++{ ++ dsb(); /* ARM data synchronization (push) operation */ ++ ++ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); ++ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); ++} ++EXPORT_SYMBOL_GPL(bcm_dma_start); ++ ++extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ /* ugly busy wait only option for now */ ++ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) ++ cpu_relax(); ++} ++EXPORT_SYMBOL_GPL(bcm_dma_wait_idle); ++ ++extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_is_busy); ++ ++/* Complete an ongoing DMA (assuming its results are to be ignored) ++ Does nothing if there is no DMA in progress. ++ This routine waits for the current AXI transfer to complete before ++ terminating the current DMA. If the current transfer is hung on a DREQ used ++ by an uncooperative peripheral the AXI transfer may never complete. In this ++ case the routine times out and return a non-zero error code. ++ Use of this routine doesn't guarantee that the ongoing or aborted DMA ++ does not produce an interrupt. ++*/ ++extern int bcm_dma_abort(void __iomem *dma_chan_base) ++{ ++ unsigned long int cs; ++ int rc = 0; ++ ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (BCM2708_DMA_ACTIVE & cs) { ++ long int timeout = 10000; ++ ++ /* write 0 to the active bit - pause the DMA */ ++ writel(0, dma_chan_base + BCM2708_DMA_CS); ++ ++ /* wait for any current AXI transfer to complete */ ++ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { ++ /* we'll un-pause when we set of our next DMA */ ++ rc = -ETIMEDOUT; ++ ++ } else if (BCM2708_DMA_ACTIVE & cs) { ++ /* terminate the control block chain */ ++ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); ++ ++ /* abort the whole DMA */ ++ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, ++ dma_chan_base + BCM2708_DMA_CS); ++ } ++ } ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_abort); ++ ++ /* DMA Manager Device Methods */ ++ ++static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, ++ u32 chans_available) ++{ ++ dmaman->dma_base = dma_base; ++ dmaman->chan_available = chans_available; ++ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* 2 & 3 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* 0 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* 1 to 7 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* 8 to 14 */ ++} ++ ++static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, ++ unsigned preferred_feature_set) ++{ ++ u32 chans; ++ int chan = 0; ++ int feature; ++ ++ chans = dmaman->chan_available; ++ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) ++ /* select the subset of available channels with the desired ++ feature so long as some of the candidate channels have that ++ feature */ ++ if ((preferred_feature_set & (1 << feature)) && ++ (chans & dmaman->has_feature[feature])) ++ chans &= dmaman->has_feature[feature]; ++ ++ if (!chans) ++ return -ENOENT; ++ ++ /* return the ordinal of the first channel in the bitmap */ ++ while (chans != 0 && (chans & 1) == 0) { ++ chans >>= 1; ++ chan++; ++ } ++ /* claim the channel */ ++ dmaman->chan_available &= ~(1 << chan); ++ ++ return chan; ++} ++ ++static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) ++{ ++ if (chan < 0) ++ return -EINVAL; ++ ++ if ((1 << chan) & dmaman->chan_available) ++ return -EIDRM; ++ ++ dmaman->chan_available |= (1 << chan); ++ ++ return 0; ++} ++ ++/* DMA Manager Monitor */ ++ ++extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, int *out_dma_irq) ++{ ++ struct vc_dmaman *dmaman = g_dmaman; ++ struct platform_device *pdev = to_platform_device(dmaman_dev); ++ struct resource *r; ++ int chan; ++ ++ if (!dmaman_dev) ++ return -ENODEV; ++ ++ mutex_lock(&dmaman->lock); ++ chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); ++ if (chan < 0) ++ goto out; ++ ++ r = platform_get_resource(pdev, IORESOURCE_IRQ, (unsigned int)chan); ++ if (!r) { ++ dev_err(dmaman_dev, "failed to get irq for DMA channel %d\n", ++ chan); ++ vc_dmaman_chan_free(dmaman, chan); ++ chan = -ENOENT; ++ goto out; ++ } ++ ++ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, chan); ++ *out_dma_irq = r->start; ++ dev_dbg(dmaman_dev, ++ "Legacy API allocated channel=%d, base=%p, irq=%i\n", ++ chan, *out_dma_base, *out_dma_irq); ++ ++out: ++ mutex_unlock(&dmaman->lock); ++ ++ return chan; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); ++ ++extern int bcm_dma_chan_free(int channel) ++{ ++ struct vc_dmaman *dmaman = g_dmaman; ++ int rc; ++ ++ if (!dmaman_dev) ++ return -ENODEV; ++ ++ mutex_lock(&dmaman->lock); ++ rc = vc_dmaman_chan_free(dmaman, channel); ++ mutex_unlock(&dmaman->lock); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_free); ++ ++static int bcm_dmaman_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct vc_dmaman *dmaman; ++ struct resource *r; ++ void __iomem *dma_base; ++ uint32_t val; ++ ++ if (!of_property_read_u32(dev->of_node, ++ "brcm,dma-channel-mask", &val)) ++ dmachans = val; ++ else if (dmachans == -1) ++ dmachans = DEFAULT_DMACHAN_BITMAP; ++ ++ dmaman = devm_kzalloc(dev, sizeof(*dmaman), GFP_KERNEL); ++ if (!dmaman) ++ return -ENOMEM; ++ ++ mutex_init(&dmaman->lock); ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ dma_base = devm_ioremap_resource(dev, r); ++ if (IS_ERR(dma_base)) ++ return PTR_ERR(dma_base); ++ ++ vc_dmaman_init(dmaman, dma_base, dmachans); ++ g_dmaman = dmaman; ++ dmaman_dev = dev; ++ ++ dev_info(dev, "DMA legacy API manager at %p, dmachans=0x%x\n", ++ dma_base, dmachans); ++ ++ return 0; ++} ++ ++static int bcm_dmaman_remove(struct platform_device *pdev) ++{ ++ dmaman_dev = NULL; ++ ++ return 0; ++} ++ ++#else /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++static int bcm_dmaman_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++#endif /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++/* ++ * DMA engine ++ */ + +struct bcm2835_dmadev { + struct dma_device ddev; @@ -77602,7 +75008,10 @@ index 0000000..6150b8f + } + + /* Common part */ -+ control_block->info |= BCM2835_DMA_WAITS(SDHCI_BCM_DMA_WAITS); ++ u32 waits = SDHCI_BCM_DMA_WAITS; ++ if ((dma_debug >> 0) & 0x1f) ++ waits = (dma_debug >> 0) & 0x1f; ++ control_block->info |= BCM2835_DMA_WAITS(waits); + control_block->info |= BCM2835_DMA_WAIT_RESP; + + /* Enable */ @@ -77707,7 +75116,7 @@ index 0000000..6150b8f + return 0; +} + -+#ifdef CONFIG_ARCH_BCM2835 ++#ifndef CONFIG_DMA_BCM2708_LEGACY +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) +{ + struct bcm2835_chan *c; @@ -77785,7 +75194,7 @@ index 0000000..6150b8f +static int bcm2835_dma_probe(struct platform_device *pdev) +{ + struct bcm2835_dmadev *od; -+#ifdef CONFIG_ARCH_BCM2835 ++#ifndef CONFIG_DMA_BCM2708_LEGACY + struct resource *res; + void __iomem *base; + uint32_t chans_available; @@ -77798,10 +75207,7 @@ index 0000000..6150b8f + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + -+ /* If CONFIG_ARCH_BCM2835 is selected, device tree is used */ -+ /* hence the difference between probing */ -+ -+#ifndef CONFIG_ARCH_BCM2835 ++#ifdef CONFIG_DMA_BCM2708_LEGACY + + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) @@ -77813,6 +75219,10 @@ index 0000000..6150b8f + if (!od) + return -ENOMEM; + ++ rc = bcm_dmaman_probe(pdev); ++ if (rc) ++ return rc; ++ + pdev->dev.dma_parms = &od->dma_parms; + dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); + @@ -77831,6 +75241,7 @@ index 0000000..6150b8f + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); @@ -77899,6 +75310,7 @@ index 0000000..6150b8f + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); @@ -77954,6 +75366,7 @@ index 0000000..6150b8f + } + + dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n"); ++ dev_info(&pdev->dev, "dma_debug:%x\n", dma_debug); + + return 0; + @@ -77968,6 +75381,7 @@ index 0000000..6150b8f + + dma_async_device_unregister(&od->ddev); + bcm2835_dma_free(od); ++ bcm_dmaman_remove(pdev); + + return 0; +} @@ -77982,18 +75396,173 @@ index 0000000..6150b8f + }, +}; + -+module_platform_driver(bcm2835_dma_driver); ++static int bcm2835_init(void) ++{ ++ return platform_driver_register(&bcm2835_dma_driver); ++} + ++static void bcm2835_exit(void) ++{ ++ platform_driver_unregister(&bcm2835_dma_driver); ++} ++ ++/* ++ * Load after serial driver (arch_initcall) so we see the messages if it fails, ++ * but before drivers (module_init) that need a DMA channel. ++ */ ++subsys_initcall(bcm2835_init); ++module_exit(bcm2835_exit); ++ ++module_param(dma_debug, uint, 0644); ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++/* Keep backward compatibility: dma.dmachans= */ ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "dma." ++module_param(dmachans, int, 0644); ++#endif +MODULE_ALIAS("platform:bcm2835-dma"); +MODULE_DESCRIPTION("BCM2835 DMA engine driver"); +MODULE_AUTHOR("Florian Meier "); +MODULE_AUTHOR("Gellert Weisz "); +MODULE_LICENSE("GPL v2"); +diff --git a/include/linux/platform_data/dma-bcm2708.h b/include/linux/platform_data/dma-bcm2708.h +new file mode 100644 +index 0000000..2310e34 +--- /dev/null ++++ b/include/linux/platform_data/dma-bcm2708.h +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _PLAT_BCM2708_DMA_H ++#define _PLAT_BCM2708_DMA_H ++ ++/* DMA CS Control and Status bits */ ++#define BCM2708_DMA_ACTIVE BIT(0) ++#define BCM2708_DMA_INT BIT(2) ++#define BCM2708_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ ++#define BCM2708_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ ++#define BCM2708_DMA_ERR BIT(8) ++#define BCM2708_DMA_ABORT BIT(30) /* stop current CB, go to next, WO */ ++#define BCM2708_DMA_RESET BIT(31) /* WO, self clearing */ ++ ++/* DMA control block "info" field bits */ ++#define BCM2708_DMA_INT_EN BIT(0) ++#define BCM2708_DMA_TDMODE BIT(1) ++#define BCM2708_DMA_WAIT_RESP BIT(3) ++#define BCM2708_DMA_D_INC BIT(4) ++#define BCM2708_DMA_D_WIDTH BIT(5) ++#define BCM2708_DMA_D_DREQ BIT(6) ++#define BCM2708_DMA_S_INC BIT(8) ++#define BCM2708_DMA_S_WIDTH BIT(9) ++#define BCM2708_DMA_S_DREQ BIT(10) ++ ++#define BCM2708_DMA_BURST(x) (((x) & 0xf) << 12) ++#define BCM2708_DMA_PER_MAP(x) ((x) << 16) ++#define BCM2708_DMA_WAITS(x) (((x) & 0x1f) << 21) ++ ++#define BCM2708_DMA_DREQ_EMMC 11 ++#define BCM2708_DMA_DREQ_SDHOST 13 ++ ++#define BCM2708_DMA_CS 0x00 /* Control and Status */ ++#define BCM2708_DMA_ADDR 0x04 ++/* the current control block appears in the following registers - read only */ ++#define BCM2708_DMA_INFO 0x08 ++#define BCM2708_DMA_SOURCE_AD 0x0c ++#define BCM2708_DMA_DEST_AD 0x10 ++#define BCM2708_DMA_NEXTCB 0x1C ++#define BCM2708_DMA_DEBUG 0x20 ++ ++#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4) + BCM2708_DMA_CS) ++#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4) + BCM2708_DMA_ADDR) ++ ++#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) ++ ++/* When listing features we can ask for when allocating DMA channels give ++ those with higher priority smaller ordinal numbers */ ++#define BCM_DMA_FEATURE_FAST_ORD 0 ++#define BCM_DMA_FEATURE_BULK_ORD 1 ++#define BCM_DMA_FEATURE_NORMAL_ORD 2 ++#define BCM_DMA_FEATURE_LITE_ORD 3 ++#define BCM_DMA_FEATURE_FAST BIT(BCM_DMA_FEATURE_FAST_ORD) ++#define BCM_DMA_FEATURE_BULK BIT(BCM_DMA_FEATURE_BULK_ORD) ++#define BCM_DMA_FEATURE_NORMAL BIT(BCM_DMA_FEATURE_NORMAL_ORD) ++#define BCM_DMA_FEATURE_LITE BIT(BCM_DMA_FEATURE_LITE_ORD) ++#define BCM_DMA_FEATURE_COUNT 4 ++ ++struct bcm2708_dma_cb { ++ unsigned long info; ++ unsigned long src; ++ unsigned long dst; ++ unsigned long length; ++ unsigned long stride; ++ unsigned long next; ++ unsigned long pad[2]; ++}; ++ ++struct scatterlist; ++ ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++ ++int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); ++void bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block); ++void bcm_dma_wait_idle(void __iomem *dma_chan_base); ++bool bcm_dma_is_busy(void __iomem *dma_chan_base); ++int bcm_dma_abort(void __iomem *dma_chan_base); ++ ++/* return channel no or -ve error */ ++int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, int *out_dma_irq); ++int bcm_dma_chan_free(int channel); ++ ++#else /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++static inline int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, ++ int sg_len) ++{ ++ return 0; ++} ++ ++static inline void bcm_dma_start(void __iomem *dma_chan_base, ++ dma_addr_t control_block) { } ++ ++static inline void bcm_dma_wait_idle(void __iomem *dma_chan_base) { } ++ ++static inline bool bcm_dma_is_busy(void __iomem *dma_chan_base) ++{ ++ return false; ++} ++ ++static inline int bcm_dma_abort(void __iomem *dma_chan_base) ++{ ++ return -EINVAL; ++} ++ ++static inline int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, ++ int *out_dma_irq) ++{ ++ return -EINVAL; ++} ++ ++static inline int bcm_dma_chan_free(int channel) ++{ ++ return -EINVAL; ++} ++ ++#endif /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++#endif /* _PLAT_BCM2708_DMA_H */ -From 7ec18e818133424bf20d58993fa6822dd241e096 Mon Sep 17 00:00:00 2001 +From be30ad8849aa9fd6ffbe6f8198a5af4bb62c465f Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 008/216] MMC: added alternative MMC driver +Subject: [PATCH 09/77] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78019,23 +75588,61 @@ Probe error handling is broken in several places. Simplify error handling by using device managed functions. Replace pr_{err,info} with dev_{err,info}. +Signed-off-by: Noralf Trønnes + +bcm2835-mmc: Add locks when accessing sdhost registers + +bcm2835-mmc: Add range of debug options for slowing things down + +bcm2835-mmc: Add option to disable some delays + +bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23 + +bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23 + +bcm2835-mmc: Adding overclocking option + +Allow a different clock speed to be substitued for a requested 50MHz. +This option is exposed using the "overclock_50" DT parameter. +Note that the mmc interface is restricted to EVEN integer divisions of +250MHz, and the highest sensible option is 63 (250/4 = 62.5), the +next being 125 (250/2) which is much too high. + +Use at your own risk. + +bcm2835-mmc: Round up the overclock, so 62 works for 62.5Mhz + +Also only warn once for each overclock setting. + +mmc: bcm2835-mmc: Make available on ARCH_BCM2835 + +Make the bcm2835-mmc driver available for use on ARCH_BCM2835. + +Signed-off-by: Noralf Trønnes + +BCM270x_DT: add bcm2835-mmc entry + +Add Device Tree entry for bcm2835-mmc. +In non-DT mode, don't add the device in the board file. + Signed-off-by: Noralf Trønnes --- arch/arm/mach-bcm2708/bcm2708.c | 31 + - drivers/mmc/core/quirks.c | 4 + + arch/arm/mach-bcm2709/bcm2709.c | 35 +- + drivers/mmc/core/quirks.c | 6 + drivers/mmc/host/Kconfig | 29 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-mmc.c | 1506 +++++++++++++++++++++++++++++++++++++++ - 5 files changed, 1571 insertions(+) + drivers/mmc/host/bcm2835-mmc.c | 1558 +++++++++++++++++++++++++++++++++++++++ + 6 files changed, 1658 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5d8657b..d1308ed 100644 +index 6b0b6c4..5b10802 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -399,6 +399,34 @@ static struct platform_device bcm2708_systemtimer_device = { - }, +@@ -401,6 +401,34 @@ static struct platform_device bcm2708_gpio_device = { }; + #endif +#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ +static struct resource bcm2835_emmc_resources[] = { @@ -78065,35 +75672,97 @@ index 5d8657b..d1308ed 100644 +}; +#endif /* CONFIG_MMC_BCM2835 */ + - static struct resource bcm2708_powerman_resources[] = { - [0] = { - .start = PM_BASE, -@@ -524,6 +552,9 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -538,6 +566,9 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); +#ifdef CONFIG_MMC_BCM2835 -+ bcm_register_device(&bcm2835_emmc_device); ++ bcm_register_device_dt(&bcm2835_emmc_device); +#endif bcm2708_init_led(); + bcm2708_init_uart1(); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 86ebfbe..54c5444 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -421,6 +421,34 @@ static struct platform_device bcm2708_gpio_device = { + }; + #endif + ++#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ ++static struct resource bcm2835_emmc_resources[] = { ++ [0] = { ++ .start = EMMC_BASE, ++ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ ++ /* the memory map actually makes SZ_4K available */ ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_ARASANSDIO, ++ .end = IRQ_ARASANSDIO, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 bcm2835_emmc_dmamask = 0xffffffffUL; ++ ++struct platform_device bcm2835_emmc_device = { ++ .name = "mmc-bcm2835", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), ++ .resource = bcm2835_emmc_resources, ++ .dev = { ++ .dma_mask = &bcm2835_emmc_dmamask, ++ .coherent_dma_mask = 0xffffffffUL}, ++}; ++#endif /* CONFIG_MMC_BCM2835 */ ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -558,8 +586,11 @@ void __init bcm2709_init(void) + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +- bcm2708_init_led(); +- bcm2708_init_uart1(); ++#ifdef CONFIG_MMC_BCM2835 ++ bcm_register_device_dt(&bcm2835_emmc_device); ++#endif ++ bcm2709_init_led(); ++ bcm2709_init_uart1(); + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c -index dd1d1e0..f472082 100644 +index dd1d1e0..bc3bbad 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c -@@ -95,5 +95,9 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) +@@ -71,6 +71,7 @@ static const struct mmc_fixup mmc_fixup_methods[] = { + + void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) + { ++ extern unsigned mmc_debug; + const struct mmc_fixup *f; + u64 rev = cid_rev_card(card); + +@@ -95,5 +96,10 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) f->vendor_fixup(card, f->data); } } + /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail. + * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers). + */ ++ if (mmc_debug & (1<<13)) + card->quirks |= MMC_QUIRK_BLK_NO_CMD23; } EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 61ac63a..7c093a6 100644 +index b1f837e..0ef7417 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -4,6 +4,35 @@ @@ -78102,7 +75771,7 @@ index 61ac63a..7c093a6 100644 +config MMC_BCM2835 + tristate "MMC support on BCM2835" -+ depends on (MACH_BCM2708 || MACH_BCM2709) ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 + help + This selects the MMC Interface on BCM2835. + @@ -78133,7 +75802,7 @@ index 61ac63a..7c093a6 100644 tristate "ARM AMBA Multimedia Card Interface support" depends on ARM_AMBA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 6a7cfe0..9d41de9 100644 +index e3ab5b9..f1ee1f7 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o @@ -78146,10 +75815,10 @@ index 6a7cfe0..9d41de9 100644 obj-$(CONFIG_MMC_OMAP) += omap.o diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c new file mode 100644 -index 0000000..eef0d351 +index 0000000..b7c4883 --- /dev/null +++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -0,0 +1,1506 @@ +@@ -0,0 +1,1558 @@ +/* + * BCM2835 MMC host driver. + * @@ -78223,6 +75892,9 @@ index 0000000..eef0d351 +#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) + + ++unsigned mmc_debug; ++unsigned mmc_debug2; ++ +struct bcm2835_host { + spinlock_t lock; + @@ -78280,22 +75952,38 @@ index 0000000..eef0d351 +#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ +#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ +#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ ++ ++ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ ++ u32 max_overclock; /* Highest reported */ +}; + + -+static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) ++static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from) +{ ++ unsigned delay; ++ lockdep_assert_held_once(&host->lock); + writel(val, host->ioaddr + reg); + udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); ++ ++ delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf); ++ if (delay && !((1<lock); + writel(val, host->ioaddr + reg); ++ ++ delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf); ++ if (delay) ++ udelay(delay); +} + +static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) +{ ++ lockdep_assert_held_once(&host->lock); + return readl(host->ioaddr + reg); +} + @@ -78311,7 +75999,7 @@ index 0000000..eef0d351 + if (reg == SDHCI_TRANSFER_MODE) + host->shadow = newval; + else -+ bcm2835_mmc_writel(host, newval, reg & ~3); ++ bcm2835_mmc_writel(host, newval, reg & ~3, 0); + +} + @@ -78323,7 +76011,7 @@ index 0000000..eef0d351 + u32 mask = 0xff << byte_shift; + u32 newval = (oldval & ~mask) | (val << byte_shift); + -+ bcm2835_mmc_writel(host, newval, reg & ~3); ++ bcm2835_mmc_writel(host, newval, reg & ~3, 1); +} + + @@ -78355,7 +76043,7 @@ index 0000000..eef0d351 + ier &= ~clear; + /* change which requests generate IRQs - makes no difference to + the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ -+ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2); +} + + @@ -78407,7 +76095,9 @@ index 0000000..eef0d351 +static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) +{ + unsigned long timeout; ++ unsigned long flags; + ++ spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET); + + if (mask & SDHCI_RESET_ALL) @@ -78425,19 +76115,23 @@ index 0000000..eef0d351 + return; + } + timeout--; ++ spin_unlock_irqrestore(&host->lock, flags); + mdelay(1); ++ spin_lock_irqsave(&host->lock, flags); + } + + if (100-timeout > 10 && 100-timeout > host->max_delay) { + host->max_delay = 100-timeout; + pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay); + } ++ spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + +static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) +{ ++ unsigned long flags; + if (soft) + bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); + else @@ -78449,8 +76143,10 @@ index 0000000..eef0d351 + SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | + SDHCI_INT_RESPONSE; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ spin_lock_irqsave(&host->lock, flags); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3); ++ spin_unlock_irqrestore(&host->lock, flags); + + if (soft) { + /* force clock reconfiguration */ @@ -78649,11 +76345,14 @@ index 0000000..eef0d351 + dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); + } + if (desc) { ++ unsigned long flags; ++ spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + host->tx_desc = desc; + desc->callback = bcm2835_mmc_dma_complete; + desc->callback_param = host; ++ spin_unlock_irqrestore(&host->lock, flags); + dmaengine_submit(desc); + dma_async_issue_pending(dma_chan); + } @@ -78672,8 +76371,8 @@ index 0000000..eef0d351 + else + host->ier = (host->ier & ~dma_irqs) | pio_irqs; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4); +} + + @@ -78755,7 +76454,7 @@ index 0000000..eef0d351 + mode |= SDHCI_TRNS_AUTO_CMD12; + else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { + mode |= SDHCI_TRNS_AUTO_CMD23; -+ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); ++ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5); + } + } + @@ -78818,7 +76517,7 @@ index 0000000..eef0d351 + + bcm2835_mmc_prepare_data(host, cmd); + -+ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT); ++ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6); + + bcm2835_mmc_set_transfer_mode(host, cmd); + @@ -78975,8 +76674,8 @@ index 0000000..eef0d351 + else + host->ier &= ~SDHCI_INT_CARD_INT; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7); + mmiowb(); + } +} @@ -79123,7 +76822,7 @@ index 0000000..eef0d351 + /* Clear selected interrupts. */ + mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | + SDHCI_INT_BUS_POWER); -+ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS); ++ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8); + + + if (intmask & SDHCI_INT_CMD_MASK) @@ -79153,7 +76852,7 @@ index 0000000..eef0d351 + + if (intmask) { + unexpected |= intmask; -+ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS); ++ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9); + } + + if (result == IRQ_NONE) @@ -79211,7 +76910,10 @@ index 0000000..eef0d351 + int real_div = div, clk_mul = 1; + u16 clk = 0; + unsigned long timeout; ++ unsigned int input_clock = clock; + ++ if (host->overclock_50 && (clock == 50000000)) ++ clock = host->overclock_50 * 1000000 + 999999; + + host->mmc->actual_clock = 0; + @@ -79235,7 +76937,14 @@ index 0000000..eef0d351 + div >>= 1; + + if (real_div) -+ host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; ++ clock = (host->max_clk * clk_mul) / real_div; ++ host->mmc->actual_clock = clock; ++ ++ if ((clock > input_clock) && (clock > host->max_overclock)) { ++ pr_warn("%s: Overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->max_overclock = clock; ++ } + + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) @@ -79302,6 +77011,9 @@ index 0000000..eef0d351 + u8 ctrl; + u16 clk, ctrl_2; + ++ pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); + + spin_lock_irqsave(&host->lock, flags); + @@ -79395,8 +77107,10 @@ index 0000000..eef0d351 + (mrq->data && (mrq->data->error || + (mrq->data->stop && mrq->data->stop->error))))) { + ++ spin_unlock_irqrestore(&host->lock, flags); + bcm2835_mmc_reset(host, SDHCI_RESET_CMD); + bcm2835_mmc_reset(host, SDHCI_RESET_DATA); ++ spin_lock_irqsave(&host->lock, flags); + } + + host->mrq = NULL; @@ -79411,7 +77125,7 @@ index 0000000..eef0d351 + + + -+int bcm2835_mmc_add_host(struct bcm2835_host *host) ++static int bcm2835_mmc_add_host(struct bcm2835_host *host) +{ + struct mmc_host *mmc = host->mmc; + struct device *dev = mmc->parent; @@ -79439,8 +77153,7 @@ index 0000000..eef0d351 + + host->flags = SDHCI_AUTO_CMD23; + -+ spin_lock_init(&host->lock); -+ ++ dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2); +#ifdef FORCE_PIO + dev_info(dev, "Forcing PIO mode\n"); + host->have_dma = false; @@ -79568,10 +77281,16 @@ index 0000000..eef0d351 + goto err; + } + -+ if (node) ++ if (node) { + mmc_of_parse(mmc); -+ else ++ ++ /* Read any custom properties */ ++ of_property_read_u32(node, ++ "brcm,overclock-50", ++ &host->overclock_50); ++ } else { + mmc->caps |= MMC_CAP_4_BIT_DATA; ++ } + + ret = bcm2835_mmc_add_host(host); + if (ret) @@ -79652,15 +77371,1790 @@ index 0000000..eef0d351 +}; +module_platform_driver(bcm2835_mmc_driver); + ++module_param(mmc_debug, uint, 0644); ++module_param(mmc_debug2, uint, 0644); +MODULE_ALIAS("platform:mmc-bcm2835"); +MODULE_DESCRIPTION("BCM2835 SDHCI driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 97f9d94720b108ba3e793621d4a500cc593fc775 Mon Sep 17 00:00:00 2001 +From 81cff325dce6ba8765e23e542a219d3c9103a70b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 25 Mar 2015 17:49:47 +0000 +Subject: [PATCH 10/77] Adding bcm2835-sdhost driver, and an overlay to enable + it + +BCM2835 has two SD card interfaces. This driver uses the other one. + +bcm2835-sdhost: Error handling fix, and code clarification + +bcm2835-sdhost: Adding overclocking option + +Allow a different clock speed to be substitued for a requested 50MHz. +This option is exposed using the "overclock_50" DT parameter. +Note that the sdhost interface is restricted to integer divisions of +core_freq, and the highest sensible option for a core_freq of 250MHz +is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too +high. + +Use at your own risk. + +bcm2835-sdhost: Round up the overclock, so 62 works for 62.5Mhz + +Also only warn once for each overclock setting. +--- + drivers/mmc/host/Kconfig | 10 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/bcm2835-sdhost.c | 1702 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 1713 insertions(+) + create mode 100644 drivers/mmc/host/bcm2835-sdhost.c + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 0ef7417..1af139a 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER + + If unsure, say 2 here. + ++config MMC_BCM2835_SDHOST ++ tristate "Support for the SDHost controller on BCM2708/9" ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ help ++ This selects the SDHost controller on BCM2835/6. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_ARMMMCI + tristate "ARM AMBA Multimedia Card Interface support" + depends on ARM_AMBA +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index f1ee1f7..8c656a5 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o + obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o + obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o + obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o ++obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o + obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o + obj-$(CONFIG_MMC_WBSD) += wbsd.o + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +new file mode 100644 +index 0000000..eef8a24 +--- /dev/null ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -0,0 +1,1702 @@ ++/* ++ * BCM2835 SD host driver. ++ * ++ * Author: Phil Elwell ++ * Copyright 2015 ++ * ++ * Based on ++ * mmc-bcm2835.c by Gellert Weisz ++ * which is, in turn, based on ++ * sdhci-bcm2708.c by Broadcom ++ * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko ++ * sdhci.c and sdhci-pci.c by Pierre Ossman ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#define SAFE_READ_THRESHOLD 4 ++#define SAFE_WRITE_THRESHOLD 4 ++#define ALLOW_DMA 1 ++#define ALLOW_CMD23 0 ++#define ALLOW_FAST 1 ++#define USE_BLOCK_IRQ 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "sdhost-bcm2835" ++ ++#define SDCMD 0x00 /* Command to SD card - 16 R/W */ ++#define SDARG 0x04 /* Argument to SD card - 32 R/W */ ++#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ ++#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ ++#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ ++#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ ++#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ ++#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ ++#define SDHSTS 0x20 /* SD host status - 11 R */ ++#define SDVDD 0x30 /* SD card power control - 1 R/W */ ++#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ ++#define SDHCFG 0x38 /* Host configuration - 2 R/W */ ++#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ ++#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ ++#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ ++ ++#define SDCMD_NEW_FLAG 0x8000 ++#define SDCMD_FAIL_FLAG 0x4000 ++#define SDCMD_BUSYWAIT 0x800 ++#define SDCMD_NO_RESPONSE 0x400 ++#define SDCMD_LONG_RESPONSE 0x200 ++#define SDCMD_WRITE_CMD 0x80 ++#define SDCMD_READ_CMD 0x40 ++#define SDCMD_CMD_MASK 0x3f ++ ++#define SDCDIV_MAX_CDIV 0x7ff ++ ++#define SDHSTS_BUSY_IRPT 0x400 ++#define SDHSTS_BLOCK_IRPT 0x200 ++#define SDHSTS_SDIO_IRPT 0x100 ++#define SDHSTS_REW_TIME_OUT 0x80 ++#define SDHSTS_CMD_TIME_OUT 0x40 ++#define SDHSTS_CRC16_ERROR 0x20 ++#define SDHSTS_CRC7_ERROR 0x10 ++#define SDHSTS_FIFO_ERROR 0x08 ++/* Reserved */ ++/* Reserved */ ++#define SDHSTS_DATA_FLAG 0x01 ++ ++#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) ++#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) ++/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ ++ ++#define SDHCFG_BUSY_IRPT_EN (1<<10) ++#define SDHCFG_BLOCK_IRPT_EN (1<<8) ++#define SDHCFG_SDIO_IRPT_EN (1<<5) ++#define SDHCFG_DATA_IRPT_EN (1<<4) ++#define SDHCFG_SLOW_CARD (1<<3) ++#define SDHCFG_WIDE_EXT_BUS (1<<2) ++#define SDHCFG_WIDE_INT_BUS (1<<1) ++#define SDHCFG_REL_CMD_LINE (1<<0) ++ ++#define SDEDM_FORCE_DATA_MODE (1<<19) ++#define SDEDM_CLOCK_PULSE (1<<20) ++#define SDEDM_BYPASS (1<<21) ++ ++#define SDEDM_WRITE_THRESHOLD_SHIFT 9 ++#define SDEDM_READ_THRESHOLD_SHIFT 14 ++#define SDEDM_THRESHOLD_MASK 0x1f ++ ++/* the inclusive limit in bytes under which PIO will be used instead of DMA */ ++#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER ++#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER ++#else ++#define PIO_DMA_BARRIER 0 ++#endif ++ ++#define MIN_FREQ 400000 ++#define TIMEOUT_VAL 0xE ++#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) ++ ++#ifndef BCM2708_PERI_BASE ++ #define BCM2708_PERI_BASE 0x20000000 ++#endif ++ ++/* FIXME: Needs IOMMU support */ ++#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) ++ ++ ++struct bcm2835_host { ++ spinlock_t lock; ++ ++ void __iomem *ioaddr; ++ u32 phys_addr; ++ ++ struct mmc_host *mmc; ++ ++ u32 timeout; ++ ++ int clock; /* Current clock speed */ ++ ++ bool slow_card; /* Force 11-bit divisor */ ++ ++ unsigned int max_clk; /* Max possible freq */ ++ unsigned int timeout_clk; /* Timeout freq (KHz) */ ++ ++ struct tasklet_struct finish_tasklet; /* Tasklet structures */ ++ ++ struct timer_list timer; /* Timer for timeouts */ ++ ++ struct sg_mapping_iter sg_miter; /* SG state for PIO */ ++ unsigned int blocks; /* remaining PIO blocks */ ++ ++ int irq; /* Device IRQ */ ++ ++ ++ /* cached registers */ ++ u32 hcfg; ++ u32 cdiv; ++ ++ struct mmc_request *mrq; /* Current request */ ++ struct mmc_command *cmd; /* Current command */ ++ struct mmc_data *data; /* Current data request */ ++ unsigned int data_complete:1; /* Data finished before cmd */ ++ ++ unsigned int flush_fifo:1; /* Drain the fifo when finishing */ ++ ++ unsigned int use_busy:1; /* Wait for busy interrupt */ ++ ++ u32 thread_isr; ++ ++ /*DMA part*/ ++ struct dma_chan *dma_chan_rx; /* DMA channel for reads */ ++ struct dma_chan *dma_chan_tx; /* DMA channel for writes */ ++ ++ bool allow_dma; ++ bool have_dma; ++ bool use_dma; ++ /*end of DMA part*/ ++ ++ int max_delay; /* maximum length of time spent waiting */ ++ struct timeval stop_time; /* when the last stop was issued */ ++ u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ ++ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ ++ u32 max_overclock; /* Highest reported */ ++}; ++ ++ ++static inline void bcm2835_sdhost_write(struct bcm2835_host *host, u32 val, int reg) ++{ ++ writel(val, host->ioaddr + reg); ++} ++ ++static inline u32 bcm2835_sdhost_read(struct bcm2835_host *host, int reg) ++{ ++ return readl(host->ioaddr + reg); ++} ++ ++static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg) ++{ ++ return readl_relaxed(host->ioaddr + reg); ++} ++ ++static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) ++{ ++ pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", ++ mmc_hostname(host->mmc)); ++ ++ pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", ++ bcm2835_sdhost_read(host, SDCMD)); ++ pr_info(DRIVER_NAME ": SDARG 0x%08x\n", ++ bcm2835_sdhost_read(host, SDARG)); ++ pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", ++ bcm2835_sdhost_read(host, SDTOUT)); ++ pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", ++ bcm2835_sdhost_read(host, SDCDIV)); ++ pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP0)); ++ pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP1)); ++ pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP2)); ++ pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP3)); ++ pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHSTS)); ++ pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", ++ bcm2835_sdhost_read(host, SDVDD)); ++ pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", ++ bcm2835_sdhost_read(host, SDEDM)); ++ pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHCFG)); ++ pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHBCT)); ++ pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHBLC)); ++ ++ pr_debug(DRIVER_NAME ": ===========================================\n"); ++} ++ ++ ++static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) ++{ ++ bcm2835_sdhost_write(host, on ? 1 : 0, SDVDD); ++} ++ ++ ++static void bcm2835_sdhost_reset(struct bcm2835_host *host) ++{ ++ u32 temp; ++ ++ pr_debug("bcm2835_sdhost_reset\n"); ++ ++ bcm2835_sdhost_set_power(host, false); ++ ++ bcm2835_sdhost_write(host, 0, SDCMD); ++ bcm2835_sdhost_write(host, 0, SDARG); ++ bcm2835_sdhost_write(host, 0xf00000, SDTOUT); ++ bcm2835_sdhost_write(host, 0, SDCDIV); ++ bcm2835_sdhost_write(host, 0x7f8, SDHSTS); /* Write 1s to clear */ ++ bcm2835_sdhost_write(host, 0, SDHCFG); ++ bcm2835_sdhost_write(host, 0, SDHBCT); ++ bcm2835_sdhost_write(host, 0, SDHBLC); ++ ++ /* Limit fifo usage due to silicon bug */ ++ temp = bcm2835_sdhost_read(host, SDEDM); ++ temp &= ~((SDEDM_THRESHOLD_MASK<clock = 0; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ mmiowb(); ++} ++ ++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); ++ ++static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) ++{ ++ pr_debug("bcm2835_sdhost_init(%d)\n", soft); ++ ++ /* Set interrupt enables */ ++ host->hcfg = SDHCFG_BUSY_IRPT_EN; ++ ++ bcm2835_sdhost_reset(host); ++ ++ if (soft) { ++ /* force clock reconfiguration */ ++ host->clock = 0; ++ bcm2835_sdhost_set_ios(host->mmc, &host->mmc->ios); ++ } ++} ++ ++static bool bcm2835_sdhost_is_write_complete(struct bcm2835_host *host) ++{ ++ bool write_complete = ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1); ++ ++ if (!write_complete) { ++ /* Request an IRQ for the last block */ ++ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ if ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1) { ++ /* The write has now completed. Disable the interrupt ++ and clear the status flag */ ++ host->hcfg &= ~SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ bcm2835_sdhost_write(host, SDHSTS_BLOCK_IRPT, SDHSTS); ++ write_complete = true; ++ } ++ } ++ ++ return write_complete; ++} ++ ++static void bcm2835_sdhost_wait_write_complete(struct bcm2835_host *host) ++{ ++ int timediff; ++#ifdef DEBUG ++ static struct timeval start_time; ++ static int max_stall_time = 0; ++ static int total_stall_time = 0; ++ struct timeval before, after; ++ ++ do_gettimeofday(&before); ++ if (max_stall_time == 0) ++ start_time = before; ++#endif ++ ++ timediff = 0; ++ ++ while (1) { ++ u32 edm = bcm2835_sdhost_read(host, SDEDM); ++ if ((edm & 0xf) == 1) ++ break; ++ timediff++; ++ if (timediff > 5000000) { ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + ++ (after.tv_usec - before.tv_usec); ++ ++ pr_err(" wait_write_complete - still waiting after %dus\n", ++ timediff); ++#else ++ pr_err(" wait_write_complete - still waiting after %d retries\n", ++ timediff); ++#endif ++ bcm2835_sdhost_dumpregs(host); ++ host->data->error = -ETIMEDOUT; ++ return; ++ } ++ } ++ ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + (after.tv_usec - before.tv_usec); ++ ++ total_stall_time += timediff; ++ if (timediff > max_stall_time) ++ max_stall_time = timediff; ++ ++ if ((after.tv_sec - start_time.tv_sec) > 10) { ++ pr_debug(" wait_write_complete - max wait %dus, total %dus\n", ++ max_stall_time, total_stall_time); ++ start_time = after; ++ max_stall_time = 0; ++ total_stall_time = 0; ++ } ++#endif ++} ++ ++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host); ++ ++static void bcm2835_sdhost_dma_complete(void *param) ++{ ++ struct bcm2835_host *host = param; ++ struct dma_chan *dma_chan; ++ unsigned long flags; ++ u32 dir_data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->data) { ++ bool write_complete; ++ if (USE_BLOCK_IRQ) ++ write_complete = bcm2835_sdhost_is_write_complete(host); ++ else { ++ bcm2835_sdhost_wait_write_complete(host); ++ write_complete = true; ++ } ++ pr_debug("dma_complete() - write_complete=%d\n", ++ write_complete); ++ ++ if (write_complete || (host->data->flags & MMC_DATA_READ)) ++ { ++ if (write_complete) { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ } else { ++ dma_chan = host->dma_chan_rx; ++ dir_data = DMA_FROM_DEVICE; ++ } ++ ++ dma_unmap_sg(dma_chan->device->dev, ++ host->data->sg, host->data->sg_len, ++ dir_data); ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) ++{ ++ unsigned long flags; ++ size_t blksize, len; ++ u32 *buf; ++ ++ blksize = host->data->blksz; ++ ++ local_irq_save(flags); ++ ++ while (blksize) { ++ if (!sg_miter_next(&host->sg_miter)) ++ BUG(); ++ ++ len = min(host->sg_miter.length, blksize); ++ BUG_ON(len % 4); ++ ++ blksize -= len; ++ host->sg_miter.consumed = len; ++ ++ buf = (u32 *)host->sg_miter.addr; ++ ++ while (len) { ++ while (1) { ++ u32 hsts; ++ hsts = bcm2835_sdhost_read(host, SDHSTS); ++ if (hsts & SDHSTS_DATA_FLAG) ++ break; ++ ++ if (hsts & SDHSTS_ERROR_MASK) { ++ pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", ++ mmc_hostname(host->mmc), ++ hsts, ++ bcm2835_sdhost_read(host, SDHBCT), ++ blksize + len); ++ if (hsts & SDHSTS_REW_TIME_OUT) ++ host->data->error = -ETIMEDOUT; ++ else if (hsts & (SDHSTS_CRC16_ERROR || ++ SDHSTS_CRC7_ERROR)) ++ host->data->error = -EILSEQ; ++ else { ++ pr_err("%s: unexpected data error\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ } ++ } ++ } ++ ++ *(buf++) = bcm2835_sdhost_read(host, SDDATA); ++ len -= 4; ++ } ++ } ++ ++ sg_miter_stop(&host->sg_miter); ++ ++ local_irq_restore(flags); ++} ++ ++static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) ++{ ++ unsigned long flags; ++ size_t blksize, len; ++ u32 *buf; ++ ++ blksize = host->data->blksz; ++ ++ local_irq_save(flags); ++ ++ while (blksize) { ++ if (!sg_miter_next(&host->sg_miter)) ++ BUG(); ++ ++ len = min(host->sg_miter.length, blksize); ++ BUG_ON(len % 4); ++ ++ blksize -= len; ++ host->sg_miter.consumed = len; ++ ++ buf = host->sg_miter.addr; ++ ++ while (len) { ++ while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) ++ continue; ++ bcm2835_sdhost_write(host, *(buf++), SDDATA); ++ len -= 4; ++ } ++ } ++ ++ sg_miter_stop(&host->sg_miter); ++ ++ local_irq_restore(flags); ++} ++ ++ ++static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) ++{ ++ BUG_ON(!host->data); ++ ++ if (host->data->flags & MMC_DATA_READ) ++ bcm2835_sdhost_read_block_pio(host); ++ else ++ bcm2835_sdhost_write_block_pio(host); ++} ++ ++ ++static void bcm2835_sdhost_transfer_dma(struct bcm2835_host *host) ++{ ++ u32 len, dir_data, dir_slave; ++ struct dma_async_tx_descriptor *desc = NULL; ++ struct dma_chan *dma_chan; ++ ++ pr_debug("bcm2835_sdhost_transfer_dma()\n"); ++ ++ WARN_ON(!host->data); ++ ++ if (!host->data) ++ return; ++ ++ if (host->data->flags & MMC_DATA_READ) { ++ dma_chan = host->dma_chan_rx; ++ dir_data = DMA_FROM_DEVICE; ++ dir_slave = DMA_DEV_TO_MEM; ++ } else { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ dir_slave = DMA_MEM_TO_DEV; ++ } ++ ++ BUG_ON(!dma_chan->device); ++ BUG_ON(!dma_chan->device->dev); ++ BUG_ON(!host->data->sg); ++ ++ len = dma_map_sg(dma_chan->device->dev, host->data->sg, ++ host->data->sg_len, dir_data); ++ if (len > 0) { ++ desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg, ++ len, dir_slave, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ } else { ++ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); ++ } ++ if (desc) { ++ desc->callback = bcm2835_sdhost_dma_complete; ++ desc->callback_param = host; ++ dmaengine_submit(desc); ++ dma_async_issue_pending(dma_chan); ++ } ++ ++} ++ ++ ++static void bcm2835_sdhost_set_transfer_irqs(struct bcm2835_host *host) ++{ ++ u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN | ++ SDHCFG_BUSY_IRPT_EN; ++ if (host->use_dma) ++ host->hcfg = (host->hcfg & ~all_irqs) | ++ SDHCFG_BUSY_IRPT_EN; ++ else ++ host->hcfg = (host->hcfg & ~all_irqs) | ++ SDHCFG_DATA_IRPT_EN | ++ SDHCFG_BUSY_IRPT_EN; ++ ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++} ++ ++ ++static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd) ++{ ++ struct mmc_data *data = cmd->data; ++ ++ WARN_ON(host->data); ++ ++ if (!data) ++ return; ++ ++ /* Sanity checks */ ++ BUG_ON(data->blksz * data->blocks > 524288); ++ BUG_ON(data->blksz > host->mmc->max_blk_size); ++ BUG_ON(data->blocks > 65535); ++ ++ host->data = data; ++ host->data_complete = 0; ++ host->flush_fifo = 0; ++ host->data->bytes_xfered = 0; ++ ++ if (!host->use_dma) { ++ int flags; ++ ++ flags = SG_MITER_ATOMIC; ++ if (data->flags & MMC_DATA_READ) ++ flags |= SG_MITER_TO_SG; ++ else ++ flags |= SG_MITER_FROM_SG; ++ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); ++ host->blocks = data->blocks; ++ } ++ ++ host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; ++ ++ bcm2835_sdhost_set_transfer_irqs(host); ++ ++ bcm2835_sdhost_write(host, data->blksz, SDHBCT); ++ if (host->use_dma) ++ bcm2835_sdhost_write(host, data->blocks, SDHBLC); ++ ++ BUG_ON(!host->data); ++} ++ ++ ++void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd) ++{ ++ u32 sdcmd; ++ unsigned long timeout; ++ ++ WARN_ON(host->cmd); ++ ++ if (1) { ++ pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", ++ cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); ++ if (cmd->data) ++ pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ } ++ ++ /* Wait max 10 ms */ ++ timeout = 1000; ++ ++ while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { ++ if (timeout == 0) { ++ pr_err("%s: Previous command never completed.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ timeout--; ++ udelay(10); ++ } ++ ++ if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { ++ host->max_delay = (1000-timeout)/100; ++ pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); ++ } ++ ++ timeout = jiffies; ++#ifdef CONFIG_ARCH_BCM2835 ++ if (!cmd->data && cmd->busy_timeout > 9000) ++ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; ++ else ++#endif ++ timeout += 10 * HZ; ++ mod_timer(&host->timer, timeout); ++ ++ host->cmd = cmd; ++ ++ bcm2835_sdhost_prepare_data(host, cmd); ++ ++ bcm2835_sdhost_write(host, cmd->arg, SDARG); ++ ++ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { ++ pr_err("%s: Unsupported response type!\n", ++ mmc_hostname(host->mmc)); ++ cmd->error = -EINVAL; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ sdcmd = cmd->opcode & SDCMD_CMD_MASK; ++ ++ if (!(cmd->flags & MMC_RSP_PRESENT)) ++ sdcmd |= SDCMD_NO_RESPONSE; ++ else { ++ if (cmd->flags & MMC_RSP_136) ++ sdcmd |= SDCMD_LONG_RESPONSE; ++ if (cmd->flags & MMC_RSP_BUSY) { ++ sdcmd |= SDCMD_BUSYWAIT; ++ host->use_busy = 1; ++ } ++ } ++ ++ if (cmd->data) { ++ if (host->delay_after_stop) { ++ struct timeval now; ++ int time_since_stop; ++ do_gettimeofday(&now); ++ time_since_stop = (now.tv_sec - host->stop_time.tv_sec); ++ if (time_since_stop < 2) { ++ /* Possibly less than one second */ ++ time_since_stop = time_since_stop * 1000000 + ++ (now.tv_usec - host->stop_time.tv_usec); ++ if (time_since_stop < host->delay_after_stop) ++ udelay(host->delay_after_stop - ++ time_since_stop); ++ } ++ } ++ ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ sdcmd |= SDCMD_WRITE_CMD; ++ if (cmd->data->flags & MMC_DATA_READ) ++ sdcmd |= SDCMD_READ_CMD; ++ } ++ ++ bcm2835_sdhost_write(host, sdcmd | SDCMD_NEW_FLAG, SDCMD); ++} ++ ++ ++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host); ++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host); ++ ++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host) ++{ ++ struct mmc_data *data; ++ ++ data = host->data; ++ BUG_ON(!data); ++ ++ pr_debug("finish_data(error %d, stop %d, sbc %d)\n", ++ data->error, data->stop ? 1 : 0, ++ host->mrq->sbc ? 1 : 0); ++ ++ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ ++ if (data->error) { ++ data->bytes_xfered = 0; ++ } else ++ data->bytes_xfered = data->blksz * data->blocks; ++ ++ host->data_complete = 1; ++ ++ if (host->cmd) { ++ /* ++ * Data managed to finish before the ++ * command completed. Make sure we do ++ * things in the proper order. ++ */ ++ pr_debug("Finished early - HSTS %x\n", ++ bcm2835_sdhost_read(host, SDHSTS)); ++ } ++ else ++ bcm2835_sdhost_transfer_complete(host); ++} ++ ++ ++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) ++{ ++ struct mmc_data *data; ++ ++ BUG_ON(host->cmd); ++ BUG_ON(!host->data); ++ BUG_ON(!host->data_complete); ++ ++ data = host->data; ++ host->data = NULL; ++ ++ pr_debug("transfer_complete(error %d, stop %d)\n", ++ data->error, data->stop ? 1 : 0); ++ ++ if (data->error) ++ /* ++ * The controller needs a reset of internal state machines ++ * upon error conditions. ++ */ ++ bcm2835_sdhost_reset(host); ++ ++ /* ++ * Need to send CMD12 if - ++ * a) open-ended multiblock transfer (no CMD23) ++ * b) error in multiblock transfer ++ */ ++ if (data->stop && ++ (data->error || ++ !host->mrq->sbc)) { ++ host->flush_fifo = 1; ++ bcm2835_sdhost_send_command(host, data->stop); ++ if (host->delay_after_stop) ++ do_gettimeofday(&host->stop_time); ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++ } else { ++ tasklet_schedule(&host->finish_tasklet); ++ } ++} ++ ++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) ++{ ++ u32 sdcmd; ++ int timeout = 1000; ++#ifdef DEBUG ++ struct timeval before, after; ++ int timediff = 0; ++#endif ++ ++ pr_debug("finish_command(%x)\n", bcm2835_sdhost_read(host, SDCMD)); ++ ++ BUG_ON(!host->cmd || !host->mrq); ++ ++#ifdef DEBUG ++ do_gettimeofday(&before); ++#endif ++ for (sdcmd = bcm2835_sdhost_read(host, SDCMD); ++ (sdcmd & SDCMD_NEW_FLAG) && timeout; ++ timeout--) { ++ if (host->flush_fifo) { ++ while (bcm2835_sdhost_read(host, SDHSTS) & ++ SDHSTS_DATA_FLAG) ++ (void)bcm2835_sdhost_read(host, SDDATA); ++ } ++ udelay(10); ++ sdcmd = bcm2835_sdhost_read(host, SDCMD); ++ } ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + ++ (after.tv_usec - before.tv_usec); ++ ++ pr_debug(" finish_command - waited %dus\n", timediff); ++#endif ++ ++ if (timeout == 0) { ++ pr_err("%s: Command never completed.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ if (host->flush_fifo) { ++ for (timeout = 100; ++ (bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG) && timeout; ++ timeout--) { ++ (void)bcm2835_sdhost_read(host, SDDATA); ++ } ++ host->flush_fifo = 0; ++ if (timeout == 0) { ++ pr_err("%s: FIFO never drained.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ } ++ ++ /* Check for errors */ ++ if (sdcmd & SDCMD_FAIL_FLAG) ++ { ++ u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); ++ ++ pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", ++ mmc_hostname(host->mmc), sdcmd, sdhsts, ++ bcm2835_sdhost_read(host, SDEDM)); ++ ++ if (sdhsts & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else ++ { ++ pr_err("%s: unexpected command error\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ } ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ if (host->cmd->flags & MMC_RSP_PRESENT) { ++ if (host->cmd->flags & MMC_RSP_136) { ++ int i; ++ for (i = 0; i < 4; i++) ++ host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); ++ pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", ++ host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); ++ } else { ++ host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); ++ pr_debug("bcm2835_sdhost_finish_command: %08x\n", ++ host->cmd->resp[0]); ++ } ++ } ++ ++ host->cmd->error = 0; ++ ++ if (host->cmd == host->mrq->sbc) { ++ /* Finished CMD23, now send actual command. */ ++ host->cmd = NULL; ++ bcm2835_sdhost_send_command(host, host->mrq->cmd); ++ ++ if (host->cmd->data && host->use_dma) ++ /* DMA transfer starts now, PIO starts after irq */ ++ bcm2835_sdhost_transfer_dma(host); ++ ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++ } else if (host->cmd == host->mrq->stop) ++ /* Finished CMD12 */ ++ tasklet_schedule(&host->finish_tasklet); ++ else { ++ /* Processed actual command. */ ++ host->cmd = NULL; ++ if (!host->data) ++ tasklet_schedule(&host->finish_tasklet); ++ else if (host->data_complete) ++ bcm2835_sdhost_transfer_complete(host); ++ } ++} ++ ++static void bcm2835_sdhost_timeout_timer(unsigned long data) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ host = (struct bcm2835_host *)data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->mrq) { ++ pr_err("%s: Timeout waiting for hardware interrupt.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ ++ if (host->data) { ++ host->data->error = -ETIMEDOUT; ++ bcm2835_sdhost_finish_data(host); ++ } else { ++ if (host->cmd) ++ host->cmd->error = -ETIMEDOUT; ++ else ++ host->mrq->cmd->error = -ETIMEDOUT; ++ ++ pr_debug("timeout_timer tasklet_schedule\n"); ++ tasklet_schedule(&host->finish_tasklet); ++ } ++ } ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) ++{ ++ if (enable) ++ host->hcfg |= SDHCFG_SDIO_IRPT_EN; ++ else ++ host->hcfg &= ~SDHCFG_SDIO_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ mmiowb(); ++} ++ ++static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ ++ pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); ++ spin_lock_irqsave(&host->lock, flags); ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ if (!host->cmd) { ++ pr_err("%s: Got command busy interrupt 0x%08x even " ++ "though no command operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return 0; ++ } ++ ++ if (!host->use_busy) { ++ pr_err("%s: Got command busy interrupt 0x%08x even " ++ "though not expecting one.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return 0; ++ } ++ host->use_busy = 0; ++ ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->cmd->error = -EILSEQ; ++ ++ if (host->cmd->error) ++ tasklet_schedule(&host->finish_tasklet); ++ else ++ bcm2835_sdhost_finish_command(host); ++ ++ return handled; ++} ++ ++static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ /* There are no dedicated data/space available interrupt ++ status bits, so it is necessary to use the single shared ++ data/space available FIFO status bits. It is therefore not ++ an error to get here when there is no data transfer in ++ progress. */ ++ if (!host->data) ++ return 0; ++ ++ // XXX FIFO_ERROR ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && ++ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) ++ != MMC_BUS_TEST_R)) ++ host->cmd->error = -EILSEQ; ++ ++ /* Use the block interrupt for writes after the first block */ ++ if (host->data->flags & MMC_DATA_WRITE) { ++ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); ++ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ if (host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ else ++ bcm2835_sdhost_transfer_pio(host); ++ } else { ++ if (!host->data->error) { ++ bcm2835_sdhost_transfer_pio(host); ++ host->blocks--; ++ } ++ if ((host->blocks == 0) || host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ return handled; ++} ++ ++static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ struct dma_chan *dma_chan; ++ u32 dir_data; ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ if (!host->data) { ++ pr_err("%s: Got block interrupt 0x%08x even " ++ "though no data operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return handled; ++ } ++ ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && ++ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) ++ != MMC_BUS_TEST_R)) ++ host->cmd->error = -EILSEQ; ++ ++ if (!host->use_dma) { ++ BUG_ON(!host->blocks); ++ host->blocks--; ++ if ((host->blocks == 0) || host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ else ++ bcm2835_sdhost_transfer_pio(host); ++ } else if (host->data->flags & MMC_DATA_WRITE) { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ dma_unmap_sg(dma_chan->device->dev, ++ host->data->sg, host->data->sg_len, ++ dir_data); ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ return handled; ++} ++ ++ ++static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) ++{ ++ irqreturn_t result = IRQ_NONE; ++ struct bcm2835_host *host = dev_id; ++ u32 unexpected = 0, early = 0; ++ int loops = 0; ++#ifndef CONFIG_ARCH_BCM2835 ++ int cardint = 0; ++#endif ++ spin_lock(&host->lock); ++ ++ for (loops = 0; loops < 1; loops++) { ++ u32 intmask, handled; ++ ++ intmask = bcm2835_sdhost_read(host, SDHSTS); ++ handled = intmask & (SDHSTS_BUSY_IRPT | ++ SDHSTS_BLOCK_IRPT | ++ SDHSTS_SDIO_IRPT | ++ SDHSTS_DATA_FLAG); ++ if ((handled == SDHSTS_DATA_FLAG) && // XXX ++ (loops == 0) && !host->data) { ++ pr_err("%s: sdhost_irq data interrupt 0x%08x even " ++ "though no data operation was in progress.\n", ++ mmc_hostname(host->mmc), ++ (unsigned)intmask); ++ ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++ if (!handled) ++ break; ++ ++ if (loops) ++ early |= handled; ++ ++ result = IRQ_HANDLED; ++ ++ /* Clear all interrupts and notifications */ ++ bcm2835_sdhost_write(host, intmask, SDHSTS); ++ ++ if (intmask & SDHSTS_BUSY_IRPT) ++ handled |= bcm2835_sdhost_busy_irq(host, intmask); ++ ++ /* There is no true data interrupt status bit, so it is ++ necessary to qualify the data flag with the interrupt ++ enable bit */ ++ if ((intmask & SDHSTS_DATA_FLAG) && ++ (host->hcfg & SDHCFG_DATA_IRPT_EN)) ++ handled |= bcm2835_sdhost_data_irq(host, intmask); ++ ++ if (intmask & SDHSTS_BLOCK_IRPT) ++ handled |= bcm2835_sdhost_block_irq(host, intmask); ++ ++ if (intmask & SDHSTS_SDIO_IRPT) { ++#ifndef CONFIG_ARCH_BCM2835 ++ cardint = 1; ++#else ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, false); ++ host->thread_isr |= SDHSTS_SDIO_IRPT; ++ result = IRQ_WAKE_THREAD; ++#endif ++ } ++ ++ unexpected |= (intmask & ~handled); ++ } ++ ++ mmiowb(); ++ ++ spin_unlock(&host->lock); ++ ++ if (early) ++ pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); ++ ++ if (unexpected) { ++ pr_err("%s: Unexpected interrupt 0x%08x.\n", ++ mmc_hostname(host->mmc), unexpected); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++#ifndef CONFIG_ARCH_BCM2835 ++ if (cardint) ++ mmc_signal_sdio_irq(host->mmc); ++#endif ++ ++ return result; ++} ++ ++#ifdef CONFIG_ARCH_BCM2835 ++static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) ++{ ++ struct bcm2835_host *host = dev_id; ++ unsigned long flags; ++ u32 isr; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ isr = host->thread_isr; ++ host->thread_isr = 0; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (isr & SDHSTS_SDIO_IRPT) { ++ sdio_run_irqs(host->mmc); ++ ++/* Is this necessary? Why re-enable an interrupt which is enabled? ++ spin_lock_irqsave(&host->lock, flags); ++ if (host->flags & SDHSTS_SDIO_IRPT_ENABLED) ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, true); ++ spin_unlock_irqrestore(&host->lock, flags); ++*/ ++ } ++ ++ return isr ? IRQ_HANDLED : IRQ_NONE; ++} ++#endif ++ ++ ++ ++void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) ++{ ++ int div = 0; /* Initialized for compiler warning */ ++ unsigned int input_clock = clock; ++ ++ if (host->overclock_50 && (clock == 50000000)) ++ clock = host->overclock_50 * 1000000 + 999999; ++ ++ /* The SDCDIV register has 11 bits, and holds (div - 2). ++ But in data mode the max is 50MHz wihout a minimum, and only the ++ bottom 3 bits are used. Since the switch over is automatic (unless ++ we have marked the card as slow...), chosen values have to make ++ sense in both modes. ++ Ident mode must be 100-400KHz, so can range check the requested ++ clock. CMD15 must be used to return to data mode, so this can be ++ monitored. ++ ++ clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz ++ 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz ++ ++ 623->400KHz/27.8MHz ++ reset value (507)->491159/50MHz ++ ++ BUT, the 3-bit clock divisor in data mode is too small if the ++ core clock is higher than 250MHz, so instead use the SLOW_CARD ++ configuration bit to force the use of the ident clock divisor ++ at all times. ++ */ ++ ++ host->mmc->actual_clock = 0; ++ ++ if (clock < 100000) { ++ /* Can't stop the clock, but make it as slow as possible ++ * to show willing ++ */ ++ host->cdiv = SDCDIV_MAX_CDIV; ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ return; ++ } ++ ++ div = host->max_clk / clock; ++ if (div < 2) ++ div = 2; ++ if ((host->max_clk / div) > clock) ++ div++; ++ div -= 2; ++ ++ if (div > SDCDIV_MAX_CDIV) ++ div = SDCDIV_MAX_CDIV; ++ ++ clock = host->max_clk / (div + 2); ++ host->mmc->actual_clock = clock; ++ ++ if ((clock > input_clock) && (clock > host->max_overclock)) { ++ pr_warn("%s: Overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->max_overclock = clock; ++ } ++ ++ host->cdiv = div; ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ ++ pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", ++ input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); ++} ++ ++static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ if (1) { ++ struct mmc_command *cmd = mrq->cmd; ++ const char *src = "cmd"; ++ BUG_ON(!cmd); ++ pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", ++ src, cmd->opcode, cmd->arg, cmd->flags); ++ if (cmd->data) ++ pr_debug("bcm2835_sdhost_request: %s %d*%d\n", ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ } ++ ++ if (mrq->data && !is_power_of_2(mrq->data->blksz)) { ++ pr_err("%s: Unsupported block size (%d bytes)\n", ++ mmc_hostname(mmc), mrq->data->blksz); ++ mrq->cmd->error = -EINVAL; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ host = mmc_priv(mmc); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ WARN_ON(host->mrq != NULL); ++ ++ host->mrq = mrq; ++ ++ if (mrq->sbc) ++ bcm2835_sdhost_send_command(host, mrq->sbc); ++ else ++ bcm2835_sdhost_send_command(host, mrq->cmd); ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (!mrq->sbc && mrq->cmd->data && host->use_dma) ++ /* DMA transfer starts now, PIO starts after irq */ ++ bcm2835_sdhost_transfer_dma(host); ++ ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++} ++ ++ ++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ ++ pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (!ios->clock || ios->clock != host->clock) { ++ bcm2835_sdhost_set_clock(host, ios->clock); ++ host->clock = ios->clock; ++ } ++ ++ /* set bus width */ ++ host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; ++ if (ios->bus_width == MMC_BUS_WIDTH_4) ++ host->hcfg |= SDHCFG_WIDE_EXT_BUS; ++ ++ host->hcfg |= SDHCFG_WIDE_INT_BUS; ++ ++ /* Disable clever clock switching, to cope with fast core clocks */ ++ host->hcfg |= SDHCFG_SLOW_CARD; ++ ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ ++ mmiowb(); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static int bcm2835_sdhost_multi_io_quirk(struct mmc_card *card, ++ unsigned int direction, ++ u32 blk_pos, int blk_size) ++{ ++ /* There is a bug in the host controller hardware that makes ++ reading the final sector of the card as part of a multiple read ++ problematic. Detect that case and shorten the read accordingly. ++ */ ++ /* csd.capacity is in weird units - convert to sectors */ ++ u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9)); ++ ++ if ((direction == MMC_DATA_READ) && ++ ((blk_pos + blk_size) == card_sectors)) ++ blk_size--; ++ ++ return blk_size; ++} ++ ++ ++static struct mmc_host_ops bcm2835_sdhost_ops = { ++ .request = bcm2835_sdhost_request, ++ .set_ios = bcm2835_sdhost_set_ios, ++ .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, ++ .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, ++}; ++ ++ ++static void bcm2835_sdhost_tasklet_finish(unsigned long param) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ struct mmc_request *mrq; ++ ++ host = (struct bcm2835_host *)param; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ /* ++ * If this tasklet gets rescheduled while running, it will ++ * be run again afterwards but without any active request. ++ */ ++ if (!host->mrq) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ return; ++ } ++ ++ del_timer(&host->timer); ++ ++ mrq = host->mrq; ++ ++ /* ++ * The controller needs a reset of internal state machines ++ * upon error conditions. ++ */ ++ if (((mrq->cmd && mrq->cmd->error) || ++ (mrq->data && (mrq->data->error || ++ (mrq->data->stop && mrq->data->stop->error))))) { ++ ++ bcm2835_sdhost_reset(host); ++ } ++ ++ host->mrq = NULL; ++ host->cmd = NULL; ++ host->data = NULL; ++ ++ mmiowb(); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ mmc_request_done(host->mmc, mrq); ++} ++ ++ ++ ++int bcm2835_sdhost_add_host(struct bcm2835_host *host) ++{ ++ struct mmc_host *mmc; ++ struct dma_slave_config cfg; ++ int ret; ++ ++ mmc = host->mmc; ++ ++ bcm2835_sdhost_reset(host); ++ ++ mmc->f_max = host->max_clk; ++ mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; ++ ++ /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ ++ host->timeout_clk = mmc->f_max / 1000; ++#ifdef CONFIG_ARCH_BCM2835 ++ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; ++#endif ++ /* host controller capabilities */ ++ mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | ++ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | ++ MMC_CAP_NEEDS_POLL | ++ (ALLOW_CMD23 * MMC_CAP_CMD23); ++ ++ spin_lock_init(&host->lock); ++ ++ if (host->allow_dma) { ++ if (!host->dma_chan_tx || !host->dma_chan_rx || ++ IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { ++ pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); ++ host->have_dma = false; ++ } else { ++ pr_info("DMA channels allocated for the SDHost driver"); ++ host->have_dma = true; ++ ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.slave_id = 13; /* DREQ channel */ ++ ++ cfg.direction = DMA_MEM_TO_DEV; ++ cfg.src_addr = 0; ++ cfg.dst_addr = host->phys_addr + SDDATA; ++ ret = dmaengine_slave_config(host->dma_chan_tx, &cfg); ++ ++ cfg.direction = DMA_DEV_TO_MEM; ++ cfg.src_addr = host->phys_addr + SDDATA; ++ cfg.dst_addr = 0; ++ ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); ++ } ++ } else { ++ pr_info("Forcing PIO mode\n"); ++ host->have_dma = false; ++ } ++ ++ mmc->max_segs = 128; ++ mmc->max_req_size = 524288; ++ mmc->max_seg_size = mmc->max_req_size; ++ mmc->max_blk_size = 512; ++ mmc->max_blk_count = 65535; ++ ++ /* report supported voltage ranges */ ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ tasklet_init(&host->finish_tasklet, ++ bcm2835_sdhost_tasklet_finish, (unsigned long)host); ++ ++ setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); ++ ++ bcm2835_sdhost_init(host, 0); ++#ifndef CONFIG_ARCH_BCM2835 ++ ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, ++ mmc_hostname(mmc), host); ++#else ++ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, ++ IRQF_SHARED, mmc_hostname(mmc), host); ++#endif ++ if (ret) { ++ pr_err("%s: Failed to request IRQ %d: %d\n", ++ mmc_hostname(mmc), host->irq, ret); ++ goto untasklet; ++ } ++ ++ mmiowb(); ++ mmc_add_host(mmc); ++ ++ pr_info("Load BCM2835 SDHost driver\n"); ++ if (host->delay_after_stop) ++ pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", ++ host->delay_after_stop); ++ ++ return 0; ++ ++untasklet: ++ tasklet_kill(&host->finish_tasklet); ++ ++ return ret; ++} ++ ++static int bcm2835_sdhost_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct clk *clk; ++ struct resource *iomem; ++ struct bcm2835_host *host; ++ struct mmc_host *mmc; ++ int ret; ++ ++ pr_debug("bcm2835_sdhost_probe\n"); ++ mmc = mmc_alloc_host(sizeof(*host), dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ mmc->ops = &bcm2835_sdhost_ops; ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ host->timeout = msecs_to_jiffies(1000); ++ spin_lock_init(&host->lock); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->ioaddr = devm_ioremap_resource(dev, iomem); ++ if (IS_ERR(host->ioaddr)) { ++ ret = PTR_ERR(host->ioaddr); ++ goto err; ++ } ++ ++ host->phys_addr = iomem->start + BCM2835_VCMMU_SHIFT; ++ pr_debug(" - ioaddr %lx, iomem->start %lx, phys_addr %lx\n", ++ (unsigned long)host->ioaddr, ++ (unsigned long)iomem->start, ++ (unsigned long)host->phys_addr); ++ ++ host->allow_dma = ALLOW_DMA; ++ ++ if (node) { ++ /* Read any custom properties */ ++ of_property_read_u32(node, ++ "brcm,delay-after-stop", ++ &host->delay_after_stop); ++ of_property_read_u32(node, ++ "brcm,overclock-50", ++ &host->overclock_50); ++ host->allow_dma = ALLOW_DMA && ++ !of_property_read_bool(node, "brcm,force-pio"); ++ } ++ ++ if (host->allow_dma) { ++ if (node) { ++ host->dma_chan_tx = ++ dma_request_slave_channel(dev, "tx"); ++ host->dma_chan_rx = ++ dma_request_slave_channel(dev, "rx"); ++ } else { ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ /* we don't care about the channel, any would work */ ++ dma_cap_set(DMA_SLAVE, mask); ++ host->dma_chan_tx = ++ dma_request_channel(mask, NULL, NULL); ++ host->dma_chan_rx = ++ dma_request_channel(mask, NULL, NULL); ++ } ++ } ++ ++ clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(dev, "could not get clk\n"); ++ ret = PTR_ERR(clk); ++ goto err; ++ } ++ ++ host->max_clk = clk_get_rate(clk); ++ ++ host->irq = platform_get_irq(pdev, 0); ++ if (host->irq <= 0) { ++ dev_err(dev, "get IRQ failed\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ pr_debug(" - max_clk %lx, irq %d\n", ++ (unsigned long)host->max_clk, ++ (int)host->irq); ++ ++ if (node) ++ mmc_of_parse(mmc); ++ else ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ ++ ret = bcm2835_sdhost_add_host(host); ++ if (ret) ++ goto err; ++ ++ platform_set_drvdata(pdev, host); ++ ++ pr_debug("bcm2835_sdhost_probe -> OK\n"); ++ ++ return 0; ++ ++err: ++ pr_debug("bcm2835_sdhost_probe -> err %d\n", ret); ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++static int bcm2835_sdhost_remove(struct platform_device *pdev) ++{ ++ struct bcm2835_host *host = platform_get_drvdata(pdev); ++ ++ pr_debug("bcm2835_sdhost_remove\n"); ++ ++ mmc_remove_host(host->mmc); ++ ++ bcm2835_sdhost_set_power(host, false); ++ ++ free_irq(host->irq, host); ++ ++ del_timer_sync(&host->timer); ++ ++ tasklet_kill(&host->finish_tasklet); ++ ++ mmc_free_host(host->mmc); ++ platform_set_drvdata(pdev, NULL); ++ ++ pr_debug("bcm2835_sdhost_remove - OK\n"); ++ return 0; ++} ++ ++ ++static const struct of_device_id bcm2835_sdhost_match[] = { ++ { .compatible = "brcm,bcm2835-sdhost" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_sdhost_match); ++ ++ ++ ++static struct platform_driver bcm2835_sdhost_driver = { ++ .probe = bcm2835_sdhost_probe, ++ .remove = bcm2835_sdhost_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2835_sdhost_match, ++ }, ++}; ++module_platform_driver(bcm2835_sdhost_driver); ++ ++MODULE_ALIAS("platform:sdhost-bcm2835"); ++MODULE_DESCRIPTION("BCM2835 SDHost driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Phil Elwell"); + +From 34fb9ba0190b9f9e18e6c136c64af8dcea23376d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 009/216] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 11/77] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix @@ -80985,12 +80479,15 @@ index 0000000..5325832 + +#endif /* VC_CMA_H */ -From 6bafd180b5b7672ebbaea3878e78511d309007a0 Mon Sep 17 00:00:00 2001 +From 0e6896e85bf10d584b555ecae4b55f066a774b54 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 010/216] bcm2708: alsa sound driver +Subject: [PATCH 12/77] bcm2708: alsa sound driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit - Signed-off-by: popcornmix +Signed-off-by: popcornmix alsa: add mmap support and some cleanups to bcm2835 ALSA driver @@ -81014,33 +80511,41 @@ snd-bcm2708: Fix dmesg spam for non-error case alsa: Ensure mutexes are released through error paths alsa: Make interrupted close paths quieter + +BCM270x: Add onboard sound device to Device Tree + +Add Device Tree support to alsa driver. +Add device to Device Tree. +Don't add platform devices when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/bcm2708.c | 54 +++ - sound/arm/Kconfig | 7 + + arch/arm/mach-bcm2708/bcm2708.c | 53 +++ + arch/arm/mach-bcm2709/bcm2709.c | 53 +++ + sound/arm/Kconfig | 8 + sound/arm/Makefile | 5 + sound/arm/bcm2835-ctl.c | 323 +++++++++++++ sound/arm/bcm2835-pcm.c | 557 +++++++++++++++++++++++ sound/arm/bcm2835-vchiq.c | 902 +++++++++++++++++++++++++++++++++++++ - sound/arm/bcm2835.c | 420 +++++++++++++++++ + sound/arm/bcm2835.c | 511 +++++++++++++++++++++ sound/arm/bcm2835.h | 167 +++++++ sound/arm/vc_vchi_audioserv_defs.h | 116 +++++ - 9 files changed, 2551 insertions(+) + 10 files changed, 2695 insertions(+) create mode 100755 sound/arm/bcm2835-ctl.c create mode 100755 sound/arm/bcm2835-pcm.c create mode 100755 sound/arm/bcm2835-vchiq.c - create mode 100755 sound/arm/bcm2835.c + create mode 100644 sound/arm/bcm2835.c create mode 100755 sound/arm/bcm2835.h create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d1308ed..f54e3e9b 100644 +index 5b10802..06271df 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -447,6 +447,58 @@ struct platform_device bcm2708_powerman_device = { - .coherent_dma_mask = 0xffffffffUL}, +@@ -429,6 +429,57 @@ struct platform_device bcm2835_emmc_device = { }; + #endif /* CONFIG_MMC_BCM2835 */ -+ +static struct platform_device bcm2708_alsa_devices[] = { + [0] = { + .name = "bcm2835_AUD0", @@ -81095,26 +80600,98 @@ index d1308ed..f54e3e9b 100644 int __init bcm_register_device(struct platform_device *pdev) { int ret; -@@ -556,6 +608,8 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2835_emmc_device); +@@ -571,6 +622,8 @@ void __init bcm2708_init(void) #endif bcm2708_init_led(); + bcm2708_init_uart1(); + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -+ bcm_register_device(&bcm2708_alsa_devices[i]); ++ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 54c5444..0f875ff 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -449,6 +449,57 @@ struct platform_device bcm2835_emmc_device = { + }; + #endif /* CONFIG_MMC_BCM2835 */ + ++static struct platform_device bcm2708_alsa_devices[] = { ++ [0] = { ++ .name = "bcm2835_AUD0", ++ .id = 0, /* first audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [1] = { ++ .name = "bcm2835_AUD1", ++ .id = 1, /* second audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [2] = { ++ .name = "bcm2835_AUD2", ++ .id = 2, /* third audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [3] = { ++ .name = "bcm2835_AUD3", ++ .id = 3, /* forth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [4] = { ++ .name = "bcm2835_AUD4", ++ .id = 4, /* fifth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [5] = { ++ .name = "bcm2835_AUD5", ++ .id = 5, /* sixth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [6] = { ++ .name = "bcm2835_AUD6", ++ .id = 6, /* seventh audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [7] = { ++ .name = "bcm2835_AUD7", ++ .id = 7, /* eighth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++}; ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -591,6 +642,8 @@ void __init bcm2709_init(void) + #endif + bcm2709_init_led(); + bcm2709_init_uart1(); ++ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) ++ bcm_register_device_dt(&bcm2708_alsa_devices[i]); + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 885683a..ada7ba2 100644 +index 885683a..fcbe9d7 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig -@@ -39,5 +39,12 @@ config SND_PXA2XX_AC97 +@@ -39,5 +39,13 @@ config SND_PXA2XX_AC97 Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. +config SND_BCM2835 + tristate "BCM2835 ALSA driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709) && BCM2708_VCHIQ && SND ++ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ ++ && BCM2708_VCHIQ && SND + select SND_PCM + help + Say Y or M if you want to support BCM2835 Alsa pcm card driver @@ -82935,11 +82512,11 @@ index 0000000..3de3094 +module_param(force_bulk, bool, 0444); +MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio"); diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c -new file mode 100755 -index 0000000..7ed5079 +new file mode 100644 +index 0000000..6b545e7 --- /dev/null +++ b/sound/arm/bcm2835.c -@@ -0,0 +1,420 @@ +@@ -0,0 +1,511 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -82959,6 +82536,7 @@ index 0000000..7ed5079 +#include +#include +#include ++#include + +#include "bcm2835.h" + @@ -83023,6 +82601,86 @@ index 0000000..7ed5079 + return 0; +} + ++static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ bcm2835_chip_t *chip; ++ struct snd_card *card; ++ u32 numchans; ++ int err, i; ++ ++ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", ++ &numchans); ++ if (err) { ++ dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); ++ return err; ++ } ++ ++ if (numchans == 0 || numchans > MAX_SUBSTREAMS) { ++ numchans = MAX_SUBSTREAMS; ++ dev_warn(dev, "Illegal 'brcm,pwm-channels' value, will use %u\n", ++ numchans); ++ } ++ ++ err = snd_card_new(NULL, -1, NULL, THIS_MODULE, 0, &card); ++ if (err) { ++ dev_err(dev, "Failed to create soundcard structure\n"); ++ return err; ++ } ++ ++ snd_card_set_dev(card, dev); ++ strcpy(card->driver, "bcm2835"); ++ strcpy(card->shortname, "bcm2835 ALSA"); ++ sprintf(card->longname, "%s", card->shortname); ++ ++ err = snd_bcm2835_create(card, pdev, &chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create bcm2835 chip\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_pcm(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 pcm device\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_spdif_pcm(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 spdif pcm device\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_ctl(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 ctl\n"); ++ goto err_free; ++ } ++ ++ for (i = 0; i < numchans; i++) { ++ chip->avail_substreams |= (1 << i); ++ chip->pdev[i] = pdev; ++ } ++ ++ err = snd_card_register(card); ++ if (err) { ++ dev_err(dev, "Failed to register bcm2835 ALSA card \n"); ++ goto err_free; ++ } ++ ++ g_card = card; ++ g_chip = chip; ++ platform_set_drvdata(pdev, card); ++ audio_info("bcm2835 ALSA card created with %u channels\n", numchans); ++ ++ return 0; ++ ++err_free: ++ snd_card_free(card); ++ ++ return err; ++} ++ +static int snd_bcm2835_alsa_probe(struct platform_device *pdev) +{ + static int dev; @@ -83030,6 +82688,9 @@ index 0000000..7ed5079 + struct snd_card *card; + int err; + ++ if (pdev->dev.of_node) ++ return snd_bcm2835_alsa_probe_dt(pdev); ++ + if (dev >= MAX_SUBSTREAMS) + return -ENODEV; + @@ -83166,6 +82827,12 @@ index 0000000..7ed5079 + +#endif + ++static const struct of_device_id snd_bcm2835_of_match_table[] = { ++ { .compatible = "brcm,bcm2835-audio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); ++ +static struct platform_driver bcm2835_alsa0_driver = { + .probe = snd_bcm2835_alsa_probe, + .remove = snd_bcm2835_alsa_remove, @@ -83176,6 +82843,7 @@ index 0000000..7ed5079 + .driver = { + .name = "bcm2835_AUD0", + .owner = THIS_MODULE, ++ .of_match_table = snd_bcm2835_of_match_table, + }, +}; + @@ -83656,10 +83324,13 @@ index 0000000..af3e6eb + +#endif // _VC_AUDIO_DEFS_H_ -From ddf7318165c6faf5bc73597105a2eed9fece4225 Mon Sep 17 00:00:00 2001 +From b2b5ab24c875e79e1fbb55ae76dc5a914fe301d0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 011/216] bcm2708 vchiq driver +Subject: [PATCH 13/77] bcm2708 vchiq driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -83727,7 +83398,30 @@ vchiq: Fix wrong condition check The log level is checked from within the log call. Remove the check in the call. Signed-off-by: Pranith Kumar + +BCM270x: Add vchiq device to platform file and Device Tree + +Prepare to turn the vchiq module into a driver. + +Signed-off-by: Noralf Trønnes + +bcm2708: vchiq: Add Device Tree support + +Turn vchiq into a driver and stop hardcoding resources. +Use devm_* functions in probe path to simplify cleanup. +A global variable is used to hold the register address. This is done +to keep this patch as small as possible. +Also make available on ARCH_BCM2835. +Based on work by Lubomir Rintel. + +Signed-off-by: Noralf Trønnes + +vchiq: Change logging level for inbound data --- + arch/arm/mach-bcm2708/bcm2708.c | 26 + + arch/arm/mach-bcm2708/include/mach/platform.h | 2 + + arch/arm/mach-bcm2709/bcm2709.c | 26 + + arch/arm/mach-bcm2709/include/mach/platform.h | 2 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/vc04_services/Kconfig | 9 + @@ -83741,9 +83435,9 @@ Signed-off-by: Pranith Kumar .../misc/vc04_services/interface/vchi/vchi_mh.h | 42 + .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + - .../interface/vchiq_arm/vchiq_2835_arm.c | 562 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2884 ++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 223 ++ + .../interface/vchiq_arm/vchiq_2835_arm.c | 547 +++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2886 ++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ .../interface/vchiq_arm/vchiq_build_info.h | 37 + .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + .../interface/vchiq_arm/vchiq_connected.c | 120 + @@ -83763,7 +83457,7 @@ Signed-off-by: Pranith Kumar .../vc04_services/interface/vchiq_arm/vchiq_util.c | 152 + .../vc04_services/interface/vchiq_arm/vchiq_util.h | 81 + .../interface/vchiq_arm/vchiq_version.c | 59 + - 35 files changed, 12770 insertions(+) + 39 files changed, 12810 insertions(+) create mode 100644 drivers/misc/vc04_services/Kconfig create mode 100644 drivers/misc/vc04_services/Makefile create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -83798,6 +83492,120 @@ Signed-off-by: Pranith Kumar create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 06271df..86011af 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -376,6 +376,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++static struct resource bcm2708_vchiq_resources[] = { ++ { ++ .start = ARMCTRL_0_BELL_BASE, ++ .end = ARMCTRL_0_BELL_BASE + 16, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_DOORBELL_0, ++ .end = IRQ_ARM_DOORBELL_0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vchiq_device = { ++ .name = "bcm2835_vchiq", ++ .id = -1, ++ .resource = bcm2708_vchiq_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), ++ .dev = { ++ .dma_mask = &vchiq_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + #ifdef CONFIG_BCM2708_GPIO + #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +@@ -611,6 +636,7 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif +diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h +index 2e7e1bb..69674e9 100644 +--- a/arch/arm/mach-bcm2708/include/mach/platform.h ++++ b/arch/arm/mach-bcm2708/include/mach/platform.h +@@ -81,6 +81,8 @@ + #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ + #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ + #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ ++#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + + /* +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 0f875ff..bc1ee1c 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -396,6 +396,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++static struct resource bcm2708_vchiq_resources[] = { ++ { ++ .start = ARMCTRL_0_BELL_BASE, ++ .end = ARMCTRL_0_BELL_BASE + 16, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_DOORBELL_0, ++ .end = IRQ_ARM_DOORBELL_0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vchiq_device = { ++ .name = "bcm2835_vchiq", ++ .id = -1, ++ .resource = bcm2708_vchiq_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), ++ .dev = { ++ .dma_mask = &vchiq_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + #ifdef CONFIG_BCM2708_GPIO + #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +@@ -631,6 +656,7 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif +diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h +index 7157f38..be99733 100644 +--- a/arch/arm/mach-bcm2709/include/mach/platform.h ++++ b/arch/arm/mach-bcm2709/include/mach/platform.h +@@ -81,6 +81,8 @@ + #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ + #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ + #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ ++#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + + /* diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 006242c..4e6f46c3 100644 --- a/drivers/misc/Kconfig @@ -83824,13 +83632,13 @@ index 7d5c4cd..43d2ac9 100644 obj-$(CONFIG_ECHO) += echo/ diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig new file mode 100644 -index 0000000..b94e6cd +index 0000000..c5ba283 --- /dev/null +++ b/drivers/misc/vc04_services/Kconfig @@ -0,0 +1,9 @@ +config BCM2708_VCHIQ + tristate "Videocore VCHIQ" -+ depends on MACH_BCM2708 || MACH_BCM2709 ++ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX + default y + help + Kernel to VideoCore communication interface for the @@ -85417,10 +85225,10 @@ index 0000000..7ea5c64 +#endif /* VCHIQ_2835_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c new file mode 100644 -index 0000000..8ec88bb +index 0000000..c739083 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -0,0 +1,562 @@ +@@ -0,0 +1,547 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -85458,23 +85266,18 @@ index 0000000..8ec88bb +#include +#include +#include -+#include +#include +#include +#include +#include ++#include ++#include +#include +#include + -+#include -+ -+#include -+#include -+ +#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) + -+#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0 -+#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) ++#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) + +#include "vchiq_arm.h" +#include "vchiq_2835.h" @@ -85483,17 +85286,19 @@ index 0000000..8ec88bb + +#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) + ++#define BELL0 0x00 ++#define BELL2 0x08 ++ +typedef struct vchiq_2835_state_struct { + int inited; + VCHIQ_ARM_STATE_T arm_state; +} VCHIQ_2835_ARM_STATE_T; + -+static char *g_slot_mem; -+static int g_slot_mem_size; -+dma_addr_t g_slot_phys; ++static void __iomem *g_regs; +static FRAGMENTS_T *g_fragments_base; +static FRAGMENTS_T *g_free_fragments; -+struct semaphore g_free_fragments_sema; ++static struct semaphore g_free_fragments_sema; ++static unsigned long g_virt_to_bus_offset; + +extern int vchiq_arm_log_level; + @@ -85509,43 +85314,42 @@ index 0000000..8ec88bb +static void +free_pagelist(PAGELIST_T *pagelist, int actual); + -+int __init -+vchiq_platform_init(VCHIQ_STATE_T *state) ++int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) +{ ++ struct device *dev = &pdev->dev; + VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -+ int frag_mem_size; -+ int err; -+ int i; ++ struct resource *res; ++ void *slot_mem; ++ dma_addr_t slot_phys; ++ int slot_mem_size, frag_mem_size; ++ int err, irq, i; ++ ++ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); + + /* Allocate space for the channels in coherent memory */ -+ g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); ++ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); + frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); + -+ g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size, -+ &g_slot_phys, GFP_KERNEL); -+ -+ if (!g_slot_mem) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocate channel memory"); -+ err = -ENOMEM; -+ goto failed_alloc; ++ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, ++ &slot_phys, GFP_KERNEL); ++ if (!slot_mem) { ++ dev_err(dev, "could not allocate DMA memory\n"); ++ return -ENOMEM; + } + -+ WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0); ++ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); + -+ vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size); -+ if (!vchiq_slot_zero) { -+ err = -EINVAL; -+ goto failed_init_slots; -+ } ++ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); ++ if (!vchiq_slot_zero) ++ return -EINVAL; + + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -+ (int)g_slot_phys + g_slot_mem_size; ++ (int)slot_phys + slot_mem_size; + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = + MAX_FRAGMENTS; + -+ g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size); -+ g_slot_mem_size += frag_mem_size; ++ g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); ++ slot_mem_size += frag_mem_size; + + g_free_fragments = g_fragments_base; + for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { @@ -85555,54 +85359,46 @@ index 0000000..8ec88bb + *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; + sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); + -+ if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) != -+ VCHIQ_SUCCESS) { -+ err = -EINVAL; -+ goto failed_vchiq_init; ++ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ g_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(g_regs)) ++ return PTR_ERR(g_regs); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev, "failed to get IRQ\n"); ++ return irq; + } + -+ err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq, -+ IRQF_IRQPOLL, "VCHIQ doorbell", -+ state); -+ if (err < 0) { -+ vchiq_log_error(vchiq_arm_log_level, "%s: failed to register " -+ "irq=%d err=%d", __func__, -+ VCHIQ_DOORBELL_IRQ, err); -+ goto failed_request_irq; ++ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, ++ "VCHIQ doorbell", state); ++ if (err) { ++ dev_err(dev, "failed to register irq=%d\n", irq); ++ return err; + } + + /* Send the base address of the slots to VideoCore */ + + dsb(); /* Ensure all writes have completed */ + -+ bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys); ++ err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); ++ if (err) { ++ dev_err(dev, "mailbox write failed\n"); ++ return err; ++ } + + vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_init - done (slots %x, phys %x)", -+ (unsigned int)vchiq_slot_zero, g_slot_phys); ++ "vchiq_init - done (slots %x, phys %pad)", ++ (unsigned int)vchiq_slot_zero, &slot_phys); + -+ vchiq_call_connected_callbacks(); ++ vchiq_call_connected_callbacks(); + + return 0; -+ -+failed_request_irq: -+failed_vchiq_init: -+failed_init_slots: -+ dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys); -+ -+failed_alloc: -+ return err; +} + -+void __exit -+vchiq_platform_exit(VCHIQ_STATE_T *state) -+{ -+ free_irq(VCHIQ_DOORBELL_IRQ, state); -+ dma_free_coherent(NULL, g_slot_mem_size, -+ g_slot_mem, g_slot_phys); -+} -+ -+ +VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state) +{ @@ -85636,11 +85432,8 @@ index 0000000..8ec88bb + + dsb(); /* data barrier operation */ + -+ if (event->armed) { -+ /* trigger vc interrupt */ -+ -+ writel(0, __io_address(ARM_0_BELL2)); -+ } ++ if (event->armed) ++ writel(0, g_regs + BELL2); /* trigger vc interrupt */ +} + +int @@ -85764,7 +85557,7 @@ index 0000000..8ec88bb + unsigned int status; + + /* Read (and clear) the doorbell */ -+ status = readl(__io_address(ARM_0_BELL0)); ++ status = readl(g_regs + BELL0); + + if (status & 0x4) { /* Was the doorbell rung? */ + remote_event_pollall(state); @@ -85985,10 +85778,10 @@ index 0000000..8ec88bb +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000..0ad9656 +index 0000000..31e2cba --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2884 @@ +@@ -0,0 +1,2886 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -86036,6 +85829,7 @@ index 0000000..0ad9656 +#include +#include +#include ++#include + +#include "vchiq_core.h" +#include "vchiq_ioctl.h" @@ -88781,15 +88575,7 @@ index 0000000..0ad9656 + } +} + -+ -+/**************************************************************************** -+* -+* vchiq_init - called when the module is loaded. -+* -+***************************************************************************/ -+ -+static int __init -+vchiq_init(void) ++static int vchiq_probe(struct platform_device *pdev) +{ + int err; + void *ptr_err; @@ -88826,7 +88612,7 @@ index 0000000..0ad9656 + if (IS_ERR(ptr_err)) + goto failed_device_create; + -+ err = vchiq_platform_init(&g_state); ++ err = vchiq_platform_init(pdev, &g_state); + if (err != 0) + goto failed_platform_init; + @@ -88853,32 +88639,41 @@ index 0000000..0ad9656 + return err; +} + -+/**************************************************************************** -+* -+* vchiq_exit - called when the module is unloaded. -+* -+***************************************************************************/ -+ -+static void __exit -+vchiq_exit(void) ++static int vchiq_remove(struct platform_device *pdev) +{ -+ vchiq_platform_exit(&g_state); + device_destroy(vchiq_class, vchiq_devid); + class_destroy(vchiq_class); + cdev_del(&vchiq_cdev); + unregister_chrdev_region(vchiq_devid, 1); ++ ++ return 0; +} + -+module_init(vchiq_init); -+module_exit(vchiq_exit); ++static const struct of_device_id vchiq_of_match[] = { ++ { .compatible = "brcm,bcm2835-vchiq", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, vchiq_of_match); ++ ++static struct platform_driver vchiq_driver = { ++ .driver = { ++ .name = "bcm2835_vchiq", ++ .owner = THIS_MODULE, ++ .of_match_table = vchiq_of_match, ++ }, ++ .probe = vchiq_probe, ++ .remove = vchiq_remove, ++}; ++module_platform_driver(vchiq_driver); ++ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h new file mode 100644 -index 0000000..d1e2741 +index 0000000..9740e1a --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -0,0 +1,223 @@ +@@ -0,0 +1,220 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -88917,6 +88712,7 @@ index 0000000..d1e2741 +#define VCHIQ_ARM_H + +#include ++#include +#include +#include +#include "vchiq_core.h" @@ -89009,11 +88805,7 @@ index 0000000..d1e2741 +extern int vchiq_arm_log_level; +extern int vchiq_susp_log_level; + -+extern int __init -+vchiq_platform_init(VCHIQ_STATE_T *state); -+ -+extern void __exit -+vchiq_platform_exit(VCHIQ_STATE_T *state); ++int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); + +extern VCHIQ_STATE_T * +vchiq_get_state(void); @@ -89404,7 +89196,7 @@ index 0000000..863b3e3 +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 -index 0000000..835688b +index 0000000..2c98da4 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -0,0 +1,3934 @@ @@ -91192,7 +90984,7 @@ index 0000000..835688b + service->remoteport); + break; + case VCHIQ_MSG_DATA: -+ vchiq_log_trace(vchiq_core_log_level, ++ vchiq_log_info(vchiq_core_log_level, + "%d: prs DATA@%x,%x (%d->%d)", + state->id, (unsigned int)header, size, + remoteport, localport); @@ -96789,10 +96581,1019 @@ index 0000000..b6bfa21 + return vchiq_build_time; +} -From 859a7d70416a46048ab89165367891de2104ef6f Mon Sep 17 00:00:00 2001 +From 6290b45c0e5fa71d2131718d1b5770e7849aedeb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 17 Jun 2015 16:07:06 +0100 +Subject: [PATCH 14/77] vc_mem: Add vc_mem driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +BCM270x: Move vc_mem + +Make the vc_mem module available for ARCH_BCM2835 by moving it. + +Signed-off-by: Noralf Trønnes +--- + arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- + arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- + drivers/char/broadcom/Kconfig | 12 +- + drivers/char/broadcom/Makefile | 1 + + drivers/char/broadcom/vc_mem.c | 423 +++++++++++++++++++++++++++ + include/linux/broadcom/vc_mem.h | 35 +++ + 6 files changed, 470 insertions(+), 467 deletions(-) + delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h + delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c + create mode 100644 drivers/char/broadcom/vc_mem.c + create mode 100644 include/linux/broadcom/vc_mem.h + +diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h +deleted file mode 100644 +index 4a4a338..0000000 +--- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/***************************************************************************** +-* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +-* +-* Unless you and Broadcom execute a separate written software license +-* agreement governing use of this software, this software is licensed to you +-* under the terms of the GNU General Public License version 2, available at +-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +-* +-* Notwithstanding the above, under no circumstances may you combine this +-* software in any way with any other Broadcom software provided under a +-* license other than the GPL, without Broadcom's express prior written +-* consent. +-*****************************************************************************/ +- +-#if !defined( VC_MEM_H ) +-#define VC_MEM_H +- +-#include +- +-#define VC_MEM_IOC_MAGIC 'v' +- +-#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) +-#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) +-#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) +-#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) +- +-#if defined( __KERNEL__ ) +-#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF +- +-extern unsigned long mm_vc_mem_phys_addr; +-extern unsigned int mm_vc_mem_size; +-extern int vc_mem_get_current_size( void ); +-#endif +- +-#endif /* VC_MEM_H */ +diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c +deleted file mode 100644 +index d2adfd1..0000000 +--- a/arch/arm/mach-bcm2709/vc_mem.c ++++ /dev/null +@@ -1,431 +0,0 @@ +-/***************************************************************************** +-* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +-* +-* Unless you and Broadcom execute a separate written software license +-* agreement governing use of this software, this software is licensed to you +-* under the terms of the GNU General Public License version 2, available at +-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +-* +-* Notwithstanding the above, under no circumstances may you combine this +-* software in any way with any other Broadcom software provided under a +-* license other than the GPL, without Broadcom's express prior written +-* consent. +-*****************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef CONFIG_ARCH_KONA +-#include +-#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) +-#else +-#include +-#endif +- +-#include "mach/vc_mem.h" +- +-#define DRIVER_NAME "vc-mem" +- +-// Device (/dev) related variables +-static dev_t vc_mem_devnum = 0; +-static struct class *vc_mem_class = NULL; +-static struct cdev vc_mem_cdev; +-static int vc_mem_inited = 0; +- +-#ifdef CONFIG_DEBUG_FS +-static struct dentry *vc_mem_debugfs_entry; +-#endif +- +-/* +- * Videocore memory addresses and size +- * +- * Drivers that wish to know the videocore memory addresses and sizes should +- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in +- * headers. This allows the other drivers to not be tied down to a a certain +- * address/size at compile time. +- * +- * In the future, the goal is to have the videocore memory virtual address and +- * size be calculated at boot time rather than at compile time. The decision of +- * where the videocore memory resides and its size would be in the hands of the +- * bootloader (and/or kernel). When that happens, the values of these variables +- * would be calculated and assigned in the init function. +- */ +-// in the 2835 VC in mapped above ARM, but ARM has full access to VC space +-unsigned long mm_vc_mem_phys_addr = 0x00000000; +-unsigned int mm_vc_mem_size = 0; +-unsigned int mm_vc_mem_base = 0; +- +-EXPORT_SYMBOL(mm_vc_mem_phys_addr); +-EXPORT_SYMBOL(mm_vc_mem_size); +-EXPORT_SYMBOL(mm_vc_mem_base); +- +-static uint phys_addr = 0; +-static uint mem_size = 0; +-static uint mem_base = 0; +- +- +-/**************************************************************************** +-* +-* vc_mem_open +-* +-***************************************************************************/ +- +-static int +-vc_mem_open(struct inode *inode, struct file *file) +-{ +- (void) inode; +- (void) file; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- return 0; +-} +- +-/**************************************************************************** +-* +-* vc_mem_release +-* +-***************************************************************************/ +- +-static int +-vc_mem_release(struct inode *inode, struct file *file) +-{ +- (void) inode; +- (void) file; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- return 0; +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_size +-* +-***************************************************************************/ +- +-static void +-vc_mem_get_size(void) +-{ +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_base +-* +-***************************************************************************/ +- +-static void +-vc_mem_get_base(void) +-{ +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_current_size +-* +-***************************************************************************/ +- +-int +-vc_mem_get_current_size(void) +-{ +- return mm_vc_mem_size; +-} +- +-EXPORT_SYMBOL_GPL(vc_mem_get_current_size); +- +-/**************************************************************************** +-* +-* vc_mem_ioctl +-* +-***************************************************************************/ +- +-static long +-vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +-{ +- int rc = 0; +- +- (void) cmd; +- (void) arg; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- switch (cmd) { +- case VC_MEM_IOC_MEM_PHYS_ADDR: +- { +- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", +- __func__, (void *) mm_vc_mem_phys_addr); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, +- sizeof (mm_vc_mem_phys_addr)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_SIZE: +- { +- // Get the videocore memory size first +- vc_mem_get_size(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, +- mm_vc_mem_size); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_size, +- sizeof (mm_vc_mem_size)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_BASE: +- { +- // Get the videocore memory base +- vc_mem_get_base(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, +- mm_vc_mem_base); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_base, +- sizeof (mm_vc_mem_base)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_LOAD: +- { +- // Get the videocore memory base +- vc_mem_get_base(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, +- mm_vc_mem_base); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_base, +- sizeof (mm_vc_mem_base)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- default: +- { +- return -ENOTTY; +- } +- } +- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); +- +- return rc; +-} +- +-/**************************************************************************** +-* +-* vc_mem_mmap +-* +-***************************************************************************/ +- +-static int +-vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) +-{ +- int rc = 0; +- unsigned long length = vma->vm_end - vma->vm_start; +- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; +- +- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", +- __func__, (long) vma->vm_start, (long) vma->vm_end, +- (long) vma->vm_pgoff); +- +- if (offset + length > mm_vc_mem_size) { +- pr_err("%s: length %ld is too big\n", __func__, length); +- return -EINVAL; +- } +- // Do not cache the memory map +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- +- rc = remap_pfn_range(vma, vma->vm_start, +- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + +- vma->vm_pgoff, length, vma->vm_page_prot); +- if (rc != 0) { +- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); +- } +- +- return rc; +-} +- +-/**************************************************************************** +-* +-* File Operations for the driver. +-* +-***************************************************************************/ +- +-static const struct file_operations vc_mem_fops = { +- .owner = THIS_MODULE, +- .open = vc_mem_open, +- .release = vc_mem_release, +- .unlocked_ioctl = vc_mem_ioctl, +- .mmap = vc_mem_mmap, +-}; +- +-#ifdef CONFIG_DEBUG_FS +-static void vc_mem_debugfs_deinit(void) +-{ +- debugfs_remove_recursive(vc_mem_debugfs_entry); +- vc_mem_debugfs_entry = NULL; +-} +- +- +-static int vc_mem_debugfs_init( +- struct device *dev) +-{ +- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); +- if (!vc_mem_debugfs_entry) { +- dev_warn(dev, "could not create debugfs entry\n"); +- return -EFAULT; +- } +- +- if (!debugfs_create_x32("vc_mem_phys_addr", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_phys_addr)) { +- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", +- __func__); +- goto fail; +- } +- +- if (!debugfs_create_x32("vc_mem_size", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_size)) { +- dev_warn(dev, "%s:could not create vc_mem_size entry\n", +- __func__); +- goto fail; +- } +- +- if (!debugfs_create_x32("vc_mem_base", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_base)) { +- dev_warn(dev, "%s:could not create vc_mem_base entry\n", +- __func__); +- goto fail; +- } +- +- return 0; +- +-fail: +- vc_mem_debugfs_deinit(); +- return -EFAULT; +-} +- +-#endif /* CONFIG_DEBUG_FS */ +- +- +-/**************************************************************************** +-* +-* vc_mem_init +-* +-***************************************************************************/ +- +-static int __init +-vc_mem_init(void) +-{ +- int rc = -EFAULT; +- struct device *dev; +- +- pr_debug("%s: called\n", __func__); +- +- mm_vc_mem_phys_addr = phys_addr; +- mm_vc_mem_size = mem_size; +- mm_vc_mem_base = mem_base; +- +- vc_mem_get_size(); +- +- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", +- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); +- +- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { +- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", +- __func__, rc); +- goto out_err; +- } +- +- cdev_init(&vc_mem_cdev, &vc_mem_fops); +- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { +- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); +- goto out_unregister; +- } +- +- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); +- if (IS_ERR(vc_mem_class)) { +- rc = PTR_ERR(vc_mem_class); +- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); +- goto out_cdev_del; +- } +- +- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, +- DRIVER_NAME); +- if (IS_ERR(dev)) { +- rc = PTR_ERR(dev); +- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); +- goto out_class_destroy; +- } +- +-#ifdef CONFIG_DEBUG_FS +- /* don't fail if the debug entries cannot be created */ +- vc_mem_debugfs_init(dev); +-#endif +- +- vc_mem_inited = 1; +- return 0; +- +- device_destroy(vc_mem_class, vc_mem_devnum); +- +- out_class_destroy: +- class_destroy(vc_mem_class); +- vc_mem_class = NULL; +- +- out_cdev_del: +- cdev_del(&vc_mem_cdev); +- +- out_unregister: +- unregister_chrdev_region(vc_mem_devnum, 1); +- +- out_err: +- return -1; +-} +- +-/**************************************************************************** +-* +-* vc_mem_exit +-* +-***************************************************************************/ +- +-static void __exit +-vc_mem_exit(void) +-{ +- pr_debug("%s: called\n", __func__); +- +- if (vc_mem_inited) { +-#if CONFIG_DEBUG_FS +- vc_mem_debugfs_deinit(); +-#endif +- device_destroy(vc_mem_class, vc_mem_devnum); +- class_destroy(vc_mem_class); +- cdev_del(&vc_mem_cdev); +- unregister_chrdev_region(vc_mem_devnum, 1); +- } +-} +- +-module_init(vc_mem_init); +-module_exit(vc_mem_exit); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Broadcom Corporation"); +- +-module_param(phys_addr, uint, 0644); +-module_param(mem_size, uint, 0644); +-module_param(mem_base, uint, 0644); +diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig +index 2d8bd6e..7037928 100644 +--- a/drivers/char/broadcom/Kconfig ++++ b/drivers/char/broadcom/Kconfig +@@ -7,9 +7,19 @@ menuconfig BRCM_CHAR_DRIVERS + help + Broadcom's char drivers + ++if BRCM_CHAR_DRIVERS ++ + config BCM_VC_CMA + bool "Videocore CMA" +- depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ ++ depends on CMA && BCM2708_VCHIQ + default n + help + Helper for videocore CMA access. ++ ++config BCM2708_VCMEM ++ bool "Videocore Memory" ++ default y ++ help ++ Helper for videocore memory access and total size allocation. ++ ++endif +diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile +index 13c5bca..fce918c 100644 +--- a/drivers/char/broadcom/Makefile ++++ b/drivers/char/broadcom/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ ++obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +diff --git a/drivers/char/broadcom/vc_mem.c b/drivers/char/broadcom/vc_mem.c +new file mode 100644 +index 0000000..fcde6b1 +--- /dev/null ++++ b/drivers/char/broadcom/vc_mem.c +@@ -0,0 +1,423 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "vc-mem" ++ ++// Device (/dev) related variables ++static dev_t vc_mem_devnum = 0; ++static struct class *vc_mem_class = NULL; ++static struct cdev vc_mem_cdev; ++static int vc_mem_inited = 0; ++ ++#ifdef CONFIG_DEBUG_FS ++static struct dentry *vc_mem_debugfs_entry; ++#endif ++ ++/* ++ * Videocore memory addresses and size ++ * ++ * Drivers that wish to know the videocore memory addresses and sizes should ++ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in ++ * headers. This allows the other drivers to not be tied down to a a certain ++ * address/size at compile time. ++ * ++ * In the future, the goal is to have the videocore memory virtual address and ++ * size be calculated at boot time rather than at compile time. The decision of ++ * where the videocore memory resides and its size would be in the hands of the ++ * bootloader (and/or kernel). When that happens, the values of these variables ++ * would be calculated and assigned in the init function. ++ */ ++// in the 2835 VC in mapped above ARM, but ARM has full access to VC space ++unsigned long mm_vc_mem_phys_addr = 0x00000000; ++unsigned int mm_vc_mem_size = 0; ++unsigned int mm_vc_mem_base = 0; ++ ++EXPORT_SYMBOL(mm_vc_mem_phys_addr); ++EXPORT_SYMBOL(mm_vc_mem_size); ++EXPORT_SYMBOL(mm_vc_mem_base); ++ ++static uint phys_addr = 0; ++static uint mem_size = 0; ++static uint mem_base = 0; ++ ++ ++/**************************************************************************** ++* ++* vc_mem_open ++* ++***************************************************************************/ ++ ++static int ++vc_mem_open(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_release ++* ++***************************************************************************/ ++ ++static int ++vc_mem_release(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_size ++* ++***************************************************************************/ ++ ++static void ++vc_mem_get_size(void) ++{ ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_base ++* ++***************************************************************************/ ++ ++static void ++vc_mem_get_base(void) ++{ ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_current_size ++* ++***************************************************************************/ ++ ++int ++vc_mem_get_current_size(void) ++{ ++ return mm_vc_mem_size; ++} ++ ++EXPORT_SYMBOL_GPL(vc_mem_get_current_size); ++ ++/**************************************************************************** ++* ++* vc_mem_ioctl ++* ++***************************************************************************/ ++ ++static long ++vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int rc = 0; ++ ++ (void) cmd; ++ (void) arg; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ switch (cmd) { ++ case VC_MEM_IOC_MEM_PHYS_ADDR: ++ { ++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", ++ __func__, (void *) mm_vc_mem_phys_addr); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, ++ sizeof (mm_vc_mem_phys_addr)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_SIZE: ++ { ++ // Get the videocore memory size first ++ vc_mem_get_size(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, ++ mm_vc_mem_size); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_size, ++ sizeof (mm_vc_mem_size)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_BASE: ++ { ++ // Get the videocore memory base ++ vc_mem_get_base(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, ++ mm_vc_mem_base); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_base, ++ sizeof (mm_vc_mem_base)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_LOAD: ++ { ++ // Get the videocore memory base ++ vc_mem_get_base(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, ++ mm_vc_mem_base); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_base, ++ sizeof (mm_vc_mem_base)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ default: ++ { ++ return -ENOTTY; ++ } ++ } ++ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_mmap ++* ++***************************************************************************/ ++ ++static int ++vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ int rc = 0; ++ unsigned long length = vma->vm_end - vma->vm_start; ++ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; ++ ++ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", ++ __func__, (long) vma->vm_start, (long) vma->vm_end, ++ (long) vma->vm_pgoff); ++ ++ if (offset + length > mm_vc_mem_size) { ++ pr_err("%s: length %ld is too big\n", __func__, length); ++ return -EINVAL; ++ } ++ // Do not cache the memory map ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ ++ rc = remap_pfn_range(vma, vma->vm_start, ++ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + ++ vma->vm_pgoff, length, vma->vm_page_prot); ++ if (rc != 0) { ++ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); ++ } ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* File Operations for the driver. ++* ++***************************************************************************/ ++ ++static const struct file_operations vc_mem_fops = { ++ .owner = THIS_MODULE, ++ .open = vc_mem_open, ++ .release = vc_mem_release, ++ .unlocked_ioctl = vc_mem_ioctl, ++ .mmap = vc_mem_mmap, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++static void vc_mem_debugfs_deinit(void) ++{ ++ debugfs_remove_recursive(vc_mem_debugfs_entry); ++ vc_mem_debugfs_entry = NULL; ++} ++ ++ ++static int vc_mem_debugfs_init( ++ struct device *dev) ++{ ++ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); ++ if (!vc_mem_debugfs_entry) { ++ dev_warn(dev, "could not create debugfs entry\n"); ++ return -EFAULT; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_phys_addr", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_phys_addr)) { ++ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_size", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_size)) { ++ dev_warn(dev, "%s:could not create vc_mem_size entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_base", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_base)) { ++ dev_warn(dev, "%s:could not create vc_mem_base entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ vc_mem_debugfs_deinit(); ++ return -EFAULT; ++} ++ ++#endif /* CONFIG_DEBUG_FS */ ++ ++ ++/**************************************************************************** ++* ++* vc_mem_init ++* ++***************************************************************************/ ++ ++static int __init ++vc_mem_init(void) ++{ ++ int rc = -EFAULT; ++ struct device *dev; ++ ++ pr_debug("%s: called\n", __func__); ++ ++ mm_vc_mem_phys_addr = phys_addr; ++ mm_vc_mem_size = mem_size; ++ mm_vc_mem_base = mem_base; ++ ++ vc_mem_get_size(); ++ ++ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", ++ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); ++ ++ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { ++ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", ++ __func__, rc); ++ goto out_err; ++ } ++ ++ cdev_init(&vc_mem_cdev, &vc_mem_fops); ++ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { ++ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); ++ goto out_unregister; ++ } ++ ++ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); ++ if (IS_ERR(vc_mem_class)) { ++ rc = PTR_ERR(vc_mem_class); ++ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); ++ goto out_cdev_del; ++ } ++ ++ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, ++ DRIVER_NAME); ++ if (IS_ERR(dev)) { ++ rc = PTR_ERR(dev); ++ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); ++ goto out_class_destroy; ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ /* don't fail if the debug entries cannot be created */ ++ vc_mem_debugfs_init(dev); ++#endif ++ ++ vc_mem_inited = 1; ++ return 0; ++ ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ ++ out_class_destroy: ++ class_destroy(vc_mem_class); ++ vc_mem_class = NULL; ++ ++ out_cdev_del: ++ cdev_del(&vc_mem_cdev); ++ ++ out_unregister: ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ ++ out_err: ++ return -1; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_exit ++* ++***************************************************************************/ ++ ++static void __exit ++vc_mem_exit(void) ++{ ++ pr_debug("%s: called\n", __func__); ++ ++ if (vc_mem_inited) { ++#if CONFIG_DEBUG_FS ++ vc_mem_debugfs_deinit(); ++#endif ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ class_destroy(vc_mem_class); ++ cdev_del(&vc_mem_cdev); ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ } ++} ++ ++module_init(vc_mem_init); ++module_exit(vc_mem_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); ++ ++module_param(phys_addr, uint, 0644); ++module_param(mem_size, uint, 0644); ++module_param(mem_base, uint, 0644); +diff --git a/include/linux/broadcom/vc_mem.h b/include/linux/broadcom/vc_mem.h +new file mode 100644 +index 0000000..20a4753 +--- /dev/null ++++ b/include/linux/broadcom/vc_mem.h +@@ -0,0 +1,35 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#ifndef _VC_MEM_H ++#define _VC_MEM_H ++ ++#include ++ ++#define VC_MEM_IOC_MAGIC 'v' ++ ++#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) ++#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) ++#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) ++#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) ++ ++#if defined( __KERNEL__ ) ++#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF ++ ++extern unsigned long mm_vc_mem_phys_addr; ++extern unsigned int mm_vc_mem_size; ++extern int vc_mem_get_current_size( void ); ++#endif ++ ++#endif /* _VC_MEM_H */ + +From e9ebded52208b6164753a82d268cd80e833e2737 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 012/216] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 15/77] vcsm: VideoCore shared memory service for BCM2835 Add experimental support for the VideoCore shared memory service. This allows user processes to allocate memory from VideoCore's @@ -96823,17 +97624,19 @@ On building the bcm_vc_sm as a module we get the following error: v7_dma_flush_range and do_munmap are undefined in vc-sm.ko. Fix by making it not an option to build as module + +vcsm: Add ioctl for custom cache flushing --- arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h | 181 ++ arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h | 55 + arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h | 82 + - arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 233 ++ - drivers/char/broadcom/Kconfig | 7 + + arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 248 ++ + drivers/char/broadcom/Kconfig | 9 + drivers/char/broadcom/Makefile | 1 + drivers/char/broadcom/vc_sm/Makefile | 21 + drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 492 +++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 3163 ++++++++++++++++++++ - 9 files changed, 4235 insertions(+) + drivers/char/broadcom/vc_sm/vmcs_sm.c | 3211 ++++++++++++++++++++ + 9 files changed, 4300 insertions(+) create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h @@ -97180,10 +97983,10 @@ index 0000000..5e279f5 +#endif /* __VC_VCHI_SM_H__INCLUDED__ */ diff --git a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h new file mode 100644 -index 0000000..42d0eb0 +index 0000000..334f36d --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -@@ -0,0 +1,233 @@ +@@ -0,0 +1,248 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97247,6 +98050,8 @@ index 0000000..42d0eb0 + VMCS_SM_CMD_HOST_WALK_PID_ALLOC, + VMCS_SM_CMD_HOST_WALK_PID_MAP, + ++ VMCS_SM_CMD_CLEAN_INVALID, ++ + VMCS_SM_CMD_LAST /* Do no delete */ +}; + @@ -97349,6 +98154,16 @@ index 0000000..42d0eb0 + unsigned int size; +}; + ++struct vmcs_sm_ioctl_clean_invalid { ++ /* user -> kernel */ ++ struct { ++ unsigned int cmd; ++ unsigned int handle; ++ unsigned int addr; ++ unsigned int size; ++ } s[8]; ++}; ++ +/* IOCTL numbers */ +#define VMCS_SM_IOCTL_MEM_ALLOC\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\ @@ -97377,6 +98192,9 @@ index 0000000..42d0eb0 +#define VMCS_SM_IOCTL_MEM_INVALID\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\ + struct vmcs_sm_ioctl_cache) ++#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\ ++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\ ++ struct vmcs_sm_ioctl_clean_invalid) + +#define VMCS_SM_IOCTL_SIZE_USR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\ @@ -97418,26 +98236,29 @@ index 0000000..42d0eb0 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 2d8bd6e..fd23e00 100644 +index 7037928..75fa1cb 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -13,3 +13,10 @@ config BCM_VC_CMA - default n - help - Helper for videocore CMA access. +@@ -23,3 +23,12 @@ config BCM2708_VCMEM + Helper for videocore memory access and total size allocation. + + endif + +config BCM_VC_SM + bool "VMCS Shared Memory" ++ depends on BCM2708_VCHIQ ++ select BCM2708_VCMEM + default n + help + Support for the VC shared memory on the Broadcom reference + design. Uses the VCHIQ stack. diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 13c5bca..0bf7fdf 100644 +index fce918c..de8feb9 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -1 +1,2 @@ +@@ -1,2 +1,3 @@ obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ + obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ diff --git a/drivers/char/broadcom/vc_sm/Makefile b/drivers/char/broadcom/vc_sm/Makefile new file mode 100644 @@ -97966,10 +98787,10 @@ index 0000000..7c6ba1a +} diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c new file mode 100644 -index 0000000..da1c523 +index 0000000..0bfb42e --- /dev/null +++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -0,0 +1,3163 @@ +@@ -0,0 +1,3211 @@ +/***************************************************************************** +* Copyright 2011-2012 Broadcom Corporation. All rights reserved. +* @@ -97987,6 +98808,7 @@ index 0000000..da1c523 +/* ---- Include Files ----------------------------------------------------- */ + +#include ++#include +#include +#include +#include @@ -98007,8 +98829,6 @@ index 0000000..da1c523 +#include +#include + -+#include -+ +#include "vchiq_connected.h" +#include "vc_vchi_sm.h" + @@ -100704,6 +101524,55 @@ index 0000000..da1c523 + } + break; + ++ /* Flush/Invalidate the cache for a given mapping. */ ++ case VMCS_SM_CMD_CLEAN_INVALID: ++ { ++ int i; ++ struct vmcs_sm_ioctl_clean_invalid ioparam; ++ ++ /* Get parameter data. */ ++ if (copy_from_user(&ioparam, ++ (void *)arg, sizeof(ioparam)) != 0) { ++ pr_err("[%s]: failed to copy-from-user for cmd %x\n", ++ __func__, cmdnr); ++ ret = -EFAULT; ++ goto out; ++ } ++ for (i=0; ires_cached) { ++ unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1); ++ unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1); ++ resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++; ++ ++ /* L1/L2 cache flush */ ++ down_read(¤t->mm->mmap_sem); ++ vcsm_vma_cache_clean_page_range(base, end); ++ up_read(¤t->mm->mmap_sem); ++ } else if (resource == NULL) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (resource) ++ vmcs_sm_release_resource(resource, 0); ++ } ++ break; ++ } ++ } ++ } ++ break; ++ + default: + { + ret = -EINVAL; @@ -101134,23 +102003,32 @@ index 0000000..da1c523 +MODULE_DESCRIPTION("VideoCore SharedMemory Driver"); +MODULE_LICENSE("GPL v2"); -From 103cb0411fad640ec86640f3fda90a3da782aa68 Mon Sep 17 00:00:00 2001 +From 7f769de038003dcf3f6eff180e2e295888789dc2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 013/216] Add hwrng (hardware random number generator) driver +Subject: [PATCH 16/77] Add hwrng (hardware random number generator) driver --- - drivers/char/hw_random/Kconfig | 11 ++++ + drivers/char/hw_random/Kconfig | 13 +++- drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/bcm2708-rng.c | 118 +++++++++++++++++++++++++++++++++++ - 3 files changed, 130 insertions(+) + 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100755 drivers/char/hw_random/bcm2708-rng.c diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index de57b38..1c97093 100644 +index f48cf11..70f9613 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig -@@ -320,6 +320,17 @@ config HW_RANDOM_TPM +@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX + + config HW_RANDOM_BCM2835 + tristate "Broadcom BCM2835 Random Number Generator support" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number +@@ -333,6 +333,17 @@ config HW_RANDOM_TPM If unsure, say Y. @@ -101169,16 +102047,17 @@ index de57b38..1c97093 100644 tristate "Qualcomm SoCs Random Number Generator support" depends on HW_RANDOM && ARCH_QCOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile -index 0b4cd57..78b019c 100644 +index 055bb01..36be864 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile -@@ -28,5 +28,6 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o - obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o - obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o - obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o +@@ -4,6 +4,7 @@ + + obj-$(CONFIG_HW_RANDOM) += rng-core.o + rng-core-y := core.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o - obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o - obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o + obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o + obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o diff --git a/drivers/char/hw_random/bcm2708-rng.c b/drivers/char/hw_random/bcm2708-rng.c new file mode 100755 index 0000000..340f004 @@ -101304,10 +102183,10 @@ index 0000000..340f004 +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); -From 4e3072cbb7ce07057d091188fc1a3897e3169007 Mon Sep 17 00:00:00 2001 +From 68990b28334ea63cdc56bfe9663025dade9d7822 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 014/216] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 17/77] 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 @@ -101344,11 +102223,19 @@ read_current_timer isn't guaranteed to return values in microseconds, and indeed it doesn't on a Pi2. Issue: linux#827 + +lirc-rpi: Add device tree support, and a suitable overlay + +The overlay supports DT parameters that match the old module +parameters, except that gpio_in_pull should be set using the +strings "up", "down" or "off". + +lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode --- drivers/staging/media/lirc/Kconfig | 6 + drivers/staging/media/lirc/Makefile | 1 + - drivers/staging/media/lirc/lirc_rpi.c | 667 ++++++++++++++++++++++++++++++++++ - 3 files changed, 674 insertions(+) + drivers/staging/media/lirc/lirc_rpi.c | 765 ++++++++++++++++++++++++++++++++++ + 3 files changed, 772 insertions(+) create mode 100644 drivers/staging/media/lirc/lirc_rpi.c diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig @@ -101382,10 +102269,10 @@ index 5430adf..9e53cd0 100644 obj-$(CONFIG_LIRC_SIR) += lirc_sir.o diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c new file mode 100644 -index 0000000..8aa452d +index 0000000..24563ec --- /dev/null +++ b/drivers/staging/media/lirc/lirc_rpi.c -@@ -0,0 +1,667 @@ +@@ -0,0 +1,765 @@ +/* + * lirc_rpi.c + * @@ -101429,6 +102316,7 @@ index 0000000..8aa452d +#include +#include +#include ++#include + +#include + @@ -101691,32 +102579,117 @@ index 0000000..8aa452d + return 0; +} + ++static inline int read_bool_property(const struct device_node *np, ++ const char *propname, ++ bool *out_value) ++{ ++ u32 value = 0; ++ int err = of_property_read_u32(np, propname, &value); ++ if (err == 0) ++ *out_value = (value != 0); ++ return err; ++} ++ ++static void read_pin_settings(struct device_node *node) ++{ ++ u32 pin; ++ int index; ++ ++ for (index = 0; ++ of_property_read_u32_index( ++ node, ++ "brcm,pins", ++ index, ++ &pin) == 0; ++ index++) { ++ u32 function; ++ int err; ++ err = of_property_read_u32_index( ++ node, ++ "brcm,function", ++ index, ++ &function); ++ if (err == 0) { ++ if (function == 1) /* Output */ ++ gpio_out_pin = pin; ++ else if (function == 0) /* Input */ ++ gpio_in_pin = pin; ++ } ++ } ++} ++ +static int init_port(void) +{ + int i, nlow, nhigh, ret; ++ struct device_node *node; ++ ++ node = lirc_rpi_dev->dev.of_node; + + gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip); + -+ if (!gpiochip) ++ /* ++ * Because of the lack of a setpull function, only support ++ * pinctrl-bcm2835 if using device tree. ++ */ ++ if (!gpiochip && node) ++ gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip); ++ ++ if (!gpiochip) { ++ pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n"); + return -ENODEV; -+ -+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_out_pin); -+ ret = -ENODEV; -+ goto exit_init_port; + } + -+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_in_pin); -+ ret = -ENODEV; -+ goto exit_gpio_free_out_pin; ++ if (node) { ++ struct device_node *pins_node; ++ ++ pins_node = of_parse_phandle(node, "pinctrl-0", 0); ++ if (!pins_node) { ++ printk(KERN_ERR LIRC_DRIVER_NAME ++ ": pinctrl settings not found!\n"); ++ ret = -EINVAL; ++ goto exit_init_port; ++ } ++ ++ read_pin_settings(pins_node); ++ ++ of_property_read_u32(node, "rpi,sense", &sense); ++ ++ read_bool_property(node, "rpi,softcarrier", &softcarrier); ++ ++ read_bool_property(node, "rpi,invert", &invert); ++ ++ read_bool_property(node, "rpi,debug", &debug); ++ ++ } ++ else ++ { ++ if (gpio_in_pin >= BCM2708_NR_GPIOS || ++ gpio_out_pin >= BCM2708_NR_GPIOS) { ++ ret = -EINVAL; ++ printk(KERN_ERR LIRC_DRIVER_NAME ++ ": invalid GPIO pin(s) specified!\n"); ++ goto exit_init_port; ++ } ++ ++ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { ++ printk(KERN_ALERT LIRC_DRIVER_NAME ++ ": cant claim gpio pin %d\n", gpio_out_pin); ++ ret = -ENODEV; ++ goto exit_init_port; ++ } ++ ++ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { ++ printk(KERN_ALERT LIRC_DRIVER_NAME ++ ": cant claim gpio pin %d\n", gpio_in_pin); ++ ret = -ENODEV; ++ goto exit_gpio_free_out_pin; ++ } ++ ++ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); ++ gpiochip->direction_input(gpiochip, gpio_in_pin); ++ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); + } + -+ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -+ gpiochip->direction_input(gpiochip, gpio_in_pin); -+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); + gpiochip->set(gpiochip, gpio_out_pin, invert); + + irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin); @@ -101910,15 +102883,23 @@ index 0000000..8aa452d + .owner = THIS_MODULE, +}; + ++static const struct of_device_id lirc_rpi_of_match[] = { ++ { .compatible = "rpi,lirc-rpi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, lirc_rpi_of_match); ++ +static struct platform_driver lirc_rpi_driver = { + .driver = { + .name = LIRC_DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(lirc_rpi_of_match), + }, +}; + +static int __init lirc_rpi_init(void) +{ ++ struct device_node *node; + int result; + + /* Init read buffer. */ @@ -101933,15 +102914,26 @@ index 0000000..8aa452d + goto exit_buffer_free; + } + -+ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -+ if (!lirc_rpi_dev) { -+ result = -ENOMEM; -+ goto exit_driver_unregister; -+ } ++ node = of_find_compatible_node(NULL, NULL, ++ lirc_rpi_of_match[0].compatible); + -+ result = platform_device_add(lirc_rpi_dev); -+ if (result) -+ goto exit_device_put; ++ if (node) { ++ /* DT-enabled */ ++ lirc_rpi_dev = of_find_device_by_node(node); ++ WARN_ON(lirc_rpi_dev->dev.of_node != node); ++ of_node_put(node); ++ } ++ else { ++ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); ++ if (!lirc_rpi_dev) { ++ result = -ENOMEM; ++ goto exit_driver_unregister; ++ } ++ ++ result = platform_device_add(lirc_rpi_dev); ++ if (result) ++ goto exit_device_put; ++ } + + return 0; + @@ -101973,13 +102965,6 @@ index 0000000..8aa452d + if (result) + return result; + -+ if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) { -+ result = -EINVAL; -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": invalid GPIO pin(s) specified!\n"); -+ goto exit_rpi; -+ } -+ + result = init_port(); + if (result < 0) + goto exit_rpi; @@ -102054,40 +103039,29 @@ index 0000000..8aa452d +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -From 123948742379f19e1c2764020d8c523d445550bf Mon Sep 17 00:00:00 2001 +From b359d4ff9144f1ee3f333eee7b49bab1c6d92c1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 015/216] Add cpufreq driver +Subject: [PATCH 18/77] Add cpufreq driver +Signed-off-by: popcornmix --- - arch/arm/Kconfig | 1 + - drivers/cpufreq/Kconfig.arm | 8 ++ + drivers/cpufreq/Kconfig.arm | 9 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/bcm2835-cpufreq.c | 224 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 234 insertions(+) - create mode 100755 drivers/cpufreq/bcm2835-cpufreq.c + 3 files changed, 234 insertions(+) + create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index ee1bb5e..9fcd395 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -378,6 +378,7 @@ config ARCH_BCM2708 - select NEED_MACH_GPIO_H - select NEED_MACH_MEMORY_H - select CLKDEV_LOOKUP -+ select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS - select ARM_ERRATA_411920 - select MACH_BCM2708 diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 1b06fc4..0b90de8 100644 +index 4f3dbc8..a1039f0 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -249,6 +249,14 @@ config ARM_SPEAR_CPUFREQ +@@ -258,6 +258,15 @@ config ARM_SPEAR_CPUFREQ help This adds the CPUFreq driver support for SPEAr SOCs. +config ARM_BCM2835_CPUFREQ ++ depends on BCM2708_MBOX + bool "BCM2835 Driver" + default y + help @@ -102099,10 +103073,10 @@ index 1b06fc4..0b90de8 100644 bool "TEGRA CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 82a1821..50b1954 100644 +index cdce92a..c420f3f 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o +@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o @@ -102111,8 +103085,8 @@ index 82a1821..50b1954 100644 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -new file mode 100755 -index 0000000..447ca09 +new file mode 100644 +index 0000000..6735da9 --- /dev/null +++ b/drivers/cpufreq/bcm2835-cpufreq.c @@ -0,0 +1,224 @@ @@ -102144,7 +103118,7 @@ index 0000000..447ca09 +#include +#include +#include -+#include ++#include + +/* ---------- DEFINES ---------- */ +/*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */ @@ -102341,36 +103315,39 @@ index 0000000..447ca09 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From f563316302e117df98e91a8e1366dae653094f04 Mon Sep 17 00:00:00 2001 +From 37e551cc949ea14042539b089e08df475bab0f59 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 016/216] Added hwmon/thermal driver for reporting core +Subject: [PATCH 19/77] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +BCM270x: Move thermal sensor to Device Tree + +Add Device Tree support to bcm2835-thermal driver. +Add thermal sensor device to Device Tree. +Don't add platform device when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/bcm2708.c | 11 ++ - drivers/hwmon/Kconfig | 10 ++ - drivers/hwmon/Makefile | 1 + - drivers/hwmon/bcm2835-hwmon.c | 219 ++++++++++++++++++++++++++++++++++++++ - drivers/thermal/Kconfig | 6 ++ + arch/arm/mach-bcm2708/bcm2708.c | 6 ++ + arch/arm/mach-bcm2709/bcm2709.c | 6 ++ + drivers/thermal/Kconfig | 7 ++ drivers/thermal/Makefile | 1 + - drivers/thermal/bcm2835-thermal.c | 184 ++++++++++++++++++++++++++++++++ - 7 files changed, 432 insertions(+) - create mode 100644 drivers/hwmon/bcm2835-hwmon.c + drivers/thermal/bcm2835-thermal.c | 190 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 210 insertions(+) create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f54e3e9b..bae8ba5 100644 +index 86011af..f2d9b03 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -499,6 +499,14 @@ static struct platform_device bcm2708_alsa_devices[] = { +@@ -505,6 +505,10 @@ static struct platform_device bcm2708_alsa_devices[] = { }, }; -+static struct platform_device bcm2835_hwmon_device = { -+ .name = "bcm2835_hwmon", -+}; -+ +static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", +}; @@ -102378,283 +103355,49 @@ index f54e3e9b..bae8ba5 100644 int __init bcm_register_device(struct platform_device *pdev) { int ret; -@@ -611,6 +619,9 @@ void __init bcm2708_init(void) +@@ -651,6 +655,8 @@ void __init bcm2708_init(void) for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); + bcm_register_device_dt(&bcm2708_alsa_devices[i]); -+ bcm_register_device(&bcm2835_hwmon_device); -+ bcm_register_device(&bcm2835_thermal_device); ++ bcm_register_device_dt(&bcm2835_thermal_device); + - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 110fade..8c4474d 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -1703,6 +1703,16 @@ config SENSORS_ULTRA45 - This driver provides support for the Ultra45 workstation environmental - sensors. + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index bc1ee1c..9631bdb 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -525,6 +525,10 @@ static struct platform_device bcm2708_alsa_devices[] = { + }, + }; -+config SENSORS_BCM2835 -+ depends on THERMAL_BCM2835=n -+ tristate "Broadcom BCM2835 HWMON Driver" -+ help -+ If you say yes here you get support for the hardware -+ monitoring features of the BCM2835 Chip ++static struct platform_device bcm2835_thermal_device = { ++ .name = "bcm2835_thermal", ++}; + -+ This driver can also be built as a module. If so, the module -+ will be called bcm2835-hwmon. -+ - if ACPI + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -671,6 +675,8 @@ void __init bcm2709_init(void) + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device_dt(&bcm2708_alsa_devices[i]); - comment "ACPI drivers" -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 6c94147..e7c60cb 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -155,6 +155,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o - obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o - obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o - obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -+obj-$(CONFIG_SENSORS_BCM2835) += bcm2835-hwmon.o - - obj-$(CONFIG_PMBUS) += pmbus/ - -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -new file mode 100644 -index 0000000..5bbed45 ---- /dev/null -+++ b/drivers/hwmon/bcm2835-hwmon.c -@@ -0,0 +1,219 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ ++ bcm_register_device_dt(&bcm2835_thermal_device); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "bcm2835_hwmon" -+ -+/*#define HWMON_DEBUG_ENABLE*/ -+ -+#ifdef HWMON_DEBUG_ENABLE -+#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__) -+#else -+#define print_debug(fmt,...) -+#endif -+#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__) -+#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__) -+ -+#define VC_TAG_GET_TEMP 0x00030006 -+#define VC_TAG_GET_MAX_TEMP 0x0003000A -+ -+/* --- STRUCTS --- */ -+struct bcm2835_hwmon_data { -+ struct device *hwmon_dev; -+}; -+ -+/* tag part of the message */ -+struct vc_msg_tag { -+ uint32_t tag_id; /* the tag ID for the temperature */ -+ uint32_t buffer_size; /* size of the buffer (should be 8) */ -+ uint32_t request_code; /* identifies message as a request (should be 0) */ -+ uint32_t id; /* extra ID field (should be 0) */ -+ uint32_t val; /* returned value of the temperature */ -+}; -+ -+/* message structure to be sent to videocore */ -+struct vc_msg { -+ uint32_t msg_size; /* simply, sizeof(struct vc_msg) */ -+ uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */ -+ struct vc_msg_tag tag; /* the tag structure above to make */ -+ uint32_t end_tag; /* an end identifier, should be set to NULL */ -+}; -+ -+typedef enum { -+ TEMP, -+ MAX_TEMP, -+} temp_type; -+ -+/* --- PROTOTYPES --- */ -+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf); -+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf); -+ -+/* --- GLOBALS --- */ -+ -+static struct bcm2835_hwmon_data *bcm2835_data; -+static struct platform_driver bcm2835_hwmon_driver; -+ -+static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0); -+static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP); -+static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP); -+ -+static struct attribute* bcm2835_attributes[] = { -+ &sensor_dev_attr_name.dev_attr.attr, -+ &sensor_dev_attr_temp1_input.dev_attr.attr, -+ &sensor_dev_attr_temp1_max.dev_attr.attr, -+ NULL, -+}; -+ -+static struct attribute_group bcm2835_attr_group = { -+ .attrs = bcm2835_attributes, -+}; -+ -+/* --- FUNCTIONS --- */ -+ -+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf,"bcm2835_hwmon\n"); -+} -+ -+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct vc_msg msg; -+ int result; -+ uint temp = 0; -+ int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index; -+ -+ print_debug("IN"); -+ -+ /* wipe all previous message data */ -+ memset(&msg, 0, sizeof msg); -+ -+ /* determine the message type */ -+ if(index == TEMP) -+ msg.tag.tag_id = VC_TAG_GET_TEMP; -+ else if (index == MAX_TEMP) -+ msg.tag.tag_id = VC_TAG_GET_MAX_TEMP; -+ else -+ { -+ print_debug("Unknown temperature message!"); -+ return -EINVAL; -+ } -+ -+ msg.msg_size = sizeof msg; -+ msg.tag.buffer_size = 8; -+ -+ /* send the message */ -+ result = bcm_mailbox_property(&msg, sizeof msg); -+ -+ /* check if it was all ok and return the rate in milli degrees C */ -+ if (result == 0 && (msg.request_code & 0x80000000)) -+ temp = (uint)msg.tag.val; -+ #ifdef HWMON_DEBUG_ENABLE -+ else -+ print_debug("Failed to get temperature!"); -+ #endif -+ print_debug("Got temperature as %u",temp); -+ print_debug("OUT"); -+ return sprintf(buf, "%u\n", temp); -+} -+ -+ -+static int bcm2835_hwmon_probe(struct platform_device *pdev) -+{ -+ int err; -+ -+ print_debug("IN"); -+ print_debug("HWMON Driver has been probed!"); -+ -+ /* check that the device isn't null!*/ -+ if(pdev == NULL) -+ { -+ print_debug("Platform device is empty!"); -+ return -ENODEV; -+ } -+ -+ /* allocate memory for neccessary data */ -+ bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL); -+ if(!bcm2835_data) -+ { -+ print_debug("Unable to allocate memory for hwmon data!"); -+ err = -ENOMEM; -+ goto kzalloc_error; -+ } -+ -+ /* create the sysfs files */ -+ if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group)) -+ { -+ print_debug("Unable to create sysfs files!"); -+ err = -EFAULT; -+ goto sysfs_error; -+ } -+ -+ /* register the hwmon device */ -+ bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev); -+ if (IS_ERR(bcm2835_data->hwmon_dev)) -+ { -+ err = PTR_ERR(bcm2835_data->hwmon_dev); -+ goto hwmon_error; -+ } -+ print_debug("OUT"); -+ return 0; -+ -+ /* error goto's */ -+ hwmon_error: -+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -+ -+ sysfs_error: -+ kfree(bcm2835_data); -+ -+ kzalloc_error: -+ -+ return err; -+ -+} -+ -+static int bcm2835_hwmon_remove(struct platform_device *pdev) -+{ -+ print_debug("IN"); -+ hwmon_device_unregister(bcm2835_data->hwmon_dev); -+ -+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -+ print_debug("OUT"); -+ return 0; -+} -+ -+/* Hwmon Driver */ -+static struct platform_driver bcm2835_hwmon_driver = { -+ .probe = bcm2835_hwmon_probe, -+ .remove = bcm2835_hwmon_remove, -+ .driver = { -+ .name = "bcm2835_hwmon", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dorian Peake"); -+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip"); -+ -+module_platform_driver(bcm2835_hwmon_driver); + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index af40db0..4584b1e 100644 +index af40db0..ddc77ad 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -238,6 +238,12 @@ config INTEL_POWERCLAMP +@@ -238,6 +238,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. +config THERMAL_BCM2835 ++ depends on BCM2708_MBOX + tristate "BCM2835 Thermal Driver" + help + This will enable temperature monitoring for the Broadcom BCM2835 @@ -102677,10 +103420,10 @@ index fa0dc48..453d4d9 100644 obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c new file mode 100644 -index 0000000..85fceb5 +index 0000000..3bc80f1 --- /dev/null +++ b/drivers/thermal/bcm2835-thermal.c -@@ -0,0 +1,184 @@ +@@ -0,0 +1,190 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -102698,10 +103441,10 @@ index 0000000..85fceb5 +#include +#include +#include ++#include +#include +#include +#include -+#include +#include + + @@ -102850,13 +103593,19 @@ index 0000000..85fceb5 + .get_mode = bcm2835_get_mode, +}; + -+/* Thermal Driver */ ++static const struct of_device_id bcm2835_thermal_of_match_table[] = { ++ { .compatible = "brcm,bcm2835-thermal", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); ++ +static struct platform_driver bcm2835_thermal_driver = { + .probe = bcm2835_thermal_probe, + .remove = bcm2835_thermal_remove, + .driver = { + .name = "bcm2835_thermal", + .owner = THIS_MODULE, ++ .of_match_table = bcm2835_thermal_of_match_table, + }, +}; + @@ -102866,49 +103615,58 @@ index 0000000..85fceb5 + +module_platform_driver(bcm2835_thermal_driver); -From bb1c2fec8850e0e017e3b80f51df5dc850627555 Mon Sep 17 00:00:00 2001 +From 4d5da3fa21e1d94e38644bf9a5493bb677854e42 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Mon, 4 Nov 2013 18:56:10 +0000 -Subject: [PATCH 017/216] Add Chris Boot's i2c and spi drivers. +Date: Wed, 17 Jun 2015 15:41:33 +0100 +Subject: [PATCH 20/77] Add Chris Boot's spi driver. -i2c-bcm2708: fixed baudrate +spi: bcm2708: add device tree support -Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock). -In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits. -This resulted in incorrect setting of CDIV and higher baudrate than intended. -Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz -After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz -The correct baudrate is shown in the log after the cdiv > 0xffff correction. +Add DT support to driver and add to .dtsi file. +Setup pins and spidev in .dts file. +SPI is disabled by default. -Perform I2C combined transactions when possible +Signed-off-by: Noralf Tronnes -Perform I2C combined transactions whenever possible, within the -restrictions of the Broadcomm Serial Controller. +BCM2708: don't register SPI controller when using DT -Disable DONE interrupt during TA poll +The device for the SPI controller is in the Device Tree. +Only register the device when not using DT. -Prevent interrupt from being triggered if poll is missed and transfer -starts and finishes. +Signed-off-by: Noralf Tronnes -i2c: Make combined transactions optional and disabled by default +spi: bcm2835: make driver available on ARCH_BCM2708 + +Make this driver available on ARCH_BCM2708 + +Signed-off-by: Noralf Tronnes + +bcm2708: Remove the prohibition on mixing SPIDEV and DT + +spi-bcm2708: Prepare for Common Clock Framework migration + +As part of migrating to use the Common Clock Framework, replace clk_enable() +with clk_prepare_enable() and clk_disable() with clk_disable_unprepare(). +This does not affect behaviour under the current clock implementation. + +Also add a missing clk_disable_unprepare() in the probe error path. + +Signed-off-by: Noralf Tronnes --- - arch/arm/mach-bcm2708/Kconfig | 7 + - arch/arm/mach-bcm2708/bcm2708.c | 104 ++++++- - drivers/i2c/busses/Kconfig | 19 ++ - drivers/i2c/busses/Makefile | 2 + - drivers/i2c/busses/i2c-bcm2708.c | 449 ++++++++++++++++++++++++++++ - drivers/spi/Kconfig | 8 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-bcm2708.c | 626 +++++++++++++++++++++++++++++++++++++++ - 8 files changed, 1214 insertions(+), 2 deletions(-) - create mode 100644 drivers/i2c/busses/i2c-bcm2708.c + arch/arm/mach-bcm2708/Kconfig | 7 + + arch/arm/mach-bcm2708/bcm2708.c | 53 ++++ + arch/arm/mach-bcm2709/bcm2709.c | 53 ++++ + drivers/spi/Kconfig | 10 +- + drivers/spi/Makefile | 1 + + drivers/spi/spi-bcm2708.c | 635 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 758 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/spi-bcm2708.c diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 9355841..e151ed4 100644 +index 4cbda0c..68e3706 100644 --- a/arch/arm/mach-bcm2708/Kconfig +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -31,4 +31,11 @@ config BCM2708_NOL2CACHE +@@ -35,4 +35,11 @@ config BCM2708_NOL2CACHE help Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. @@ -102921,50 +103679,18 @@ index 9355841..e151ed4 100644 + Binds spidev driver to the SPI0 master endmenu diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index bae8ba5..752dd46 100644 +index f2d9b03..e3aa6fc 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -31,6 +31,7 @@ - #include +@@ -34,6 +34,7 @@ #include #include + #include +#include + #include #include - #include -@@ -205,7 +206,6 @@ static struct clk osc_clk = { - - /* warning - the USB needs a clock > 34MHz */ - --#ifdef CONFIG_MMC_BCM2708 - static struct clk sdhost_clk = { - #ifdef CONFIG_ARCH_BCM2708_CHIPIT - .rate = 4000000, /* 4MHz */ -@@ -213,7 +213,6 @@ static struct clk sdhost_clk = { - .rate = 250000000, /* 250MHz */ - #endif - }; --#endif - - static struct clk_lookup lookups[] = { - { /* UART0 */ -@@ -223,6 +222,15 @@ static struct clk_lookup lookups[] = { - { /* USB */ - .dev_id = "bcm2708_usb", - .clk = &osc_clk, -+ }, { /* SPI */ -+ .dev_id = "bcm2708_spi.0", -+ .clk = &sdhost_clk, -+ }, { /* BSC0 */ -+ .dev_id = "bcm2708_i2c.0", -+ .clk = &sdhost_clk, -+ }, { /* BSC1 */ -+ .dev_id = "bcm2708_i2c.1", -+ .clk = &sdhost_clk, - } - }; - -@@ -499,6 +507,89 @@ static struct platform_device bcm2708_alsa_devices[] = { +@@ -505,6 +506,50 @@ static struct platform_device bcm2708_alsa_devices[] = { }, }; @@ -103012,580 +103738,136 @@ index bae8ba5..752dd46 100644 +}; +#endif + -+static struct resource bcm2708_bsc0_resources[] = { -+ { -+ .start = BSC0_BASE, -+ .end = BSC0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc0_device = { -+ .name = "bcm2708_i2c", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), -+ .resource = bcm2708_bsc0_resources, -+}; -+ -+ -+static struct resource bcm2708_bsc1_resources[] = { -+ { -+ .start = BSC1_BASE, -+ .end = BSC1_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc1_device = { -+ .name = "bcm2708_i2c", -+ .id = 1, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), -+ .resource = bcm2708_bsc1_resources, -+}; -+ - static struct platform_device bcm2835_hwmon_device = { - .name = "bcm2835_hwmon", + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", }; -@@ -619,6 +710,10 @@ void __init bcm2708_init(void) +@@ -655,6 +700,8 @@ void __init bcm2708_init(void) for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); + bcm_register_device_dt(&bcm2708_alsa_devices[i]); -+ bcm_register_device(&bcm2708_spi_device); -+ bcm_register_device(&bcm2708_bsc0_device); -+ bcm_register_device(&bcm2708_bsc1_device); ++ bcm_register_device_dt(&bcm2708_spi_device); + - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); + bcm_register_device_dt(&bcm2835_thermal_device); -@@ -628,6 +723,11 @@ void __init bcm2708_init(void) + if (!use_dt) { +@@ -665,6 +712,12 @@ void __init bcm2708_init(void) } system_rev = boardrev; system_serial_low = serial; + +#ifdef CONFIG_BCM2708_SPIDEV -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); ++ if (!use_dt) ++ spi_register_board_info(bcm2708_spi_devices, ++ ARRAY_SIZE(bcm2708_spi_devices)); +#endif } static void timer_set_mode(enum clock_event_mode mode, -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 22da9c2..00c7baa 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" - comment "PC SMBus host controller drivers" - depends on PCI +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 9631bdb..5fb99b6 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include -+config I2C_BCM2708 -+ tristate "BCM2708 BSC" -+ depends on MACH_BCM2708 -+ help -+ Enabling this option will add BSC (Broadcom Serial Controller) -+ support for the BCM2708. BSC is a Broadcom proprietary bus compatible -+ with I2C/TWI/SMBus. -+ -+config I2C_BCM2708_BAUDRATE -+ prompt "BCM2708 I2C baudrate" -+ depends on I2C_BCM2708 -+ int -+ default 100000 -+ help -+ Set the I2C baudrate. This will alter the default value. A -+ different baudrate can be set by using a module parameter as well. If -+ no parameter is provided when loading, this is the value that will be -+ used. -+ - config I2C_ALI1535 - tristate "ALI 1535" - depends on PCI -diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 3638feb..4905fae 100644 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -2,6 +2,8 @@ - # Makefile for the i2c bus drivers. - # + #include +@@ -525,6 +526,50 @@ static struct platform_device bcm2708_alsa_devices[] = { + }, + }; -+obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o -+ - # ACPI drivers - obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -new file mode 100644 -index 0000000..7d385a3 ---- /dev/null -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -0,0 +1,449 @@ -+/* -+ * Driver for Broadcom BCM2708 BSC Controllers -+ * -+ * Copyright (C) 2012 Chris Boot & Frank Buss -+ * -+ * This driver is inspired by: -+ * i2c-ocores.c, by Peter Korsgaard -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* BSC register offsets */ -+#define BSC_C 0x00 -+#define BSC_S 0x04 -+#define BSC_DLEN 0x08 -+#define BSC_A 0x0c -+#define BSC_FIFO 0x10 -+#define BSC_DIV 0x14 -+#define BSC_DEL 0x18 -+#define BSC_CLKT 0x1c -+ -+/* Bitfields in BSC_C */ -+#define BSC_C_I2CEN 0x00008000 -+#define BSC_C_INTR 0x00000400 -+#define BSC_C_INTT 0x00000200 -+#define BSC_C_INTD 0x00000100 -+#define BSC_C_ST 0x00000080 -+#define BSC_C_CLEAR_1 0x00000020 -+#define BSC_C_CLEAR_2 0x00000010 -+#define BSC_C_READ 0x00000001 -+ -+/* Bitfields in BSC_S */ -+#define BSC_S_CLKT 0x00000200 -+#define BSC_S_ERR 0x00000100 -+#define BSC_S_RXF 0x00000080 -+#define BSC_S_TXE 0x00000040 -+#define BSC_S_RXD 0x00000020 -+#define BSC_S_TXD 0x00000010 -+#define BSC_S_RXR 0x00000008 -+#define BSC_S_TXW 0x00000004 -+#define BSC_S_DONE 0x00000002 -+#define BSC_S_TA 0x00000001 -+ -+#define I2C_TIMEOUT_MS 150 -+ -+#define DRV_NAME "bcm2708_i2c" -+ -+static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; -+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(baudrate, "The I2C baudrate"); -+ -+static bool combined = false; -+module_param(combined, bool, 0644); -+MODULE_PARM_DESC(combined, "Use combined transactions"); -+ -+struct bcm2708_i2c { -+ struct i2c_adapter adapter; -+ -+ spinlock_t lock; -+ void __iomem *base; -+ int irq; -+ struct clk *clk; -+ -+ struct completion done; -+ -+ struct i2c_msg *msg; -+ int pos; -+ int nmsgs; -+ bool error; -+}; -+ -+/* -+ * This function sets the ALT mode on the I2C pins so that we can use them with -+ * the BSC hardware. -+ * -+ * FIXME: This is a hack. Use pinmux / pinctrl. -+ */ -+static void bcm2708_i2c_init_pinmode(int id) -+{ -+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) -+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) -+ -+ int pin; -+ u32 *gpio = ioremap(GPIO_BASE, SZ_16K); -+ -+ BUG_ON(id != 0 && id != 1); -+ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ -+ for (pin = id*2+0; pin <= id*2+1; pin++) { -+printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); -+ INP_GPIO(pin); /* set mode to GPIO input first */ -+ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ -+ } -+ -+ iounmap(gpio); -+ -+#undef INP_GPIO -+#undef SET_GPIO_ALT -+} -+ -+static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg) -+{ -+ return readl(bi->base + reg); -+} -+ -+static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) -+{ -+ writel(val, bi->base + reg); -+} -+ -+static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) -+{ -+ bcm2708_wr(bi, BSC_C, 0); -+ bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); -+} -+ -+static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi) -+{ -+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len)) -+ bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO); -+} -+ -+static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) -+{ -+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len)) -+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+} -+ -+static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) -+{ -+ unsigned long bus_hz; -+ u32 cdiv, s; -+ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; -+ -+ bus_hz = clk_get_rate(bi->clk); -+ cdiv = bus_hz / baudrate; -+ if (cdiv > 0xffff) -+ cdiv = 0xffff; -+ -+ if (bi->msg->flags & I2C_M_RD) -+ c |= BSC_C_INTR | BSC_C_READ; -+ else -+ c |= BSC_C_INTT; -+ -+ bcm2708_wr(bi, BSC_DIV, cdiv); -+ bcm2708_wr(bi, BSC_A, bi->msg->addr); -+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); -+ if (combined) ++static struct resource bcm2708_spi_resources[] = { + { -+ /* Do the next two messages meet combined transaction criteria? -+ - Current message is a write, next message is a read -+ - Both messages to same slave address -+ - Write message can fit inside FIFO (16 bytes or less) */ -+ if ( (bi->nmsgs > 1) && -+ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -+ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { -+ /* Fill FIFO with entire write message (16 byte FIFO) */ -+ while (bi->pos < bi->msg->len) -+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+ /* Start write transfer (no interrupts, don't clear FIFO) */ -+ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); -+ /* poll for transfer start bit (should only take 1-20 polls) */ -+ do { -+ s = bcm2708_rd(bi, BSC_S); -+ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE))); -+ /* Send next read message before the write transfer finishes. */ -+ bi->nmsgs--; -+ bi->msg++; -+ bi->pos = 0; -+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); -+ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ; -+ } ++ .start = SPI0_BASE, ++ .end = SPI0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_SPI, ++ .end = IRQ_SPI, ++ .flags = IORESOURCE_IRQ, + } -+ bcm2708_wr(bi, BSC_C, c); -+} -+ -+static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) -+{ -+ struct bcm2708_i2c *bi = dev_id; -+ bool handled = true; -+ u32 s; -+ -+ spin_lock(&bi->lock); -+ -+ /* we may see camera interrupts on the "other" I2C channel -+ Just return if we've not sent anything */ -+ if (!bi->nmsgs || !bi->msg ) -+ goto early_exit; -+ -+ s = bcm2708_rd(bi, BSC_S); -+ -+ if (s & (BSC_S_CLKT | BSC_S_ERR)) { -+ bcm2708_bsc_reset(bi); -+ bi->error = true; -+ -+ /* wake up our bh */ -+ complete(&bi->done); -+ } else if (s & BSC_S_DONE) { -+ bi->nmsgs--; -+ -+ if (bi->msg->flags & I2C_M_RD) -+ bcm2708_bsc_fifo_drain(bi); -+ -+ bcm2708_bsc_reset(bi); -+ -+ if (bi->nmsgs) { -+ /* advance to next message */ -+ bi->msg++; -+ bi->pos = 0; -+ bcm2708_bsc_setup(bi); -+ } else { -+ /* wake up our bh */ -+ complete(&bi->done); -+ } -+ } else if (s & BSC_S_TXW) { -+ bcm2708_bsc_fifo_fill(bi); -+ } else if (s & BSC_S_RXR) { -+ bcm2708_bsc_fifo_drain(bi); -+ } else { -+ handled = false; -+ } -+ -+early_exit: -+ spin_unlock(&bi->lock); -+ -+ return handled ? IRQ_HANDLED : IRQ_NONE; -+} -+ -+static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, -+ struct i2c_msg *msgs, int num) -+{ -+ struct bcm2708_i2c *bi = adap->algo_data; -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&bi->lock, flags); -+ -+ reinit_completion(&bi->done); -+ bi->msg = msgs; -+ bi->pos = 0; -+ bi->nmsgs = num; -+ bi->error = false; -+ -+ bcm2708_bsc_setup(bi); -+ -+ /* unlockig _after_ the setup to avoid races with the interrupt routine */ -+ spin_unlock_irqrestore(&bi->lock, flags); -+ -+ ret = wait_for_completion_timeout(&bi->done, -+ msecs_to_jiffies(I2C_TIMEOUT_MS)); -+ if (ret == 0) { -+ dev_err(&adap->dev, "transfer timed out\n"); -+ spin_lock_irqsave(&bi->lock, flags); -+ bcm2708_bsc_reset(bi); -+ spin_unlock_irqrestore(&bi->lock, flags); -+ return -ETIMEDOUT; -+ } -+ -+ return bi->error ? -EIO : num; -+} -+ -+static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL; -+} -+ -+static struct i2c_algorithm bcm2708_i2c_algorithm = { -+ .master_xfer = bcm2708_i2c_master_xfer, -+ .functionality = bcm2708_i2c_functionality, +}; + -+static int bcm2708_i2c_probe(struct platform_device *pdev) -+{ -+ struct resource *regs; -+ int irq, err = -ENOMEM; -+ struct clk *clk; -+ struct bcm2708_i2c *bi; -+ struct i2c_adapter *adap; -+ unsigned long bus_hz; -+ u32 cdiv; + -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) { -+ dev_err(&pdev->dev, "could not get IO memory\n"); -+ return -ENXIO; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "could not get IRQ\n"); -+ return irq; -+ } -+ -+ clk = clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk)); -+ return PTR_ERR(clk); -+ } -+ -+ bcm2708_i2c_init_pinmode(pdev->id); -+ -+ bi = kzalloc(sizeof(*bi), GFP_KERNEL); -+ if (!bi) -+ goto out_clk_put; -+ -+ platform_set_drvdata(pdev, bi); -+ -+ adap = &bi->adapter; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC; -+ adap->algo = &bcm2708_i2c_algorithm; -+ adap->algo_data = bi; -+ adap->dev.parent = &pdev->dev; -+ adap->nr = pdev->id; -+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ -+ switch (pdev->id) { -+ case 0: -+ adap->class = I2C_CLASS_HWMON; -+ break; -+ case 1: -+ adap->class = I2C_CLASS_DDC; -+ break; -+ default: -+ dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n"); -+ err = -ENXIO; -+ goto out_free_bi; -+ } -+ -+ spin_lock_init(&bi->lock); -+ init_completion(&bi->done); -+ -+ bi->base = ioremap(regs->start, resource_size(regs)); -+ if (!bi->base) { -+ dev_err(&pdev->dev, "could not remap memory\n"); -+ goto out_free_bi; -+ } -+ -+ bi->irq = irq; -+ bi->clk = clk; -+ -+ err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED, -+ dev_name(&pdev->dev), bi); -+ if (err) { -+ dev_err(&pdev->dev, "could not request IRQ: %d\n", err); -+ goto out_iounmap; -+ } -+ -+ bcm2708_bsc_reset(bi); -+ -+ err = i2c_add_numbered_adapter(adap); -+ if (err < 0) { -+ dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); -+ goto out_free_irq; -+ } -+ -+ bus_hz = clk_get_rate(bi->clk); -+ cdiv = bus_hz / baudrate; -+ if (cdiv > 0xffff) { -+ cdiv = 0xffff; -+ baudrate = bus_hz / cdiv; -+ } -+ -+ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", -+ pdev->id, (unsigned long)regs->start, irq, baudrate); -+ -+ return 0; -+ -+out_free_irq: -+ free_irq(bi->irq, bi); -+out_iounmap: -+ iounmap(bi->base); -+out_free_bi: -+ kfree(bi); -+out_clk_put: -+ clk_put(clk); -+ return err; -+} -+ -+static int bcm2708_i2c_remove(struct platform_device *pdev) -+{ -+ struct bcm2708_i2c *bi = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ i2c_del_adapter(&bi->adapter); -+ free_irq(bi->irq, bi); -+ iounmap(bi->base); -+ clk_disable(bi->clk); -+ clk_put(bi->clk); -+ kfree(bi); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm2708_i2c_driver = { -+ .driver = { -+ .name = DRV_NAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = bcm2708_i2c_probe, -+ .remove = bcm2708_i2c_remove, ++static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++static struct platform_device bcm2708_spi_device = { ++ .name = "bcm2708_spi", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_spi_resources), ++ .resource = bcm2708_spi_resources, ++ .dev = { ++ .dma_mask = &bcm2708_spi_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, +}; + -+// module_platform_driver(bcm2708_i2c_driver); ++#ifdef CONFIG_BCM2708_SPIDEV ++static struct spi_board_info bcm2708_spi_devices[] = { ++#ifdef CONFIG_SPI_SPIDEV ++ { ++ .modalias = "spidev", ++ .max_speed_hz = 500000, ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_0, ++ }, { ++ .modalias = "spidev", ++ .max_speed_hz = 500000, ++ .bus_num = 0, ++ .chip_select = 1, ++ .mode = SPI_MODE_0, ++ } ++#endif ++}; ++#endif + + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -675,6 +720,8 @@ void __init bcm2709_init(void) + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device_dt(&bcm2708_alsa_devices[i]); + ++ bcm_register_device_dt(&bcm2708_spi_device); + -+static int __init bcm2708_i2c_init(void) -+{ -+ return platform_driver_register(&bcm2708_i2c_driver); -+} + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -685,6 +732,12 @@ void __init bcm2709_init(void) + } + system_rev = boardrev; + system_serial_low = serial; + -+static void __exit bcm2708_i2c_exit(void) -+{ -+ platform_driver_unregister(&bcm2708_i2c_driver); -+} -+ -+module_init(bcm2708_i2c_init); -+module_exit(bcm2708_i2c_exit); -+ -+ -+ -+MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); -+MODULE_AUTHOR("Chris Boot "); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:" DRV_NAME); ++#ifdef CONFIG_BCM2708_SPIDEV ++ if (!use_dt) ++ spi_register_board_info(bcm2708_spi_devices, ++ ARRAY_SIZE(bcm2708_spi_devices)); ++#endif + } + + #ifdef SYSTEM_TIMER diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index ab8dfbe..9628e75 100644 +index 72b0590..ea5e5de 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -86,6 +86,14 @@ config SPI_BCM2835 +@@ -77,7 +77,7 @@ config SPI_ATMEL + + config SPI_BCM2835 + tristate "BCM2835 SPI controller" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on GPIOLIB + help + This selects a driver for the Broadcom BCM2835 SPI master. +@@ -87,6 +87,14 @@ config SPI_BCM2835 is for the regular SPI controller. Slave mode operation is not also not supported. +config SPI_BCM2708 + tristate "BCM2708 SPI controller driver (SPI0)" -+ depends on MACH_BCM2708 ++ depends on MACH_BCM2708 || MACH_BCM2709 + help + This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This + driver is not compatible with the "Universal SPI Master" or the SPI slave @@ -103608,10 +103890,10 @@ index d8cbf65..0dcd03d 100644 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c new file mode 100644 -index 0000000..b04a57d +index 0000000..041b5e2 --- /dev/null +++ b/drivers/spi/spi-bcm2708.c -@@ -0,0 +1,626 @@ +@@ -0,0 +1,635 @@ +/* + * Driver for Broadcom BCM2708 SPI Controllers + * @@ -104126,6 +104408,7 @@ index 0000000..b04a57d + master->setup = bcm2708_spi_setup; + master->transfer = bcm2708_spi_transfer; + master->cleanup = bcm2708_spi_cleanup; ++ master->dev.of_node = pdev->dev.of_node; + platform_set_drvdata(pdev, master); + + bs = spi_master_get_devdata(master); @@ -104159,7 +104442,7 @@ index 0000000..b04a57d + } + + /* initialise the hardware */ -+ clk_enable(clk); ++ clk_prepare_enable(clk); + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX); + + err = spi_register_master(master); @@ -104175,6 +104458,7 @@ index 0000000..b04a57d + +out_free_irq: + free_irq(bs->irq, master); ++ clk_disable_unprepare(bs->clk); +out_workqueue: + destroy_workqueue(bs->workq); +out_iounmap: @@ -104199,7 +104483,7 @@ index 0000000..b04a57d + + flush_work(&bs->work); + -+ clk_disable(bs->clk); ++ clk_disable_unprepare(bs->clk); + clk_put(bs->clk); + free_irq(bs->irq, master); + iounmap(bs->base); @@ -104209,10 +104493,17 @@ index 0000000..b04a57d + return 0; +} + ++static const struct of_device_id bcm2708_spi_match[] = { ++ { .compatible = "brcm,bcm2708-spi", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_spi_match); ++ +static struct platform_driver bcm2708_spi_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, ++ .of_match_table = bcm2708_spi_match, + }, + .probe = bcm2708_spi_probe, + .remove = bcm2708_spi_remove, @@ -104239,10 +104530,814 @@ index 0000000..b04a57d +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 530db15891390005623b20a03dda6ef6871607bc Mon Sep 17 00:00:00 2001 +From 75d6625177ee7e4746baf70b60380069d58231ba Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 17 Jun 2015 15:44:08 +0100 +Subject: [PATCH 21/77] Add Chris Boot's i2c driver + +i2c-bcm2708: fixed baudrate + +Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock). +In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits. +This resulted in incorrect setting of CDIV and higher baudrate than intended. +Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz +After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz +The correct baudrate is shown in the log after the cdiv > 0xffff correction. + +Perform I2C combined transactions when possible + +Perform I2C combined transactions whenever possible, within the +restrictions of the Broadcomm Serial Controller. + +Disable DONE interrupt during TA poll + +Prevent interrupt from being triggered if poll is missed and transfer +starts and finishes. + +i2c: Make combined transactions optional and disabled by default + +i2c: bcm2708: add device tree support + +Add DT support to driver and add to .dtsi file. +Setup pins in .dts file. +i2c is disabled by default. + +Signed-off-by: Noralf Tronnes + +bcm2708: don't register i2c controllers when using DT + +The devices for the i2c controllers are in the Device Tree. +Only register devices when not using DT. + +Signed-off-by: Noralf Tronnes + +I2C: Only register the I2C device for the current board revision + +i2c_bcm2708: Fix clock reference counting + +Fix grabbing lock from atomic context in i2c driver + +2 main changes: +- check for timeouts in the bcm2708_bsc_setup function as indicated by this comment: + /* poll for transfer start bit (should only take 1-20 polls) */ + This implies that the setup function can now fail so account for this everywhere it's called +- Removed the clk_get_rate call from inside the setup function as it locks a mutex and that's not ok since we call it from under a spin lock. + +i2c-bcm2708: When using DT, leave the GPIO setup to pinctrl +--- + arch/arm/mach-bcm2708/bcm2708.c | 51 ++++ + arch/arm/mach-bcm2709/bcm2709.c | 51 ++++ + drivers/i2c/busses/Kconfig | 21 +- + drivers/i2c/busses/Makefile | 2 + + drivers/i2c/busses/i2c-bcm2708.c | 522 +++++++++++++++++++++++++++++++++++++++ + 5 files changed, 646 insertions(+), 1 deletion(-) + create mode 100644 drivers/i2c/busses/i2c-bcm2708.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index e3aa6fc..efb3544 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -83,6 +83,7 @@ static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static bool vc_i2c_override = false; + + static unsigned use_dt = 0; + +@@ -550,6 +551,45 @@ static struct spi_board_info bcm2708_spi_devices[] = { + }; + #endif + ++static struct resource bcm2708_bsc0_resources[] = { ++ { ++ .start = BSC0_BASE, ++ .end = BSC0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc0_device = { ++ .name = "bcm2708_i2c", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), ++ .resource = bcm2708_bsc0_resources, ++}; ++ ++ ++static struct resource bcm2708_bsc1_resources[] = { ++ { ++ .start = BSC1_BASE, ++ .end = BSC1_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc1_device = { ++ .name = "bcm2708_i2c", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), ++ .resource = bcm2708_bsc1_resources, ++}; ++ + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -702,6 +742,15 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2708_spi_device); + ++ if (vc_i2c_override) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ } else { ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } ++ + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -893,3 +942,5 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(vc_i2c_override, bool, 0644); ++MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 5fb99b6..8017c50 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -85,6 +85,7 @@ static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static bool vc_i2c_override = false; + + static unsigned use_dt = 0; + +@@ -570,6 +571,45 @@ static struct spi_board_info bcm2708_spi_devices[] = { + }; + #endif + ++static struct resource bcm2708_bsc0_resources[] = { ++ { ++ .start = BSC0_BASE, ++ .end = BSC0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc0_device = { ++ .name = "bcm2708_i2c", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), ++ .resource = bcm2708_bsc0_resources, ++}; ++ ++ ++static struct resource bcm2708_bsc1_resources[] = { ++ { ++ .start = BSC1_BASE, ++ .end = BSC1_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc1_device = { ++ .name = "bcm2708_i2c", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), ++ .resource = bcm2708_bsc1_resources, ++}; ++ + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -722,6 +762,15 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2708_spi_device); + ++ if (vc_i2c_override) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ } else { ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } ++ + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -1061,3 +1110,5 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(vc_i2c_override, bool, 0644); ++MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 2255af2..5b0c772 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" + comment "PC SMBus host controller drivers" + depends on PCI + ++config I2C_BCM2708 ++ tristate "BCM2708 BSC" ++ depends on MACH_BCM2708 || MACH_BCM2709 ++ help ++ Enabling this option will add BSC (Broadcom Serial Controller) ++ support for the BCM2708. BSC is a Broadcom proprietary bus compatible ++ with I2C/TWI/SMBus. ++ ++config I2C_BCM2708_BAUDRATE ++ prompt "BCM2708 I2C baudrate" ++ depends on I2C_BCM2708 ++ int ++ default 100000 ++ help ++ Set the I2C baudrate. This will alter the default value. A ++ different baudrate can be set by using a module parameter as well. If ++ no parameter is provided when loading, this is the value that will be ++ used. ++ + config I2C_ALI1535 + tristate "ALI 1535" + depends on PCI +@@ -362,7 +381,7 @@ config I2C_AXXIA + + config I2C_BCM2835 + tristate "Broadcom BCM2835 I2C controller" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + help + If you say yes to this option, support will be included for the + BCM2835 I2C controller. +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index cdf941d..e0176d7 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -2,6 +2,8 @@ + # Makefile for the i2c bus drivers. + # + ++obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o ++ + # ACPI drivers + obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o + +diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c +new file mode 100644 +index 0000000..8773203 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-bcm2708.c +@@ -0,0 +1,522 @@ ++/* ++ * Driver for Broadcom BCM2708 BSC Controllers ++ * ++ * Copyright (C) 2012 Chris Boot & Frank Buss ++ * ++ * This driver is inspired by: ++ * i2c-ocores.c, by Peter Korsgaard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* BSC register offsets */ ++#define BSC_C 0x00 ++#define BSC_S 0x04 ++#define BSC_DLEN 0x08 ++#define BSC_A 0x0c ++#define BSC_FIFO 0x10 ++#define BSC_DIV 0x14 ++#define BSC_DEL 0x18 ++#define BSC_CLKT 0x1c ++ ++/* Bitfields in BSC_C */ ++#define BSC_C_I2CEN 0x00008000 ++#define BSC_C_INTR 0x00000400 ++#define BSC_C_INTT 0x00000200 ++#define BSC_C_INTD 0x00000100 ++#define BSC_C_ST 0x00000080 ++#define BSC_C_CLEAR_1 0x00000020 ++#define BSC_C_CLEAR_2 0x00000010 ++#define BSC_C_READ 0x00000001 ++ ++/* Bitfields in BSC_S */ ++#define BSC_S_CLKT 0x00000200 ++#define BSC_S_ERR 0x00000100 ++#define BSC_S_RXF 0x00000080 ++#define BSC_S_TXE 0x00000040 ++#define BSC_S_RXD 0x00000020 ++#define BSC_S_TXD 0x00000010 ++#define BSC_S_RXR 0x00000008 ++#define BSC_S_TXW 0x00000004 ++#define BSC_S_DONE 0x00000002 ++#define BSC_S_TA 0x00000001 ++ ++#define I2C_TIMEOUT_MS 150 ++#define I2C_WAIT_LOOP_COUNT 40 ++ ++#define DRV_NAME "bcm2708_i2c" ++ ++static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; ++module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(baudrate, "The I2C baudrate"); ++ ++static bool combined = false; ++module_param(combined, bool, 0644); ++MODULE_PARM_DESC(combined, "Use combined transactions"); ++ ++struct bcm2708_i2c { ++ struct i2c_adapter adapter; ++ ++ spinlock_t lock; ++ void __iomem *base; ++ int irq; ++ struct clk *clk; ++ u32 cdiv; ++ ++ struct completion done; ++ ++ struct i2c_msg *msg; ++ int pos; ++ int nmsgs; ++ bool error; ++}; ++ ++/* ++ * This function sets the ALT mode on the I2C pins so that we can use them with ++ * the BSC hardware. ++ * ++ * FIXME: This is a hack. Use pinmux / pinctrl. ++ */ ++static void bcm2708_i2c_init_pinmode(int id) ++{ ++#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) ++#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) ++ ++ int pin; ++ u32 *gpio = ioremap(GPIO_BASE, SZ_16K); ++ ++ BUG_ON(id != 0 && id != 1); ++ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ ++ for (pin = id*2+0; pin <= id*2+1; pin++) { ++ printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); ++ INP_GPIO(pin); /* set mode to GPIO input first */ ++ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ ++ } ++ ++ iounmap(gpio); ++ ++#undef INP_GPIO ++#undef SET_GPIO_ALT ++} ++ ++static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg) ++{ ++ return readl(bi->base + reg); ++} ++ ++static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) ++{ ++ writel(val, bi->base + reg); ++} ++ ++static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) ++{ ++ bcm2708_wr(bi, BSC_C, 0); ++ bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); ++} ++ ++static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi) ++{ ++ while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len)) ++ bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO); ++} ++ ++static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) ++{ ++ while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len)) ++ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); ++} ++ ++static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi) ++{ ++ u32 cdiv, s; ++ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; ++ int wait_loops = I2C_WAIT_LOOP_COUNT; ++ ++ /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked. ++ * Use the value that we cached in the probe. ++ */ ++ cdiv = bi->cdiv; ++ ++ if (bi->msg->flags & I2C_M_RD) ++ c |= BSC_C_INTR | BSC_C_READ; ++ else ++ c |= BSC_C_INTT; ++ ++ bcm2708_wr(bi, BSC_DIV, cdiv); ++ bcm2708_wr(bi, BSC_A, bi->msg->addr); ++ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); ++ if (combined) ++ { ++ /* Do the next two messages meet combined transaction criteria? ++ - Current message is a write, next message is a read ++ - Both messages to same slave address ++ - Write message can fit inside FIFO (16 bytes or less) */ ++ if ( (bi->nmsgs > 1) && ++ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && ++ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { ++ /* Fill FIFO with entire write message (16 byte FIFO) */ ++ while (bi->pos < bi->msg->len) { ++ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); ++ } ++ /* Start write transfer (no interrupts, don't clear FIFO) */ ++ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); ++ ++ /* poll for transfer start bit (should only take 1-20 polls) */ ++ do { ++ s = bcm2708_rd(bi, BSC_S); ++ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0); ++ ++ /* did we time out or some error occured? */ ++ if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) { ++ return -1; ++ } ++ ++ /* Send next read message before the write transfer finishes. */ ++ bi->nmsgs--; ++ bi->msg++; ++ bi->pos = 0; ++ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); ++ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ; ++ } ++ } ++ bcm2708_wr(bi, BSC_C, c); ++ ++ return 0; ++} ++ ++static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) ++{ ++ struct bcm2708_i2c *bi = dev_id; ++ bool handled = true; ++ u32 s; ++ int ret; ++ ++ spin_lock(&bi->lock); ++ ++ /* we may see camera interrupts on the "other" I2C channel ++ Just return if we've not sent anything */ ++ if (!bi->nmsgs || !bi->msg) { ++ goto early_exit; ++ } ++ ++ s = bcm2708_rd(bi, BSC_S); ++ ++ if (s & (BSC_S_CLKT | BSC_S_ERR)) { ++ bcm2708_bsc_reset(bi); ++ bi->error = true; ++ ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ } else if (s & BSC_S_DONE) { ++ bi->nmsgs--; ++ ++ if (bi->msg->flags & I2C_M_RD) { ++ bcm2708_bsc_fifo_drain(bi); ++ } ++ ++ bcm2708_bsc_reset(bi); ++ ++ if (bi->nmsgs) { ++ /* advance to next message */ ++ bi->msg++; ++ bi->pos = 0; ++ ret = bcm2708_bsc_setup(bi); ++ if (ret < 0) { ++ bcm2708_bsc_reset(bi); ++ bi->error = true; ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ goto early_exit; ++ } ++ } else { ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ } ++ } else if (s & BSC_S_TXW) { ++ bcm2708_bsc_fifo_fill(bi); ++ } else if (s & BSC_S_RXR) { ++ bcm2708_bsc_fifo_drain(bi); ++ } else { ++ handled = false; ++ } ++ ++early_exit: ++ spin_unlock(&bi->lock); ++ ++ return handled ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct bcm2708_i2c *bi = adap->algo_data; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&bi->lock, flags); ++ ++ reinit_completion(&bi->done); ++ bi->msg = msgs; ++ bi->pos = 0; ++ bi->nmsgs = num; ++ bi->error = false; ++ ++ ret = bcm2708_bsc_setup(bi); ++ ++ spin_unlock_irqrestore(&bi->lock, flags); ++ ++ /* check the result of the setup */ ++ if (ret < 0) ++ { ++ dev_err(&adap->dev, "transfer setup timed out\n"); ++ goto error_timeout; ++ } ++ ++ ret = wait_for_completion_timeout(&bi->done, msecs_to_jiffies(I2C_TIMEOUT_MS)); ++ if (ret == 0) { ++ dev_err(&adap->dev, "transfer timed out\n"); ++ goto error_timeout; ++ } ++ ++ ret = bi->error ? -EIO : num; ++ return ret; ++ ++error_timeout: ++ spin_lock_irqsave(&bi->lock, flags); ++ bcm2708_bsc_reset(bi); ++ bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */ ++ bi->nmsgs = 0; ++ spin_unlock_irqrestore(&bi->lock, flags); ++ return -ETIMEDOUT; ++} ++ ++static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL; ++} ++ ++static struct i2c_algorithm bcm2708_i2c_algorithm = { ++ .master_xfer = bcm2708_i2c_master_xfer, ++ .functionality = bcm2708_i2c_functionality, ++}; ++ ++static int bcm2708_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int irq, err = -ENOMEM; ++ struct clk *clk; ++ struct bcm2708_i2c *bi; ++ struct i2c_adapter *adap; ++ unsigned long bus_hz; ++ u32 cdiv; ++ ++ if (pdev->dev.of_node) { ++ u32 bus_clk_rate; ++ pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c"); ++ if (pdev->id < 0) { ++ dev_err(&pdev->dev, "alias is missing\n"); ++ return -EINVAL; ++ } ++ if (!of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &bus_clk_rate)) ++ baudrate = bus_clk_rate; ++ else ++ dev_warn(&pdev->dev, ++ "Could not read clock-frequency property\n"); ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_err(&pdev->dev, "could not get IO memory\n"); ++ return -ENXIO; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "could not get IRQ\n"); ++ return irq; ++ } ++ ++ clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk)); ++ return PTR_ERR(clk); ++ } ++ ++ err = clk_prepare_enable(clk); ++ if (err) { ++ dev_err(&pdev->dev, "could not enable clk: %d\n", err); ++ goto out_clk_put; ++ } ++ ++ if (!pdev->dev.of_node) ++ bcm2708_i2c_init_pinmode(pdev->id); ++ ++ bi = kzalloc(sizeof(*bi), GFP_KERNEL); ++ if (!bi) ++ goto out_clk_disable; ++ ++ platform_set_drvdata(pdev, bi); ++ ++ adap = &bi->adapter; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC; ++ adap->algo = &bcm2708_i2c_algorithm; ++ adap->algo_data = bi; ++ adap->dev.parent = &pdev->dev; ++ adap->nr = pdev->id; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ switch (pdev->id) { ++ case 0: ++ adap->class = I2C_CLASS_HWMON; ++ break; ++ case 1: ++ adap->class = I2C_CLASS_DDC; ++ break; ++ default: ++ dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n"); ++ err = -ENXIO; ++ goto out_free_bi; ++ } ++ ++ spin_lock_init(&bi->lock); ++ init_completion(&bi->done); ++ ++ bi->base = ioremap(regs->start, resource_size(regs)); ++ if (!bi->base) { ++ dev_err(&pdev->dev, "could not remap memory\n"); ++ goto out_free_bi; ++ } ++ ++ bi->irq = irq; ++ bi->clk = clk; ++ ++ err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED, ++ dev_name(&pdev->dev), bi); ++ if (err) { ++ dev_err(&pdev->dev, "could not request IRQ: %d\n", err); ++ goto out_iounmap; ++ } ++ ++ bcm2708_bsc_reset(bi); ++ ++ err = i2c_add_numbered_adapter(adap); ++ if (err < 0) { ++ dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); ++ goto out_free_irq; ++ } ++ ++ bus_hz = clk_get_rate(bi->clk); ++ cdiv = bus_hz / baudrate; ++ if (cdiv > 0xffff) { ++ cdiv = 0xffff; ++ baudrate = bus_hz / cdiv; ++ } ++ bi->cdiv = cdiv; ++ ++ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", ++ pdev->id, (unsigned long)regs->start, irq, baudrate); ++ ++ return 0; ++ ++out_free_irq: ++ free_irq(bi->irq, bi); ++out_iounmap: ++ iounmap(bi->base); ++out_free_bi: ++ kfree(bi); ++out_clk_disable: ++ clk_disable_unprepare(clk); ++out_clk_put: ++ clk_put(clk); ++ return err; ++} ++ ++static int bcm2708_i2c_remove(struct platform_device *pdev) ++{ ++ struct bcm2708_i2c *bi = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ i2c_del_adapter(&bi->adapter); ++ free_irq(bi->irq, bi); ++ iounmap(bi->base); ++ clk_disable_unprepare(bi->clk); ++ clk_put(bi->clk); ++ kfree(bi); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm2708_i2c_of_match[] = { ++ { .compatible = "brcm,bcm2708-i2c" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match); ++ ++static struct platform_driver bcm2708_i2c_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2708_i2c_of_match, ++ }, ++ .probe = bcm2708_i2c_probe, ++ .remove = bcm2708_i2c_remove, ++}; ++ ++// module_platform_driver(bcm2708_i2c_driver); ++ ++ ++static int __init bcm2708_i2c_init(void) ++{ ++ return platform_driver_register(&bcm2708_i2c_driver); ++} ++ ++static void __exit bcm2708_i2c_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_i2c_driver); ++} ++ ++module_init(bcm2708_i2c_init); ++module_exit(bcm2708_i2c_exit); ++ ++ ++ ++MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); ++MODULE_AUTHOR("Chris Boot "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); + +From 87711afd62feac0850e063b279057c91fe0aabbf Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 018/216] bcm2835: add v4l2 camera device +Subject: [PATCH 22/77] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -104582,7 +105677,7 @@ index 0000000..c585a8f + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index d9b872b..2da9264 100644 +index 421f531..34ad311 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -104595,7 +105690,7 @@ index d9b872b..2da9264 100644 config VIDEO_VIA_CAMERA diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 3ec1547..d8d5927 100644 +index 8f85561..7b15c24 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -2,6 +2,8 @@ @@ -104609,7 +105704,7 @@ index 3ec1547..d8d5927 100644 diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig new file mode 100644 -index 0000000..2cb1a68 +index 0000000..99a5cbc --- /dev/null +++ b/drivers/media/platform/bcm2835/Kconfig @@ -0,0 +1,25 @@ @@ -104617,7 +105712,7 @@ index 0000000..2cb1a68 + +config VIDEO_BCM2835 + bool "Broadcom BCM2835 camera interface driver" -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709) ++ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) + ---help--- + Say Y here to enable camera host interface devices for + Broadcom BCM2835 SoC. This operates over the VCHIQ interface @@ -111569,6942 +112664,10 @@ index 0000000..9d1d11e + +#endif /* MMAL_VCHIQ_H */ -From 47303896a0462c49e8bf3e5ef31e744d891a30a4 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 6 Jul 2014 12:07:25 +0200 -Subject: [PATCH 019/216] spi-bcm2708: Prepare for Common Clock Framework - migration - -As part of migrating to use the Common Clock Framework, replace clk_enable() -with clk_prepare_enable() and clk_disable() with clk_disable_unprepare(). -This does not affect behaviour under the current clock implementation. - -Also add a missing clk_disable_unprepare() in the probe error path. - -Signed-off-by: Noralf Tronnes ---- - drivers/spi/spi-bcm2708.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c -index b04a57d..349d21f 100644 ---- a/drivers/spi/spi-bcm2708.c -+++ b/drivers/spi/spi-bcm2708.c -@@ -545,7 +545,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - } - - /* initialise the hardware */ -- clk_enable(clk); -+ clk_prepare_enable(clk); - bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX); - - err = spi_register_master(master); -@@ -561,6 +561,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - - out_free_irq: - free_irq(bs->irq, master); -+ clk_disable_unprepare(bs->clk); - out_workqueue: - destroy_workqueue(bs->workq); - out_iounmap: -@@ -585,7 +586,7 @@ static int bcm2708_spi_remove(struct platform_device *pdev) - - flush_work(&bs->work); - -- clk_disable(bs->clk); -+ clk_disable_unprepare(bs->clk); - clk_put(bs->clk); - free_irq(bs->irq, master); - iounmap(bs->base); - -From d8d78e0bb5731d6fb3f1f813dc795e98be064870 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 6 Jul 2014 12:09:30 +0200 -Subject: [PATCH 020/216] BCM2708: Migrate to the Common Clock Framework - -As part of moving towards using Device Tree, the Common Clock Framework -has to be used instead of the BCM2708 clock implementation. - -Selecting COMMON_CLK removes the need to set CLKDEV_LOOKUP and HAVE_CLK explicitly. - -CONFIG_ARCH_BCM2708_CHIPIT #ifdef's are removed. They are no longer in use. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/Kconfig | 3 +- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 79 +++++++++++++++++------------------------ - arch/arm/mach-bcm2708/clock.c | 61 ------------------------------- - arch/arm/mach-bcm2708/clock.h | 24 ------------- - 5 files changed, 34 insertions(+), 135 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/clock.c - delete mode 100644 arch/arm/mach-bcm2708/clock.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 9fcd395..c495965 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -373,11 +373,10 @@ config ARCH_BCM2708 - bool "Broadcom BCM2708 family" - select CPU_V6 - select ARM_AMBA -- select HAVE_CLK - select HAVE_SCHED_CLOCK - select NEED_MACH_GPIO_H - select NEED_MACH_MEMORY_H -- select CLKDEV_LOOKUP -+ select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS - select ARM_ERRATA_411920 -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index a722f3f..21e3521 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o dma.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 752dd46..080e260 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -27,6 +27,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -57,7 +59,6 @@ - - #include "bcm2708.h" - #include "armctrl.h" --#include "clock.h" - - #ifdef CONFIG_BCM_VC_CMA - #include -@@ -78,7 +79,7 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned uart_clock; -+static unsigned uart_clock = UART0_CLOCK; - static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; -@@ -188,51 +189,39 @@ static void __init bcm2708_clocksource_init(void) - } - } - -+struct clk __init *bcm2708_clk_register(const char *name, unsigned long fixed_rate) -+{ -+ struct clk *clk; - --/* -- * These are fixed clocks. -- */ --static struct clk ref24_clk = { -- .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */ --}; -+ clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, -+ fixed_rate); -+ if (IS_ERR(clk)) -+ pr_err("%s not registered\n", name); - --static struct clk osc_clk = { --#ifdef CONFIG_ARCH_BCM2708_CHIPIT -- .rate = 27000000, --#else -- .rate = 500000000, /* ARM clock is set from the VideoCore booter */ --#endif --}; -+ return clk; -+} - --/* warning - the USB needs a clock > 34MHz */ -+void __init bcm2708_register_clkdev(struct clk *clk, const char *name) -+{ -+ int ret; - --static struct clk sdhost_clk = { --#ifdef CONFIG_ARCH_BCM2708_CHIPIT -- .rate = 4000000, /* 4MHz */ --#else -- .rate = 250000000, /* 250MHz */ --#endif --}; -+ ret = clk_register_clkdev(clk, NULL, name); -+ if (ret) -+ pr_err("%s alias not registered\n", name); -+} - --static struct clk_lookup lookups[] = { -- { /* UART0 */ -- .dev_id = "dev:f1", -- .clk = &ref24_clk, -- }, -- { /* USB */ -- .dev_id = "bcm2708_usb", -- .clk = &osc_clk, -- }, { /* SPI */ -- .dev_id = "bcm2708_spi.0", -- .clk = &sdhost_clk, -- }, { /* BSC0 */ -- .dev_id = "bcm2708_i2c.0", -- .clk = &sdhost_clk, -- }, { /* BSC1 */ -- .dev_id = "bcm2708_i2c.1", -- .clk = &sdhost_clk, -- } --}; -+void __init bcm2708_init_clocks(void) -+{ -+ struct clk *clk; -+ -+ clk = bcm2708_clk_register("uart0_clk", uart_clock); -+ bcm2708_register_clkdev(clk, "dev:f1"); -+ -+ clk = bcm2708_clk_register("sdhost_clk", 250000000); -+ bcm2708_register_clkdev(clk, "bcm2708_spi.0"); -+ bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); -+ bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); -+} - - #define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } - #define UART0_DMA { 15, 14 } -@@ -685,11 +674,7 @@ void __init bcm2708_init(void) - printk("bcm2708.uart_clock = %d\n", uart_clock); - pm_power_off = bcm2708_power_off; - -- if (uart_clock) -- lookups[0].clk->rate = uart_clock; -- -- for (i = 0; i < ARRAY_SIZE(lookups); i++) -- clkdev_add(&lookups[i]); -+ bcm2708_init_clocks(); - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_dmaengine_device); -diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c -deleted file mode 100644 -index 4fc556e..0000000 ---- a/arch/arm/mach-bcm2708/clock.c -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "clock.h" -- --int clk_enable(struct clk *clk) --{ -- return 0; --} --EXPORT_SYMBOL(clk_enable); -- --void clk_disable(struct clk *clk) --{ --} --EXPORT_SYMBOL(clk_disable); -- --unsigned long clk_get_rate(struct clk *clk) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_get_rate); -- --long clk_round_rate(struct clk *clk, unsigned long rate) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_round_rate); -- --int clk_set_rate(struct clk *clk, unsigned long rate) --{ -- return -EIO; --} --EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h -deleted file mode 100644 -index 5f9d725..0000000 ---- a/arch/arm/mach-bcm2708/clock.h -+++ /dev/null -@@ -1,24 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --struct module; -- --struct clk { -- unsigned long rate; --}; - -From 5f8aad35cdb010ca9fc0c58cca2a5a11fce879ec Mon Sep 17 00:00:00 2001 -From: notro -Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 021/216] BCM2708: Add core Device Tree support - -Add the bare minimum needed to boot BCM2708 from a Device Tree. - -Signed-off-by: Noralf Tronnes - -BCM2708: DT: change 'axi' nodename to 'soc' - -Change DT node named 'axi' to 'soc' so it matches ARCH_BCM2835. -The VC4 bootloader fills in certain properties in the 'axi' subtree, -but since this is part of an upstreaming effort, the name is changed. - -Signed-off-by: Noralf Tronnes notro@tronnes.org - -BCM2708_DT: Correct length of the peripheral space ---- - arch/arm/boot/dts/Makefile | 21 ++++ - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 81 +++++++++++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 81 +++++++++++++++ - arch/arm/boot/dts/bcm2708.dtsi | 86 ++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 165 +++++++++++++++++++++++++++++++ - arch/arm/mach-bcm2708/Kconfig | 8 ++ - arch/arm/mach-bcm2708/bcm2708.c | 45 ++++++++- - 7 files changed, 484 insertions(+), 3 deletions(-) - create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts - create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts - create mode 100644 arch/arm/boot/dts/bcm2708.dtsi - create mode 100644 arch/arm/boot/dts/bcm2709.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 992ea0b..25fbf52 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,5 +1,17 @@ - ifeq ($(CONFIG_OF),y) - -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb -+dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb -+ -+# Raspberry Pi -+ifeq ($(CONFIG_BCM2708_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_BCM2709_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC -@@ -645,7 +657,16 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt6592-evb.dtb \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb -+ -+targets += dtbs dtbs_install -+targets += $(dtb-y) -+ - endif - - always := $(dtb-y) - clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) -+ DTC_FLAGS ?= -@ -+endif -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -new file mode 100644 -index 0000000..983c23f ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,81 @@ -+/dts-v1/; -+ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "Raspberry Pi Model B+"; -+ -+ aliases { -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -new file mode 100644 -index 0000000..d8c6d15 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,81 @@ -+/dts-v1/; -+ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "Raspberry Pi Model B"; -+ -+ aliases { -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <28 29 30 31>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -new file mode 100644 -index 0000000..96b7311 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -0,0 +1,86 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "BCM2708"; -+ -+ interrupt-parent = <&intc>; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ -+ soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x7e000000 0x20000000 0x01000000>; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -new file mode 100644 -index 0000000..15c7e65 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -0,0 +1,165 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2709"; -+ model = "BCM2709"; -+ -+ interrupt-parent = <&intc>; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x7e000000 0x3f000000 0x01000000>; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupts = <3 9>; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ clock-frequency = <19200000>; -+ interrupts = <3 0>, // PHYS_SECURE_PPI -+ <3 1>, // PHYS_NONSECURE_PPI -+ <3 3>, // VIRT_PPI -+ <3 2>; // HYP_PPI -+ always-on; -+ }; -+ -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ v7_cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf00>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf01>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf02>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf03>; -+ clock-frequency = <800000000>; -+ }; -+ }; -+ -+ __overrides__ { -+ arm_freq = <&v7_cpu0>, "clock-frequency:0", -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index e151ed4..182e7ba 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -9,6 +9,14 @@ config MACH_BCM2708 - help - Include support for the Broadcom(R) BCM2708 platform. - -+config BCM2708_DT -+ bool "BCM2708 Device Tree support" -+ depends on MACH_BCM2708 -+ default n -+ select USE_OF -+ help -+ Enable Device Tree support for BCM2708 -+ - config BCM2708_GPIO - bool "BCM2708 gpio support" - depends on MACH_BCM2708 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 080e260..496cbcd 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -33,7 +33,9 @@ - #include - #include - #include -+#include - #include -+#include - - #include - #include -@@ -84,6 +86,8 @@ static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - -+static unsigned use_dt = 0; -+ - static void __init bcm2708_init_led(void); - - void __init bcm2708_init_irq(void) -@@ -599,6 +603,16 @@ int __init bcm_register_device(struct platform_device *pdev) - return ret; - } - -+/* -+ * Use these macros for platform and i2c devices that are present in the -+ * Device Tree. This way the devices are only added on non-DT systems. -+ */ -+#define bcm_register_device_dt(pdev) \ -+ if (!use_dt) bcm_register_device(pdev) -+ -+#define i2c_register_board_info_dt(busnum, info, n) \ -+ if (!use_dt) i2c_register_board_info(busnum, info, n) -+ - int calc_rsts(int partition) - { - return PM_PASSWORD | -@@ -664,6 +678,24 @@ static void bcm2708_power_off(void) - } - } - -+#ifdef CONFIG_OF -+static void __init bcm2708_dt_init(void) -+{ -+ int ret; -+ -+ of_clk_init(NULL); -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ /* Proceed as if CONFIG_OF was not defined */ -+ } else { -+ use_dt = 1; -+ } -+} -+#else -+static void __init bcm2708_dt_init(void) { } -+#endif /* CONFIG_OF */ -+ - void __init bcm2708_init(void) - { - int i; -@@ -675,6 +707,7 @@ void __init bcm2708_init(void) - pm_power_off = bcm2708_power_off; - - bcm2708_init_clocks(); -+ bcm2708_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_dmaengine_device); -@@ -842,9 +875,9 @@ static struct platform_device bcm2708_led_device = { - - static void __init bcm2708_init_led(void) - { -- bcm2708_leds[0].gpio = disk_led_gpio; -- bcm2708_leds[0].active_low = disk_led_active_low; -- platform_device_register(&bcm2708_led_device); -+ bcm2708_leds[0].gpio = disk_led_gpio; -+ bcm2708_leds[0].active_low = disk_led_active_low; -+ bcm_register_device_dt(&bcm2708_led_device); - } - #else - static inline void bcm2708_init_led(void) -@@ -869,6 +902,11 @@ static void __init board_reserve(void) - #endif - } - -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ - MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2708_map_io, -@@ -878,6 +916,7 @@ MACHINE_START(BCM2708, "BCM2708") - .init_early = bcm2708_init_early, - .reserve = board_reserve, - .restart = bcm2708_restart, -+ .dt_compat = bcm2708_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - -From 55bd100cb5e042a279b944a4ff3c0f00c51ed64c Mon Sep 17 00:00:00 2001 -From: Siarhei Siamashka -Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 022/216] fbdev: add FBIOCOPYAREA ioctl - -Based on the patch authored by Ali Gholami Rudi at - https://lkml.org/lkml/2009/7/13/153 - -Provide an ioctl for userspace applications, but only if this operation -is hardware accelerated (otherwide it does not make any sense). - -Signed-off-by: Siarhei Siamashka ---- - drivers/video/fbdev/core/fbmem.c | 30 ++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 5 +++++ - 2 files changed, 35 insertions(+) - -diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index 0705d88..771992a 100644 ---- a/drivers/video/fbdev/core/fbmem.c -+++ b/drivers/video/fbdev/core/fbmem.c -@@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) - } - EXPORT_SYMBOL(fb_blank); - -+static int fb_copyarea_user(struct fb_info *info, -+ struct fb_copyarea *copy) -+{ -+ int ret = 0; -+ if (!lock_fb_info(info)) -+ return -ENODEV; -+ if (copy->dx + copy->width > info->var.xres || -+ copy->sx + copy->width > info->var.xres || -+ copy->dy + copy->height > info->var.yres || -+ copy->sy + copy->height > info->var.yres) { -+ ret = -EINVAL; -+ goto out; -+ } -+ info->fbops->fb_copyarea(info, copy); -+out: -+ unlock_fb_info(info); -+ return ret; -+} -+ - static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) - { -@@ -1094,6 +1113,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - struct fb_cmap cmap_from; - struct fb_cmap_user cmap; - struct fb_event event; -+ struct fb_copyarea copy; - void __user *argp = (void __user *)arg; - long ret = 0; - -@@ -1211,6 +1231,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - unlock_fb_info(info); - console_unlock(); - break; -+ case FBIOCOPYAREA: -+ if (info->flags & FBINFO_HWACCEL_COPYAREA) { -+ /* only provide this ioctl if it is accelerated */ -+ if (copy_from_user(©, argp, sizeof(copy))) -+ return -EFAULT; -+ ret = fb_copyarea_user(info, ©); -+ break; -+ } -+ /* fall through */ - default: - if (!lock_fb_info(info)) - return -ENODEV; -@@ -1365,6 +1394,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, - case FBIOPAN_DISPLAY: - case FBIOGET_CON2FBMAP: - case FBIOPUT_CON2FBMAP: -+ case FBIOCOPYAREA: - arg = (unsigned long) compat_ptr(arg); - case FBIOBLANK: - ret = do_fb_ioctl(info, cmd, arg); -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fb795c3..fa72af0 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -34,6 +34,11 @@ - #define FBIOPUT_MODEINFO 0x4617 - #define FBIOGET_DISPINFO 0x4618 - #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) -+/* -+ * HACK: use 'z' in order not to clash with any other ioctl numbers which might -+ * be concurrently added to the mainline kernel -+ */ -+#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) - - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ - -From ee44a85f3a6b76509c3de7ee16164e8d32eecc24 Mon Sep 17 00:00:00 2001 -From: Harm Hanemaaijer -Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 025/216] 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 -console monochrome imageblit function used to draw console text is -suboptimal for common pixel depths such as 16bpp and 32bpp. The existing -code is quite general and can deal with several pixel depths. By creating -special case functions for 16bpp and 32bpp, by far the most common pixel -formats used on modern systems, a significant speed-up is attained -which can be readily felt on ARM-based devices like the Raspberry Pi -and the Allwinner platform, but should help any platform using the -fb layer. - -The special case functions allow constant folding, eliminating a number -of instructions including divide operations, and allow the use of an -unrolled loop, eliminating instructions with a variable shift size, -reducing source memory access instructions, and eliminating excessive -branching. These unrolled loops also allow much better code optimization -by the C compiler. The code that selects which optimized variant is used -is also simplified, eliminating integer divide instructions. - -The speed-up, measured by timing 'cat file.txt' in the console, varies -between 40% and 70%, when testing on the Raspberry Pi and Allwinner -ARM-based platforms, depending on font size and the pixel depth, with -the greater benefit for 32bpp. - -Signed-off-by: Harm Hanemaaijer ---- - drivers/video/fbdev/core/cfbimgblt.c | 152 +++++++++++++++++++++++++++++++++-- - 1 file changed, 147 insertions(+), 5 deletions(-) - -diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c -index a2bb276..436494f 100644 ---- a/drivers/video/fbdev/core/cfbimgblt.c -+++ b/drivers/video/fbdev/core/cfbimgblt.c -@@ -28,6 +28,11 @@ - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. -+ * Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013: -+ * - Provide optimized versions of fast_imageblit for 16 and 32bpp that are -+ * significantly faster than the previous implementation. -+ * - Simplify the fast/slow_imageblit selection code, avoiding integer -+ * divides. - */ - #include - #include -@@ -262,6 +267,133 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * - } - } - -+/* -+ * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded -+ * into the code, main loop unrolled. -+ */ -+ -+static inline void fast_imageblit16(const struct fb_image *image, -+ struct fb_info *p, u8 __iomem * dst1, -+ u32 fgcolor, u32 bgcolor) -+{ -+ u32 fgx = fgcolor, bgx = bgcolor; -+ u32 spitch = (image->width + 7) / 8; -+ u32 end_mask, eorx; -+ const char *s = image->data, *src; -+ u32 __iomem *dst; -+ const u32 *tab = NULL; -+ int i, j, k; -+ -+ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; -+ -+ fgx <<= 16; -+ bgx <<= 16; -+ fgx |= fgcolor; -+ bgx |= bgcolor; -+ -+ eorx = fgx ^ bgx; -+ k = image->width / 2; -+ -+ for (i = image->height; i--;) { -+ dst = (u32 __iomem *) dst1; -+ src = s; -+ -+ j = k; -+ while (j >= 4) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 6) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 4) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 2) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[bits & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ src++; -+ j -= 4; -+ } -+ if (j != 0) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 6) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ if (j >= 2) { -+ end_mask = tab[(bits >> 4) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ if (j == 3) { -+ end_mask = tab[(bits >> 2) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst); -+ } -+ } -+ } -+ dst1 += p->fix.line_length; -+ s += spitch; -+ } -+} -+ -+/* -+ * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded -+ * into the code, main loop unrolled. -+ */ -+ -+static inline void fast_imageblit32(const struct fb_image *image, -+ struct fb_info *p, u8 __iomem * dst1, -+ u32 fgcolor, u32 bgcolor) -+{ -+ u32 fgx = fgcolor, bgx = bgcolor; -+ u32 spitch = (image->width + 7) / 8; -+ u32 end_mask, eorx; -+ const char *s = image->data, *src; -+ u32 __iomem *dst; -+ const u32 *tab = NULL; -+ int i, j, k; -+ -+ tab = cfb_tab32; -+ -+ eorx = fgx ^ bgx; -+ k = image->width; -+ -+ for (i = image->height; i--;) { -+ dst = (u32 __iomem *) dst1; -+ src = s; -+ -+ j = k; -+ while (j >= 8) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 6) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 5) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 4) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 3) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 2) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 1) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[bits & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ src++; -+ j -= 8; -+ } -+ if (j != 0) { -+ u32 bits = (u32) * src; -+ while (j > 1) { -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ bits <<= 1; -+ j--; -+ } -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst); -+ } -+ dst1 += p->fix.line_length; -+ s += spitch; -+ } -+} -+ - void cfb_imageblit(struct fb_info *p, const struct fb_image *image) - { - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; -@@ -294,11 +426,21 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) - bgcolor = image->bg_color; - } - -- if (32 % bpp == 0 && !start_index && !pitch_index && -- ((width & (32/bpp-1)) == 0) && -- bpp >= 8 && bpp <= 32) -- fast_imageblit(image, p, dst1, fgcolor, bgcolor); -- else -+ if (!start_index && !pitch_index) { -+ if (bpp == 32) -+ fast_imageblit32(image, p, dst1, fgcolor, -+ bgcolor); -+ else if (bpp == 16 && (width & 1) == 0) -+ fast_imageblit16(image, p, dst1, fgcolor, -+ bgcolor); -+ else if (bpp == 8 && (width & 3) == 0) -+ fast_imageblit(image, p, dst1, fgcolor, -+ bgcolor); -+ else -+ slow_imageblit(image, p, dst1, fgcolor, -+ bgcolor, -+ start_index, pitch_index); -+ } else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - -From 12b6956e3ba31498771d282025fc4a44b6648559 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 026/216] Allow mac address to be set in smsc95xx - -Signed-off-by: popcornmix ---- - drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 56 insertions(+) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 26423ad..e29a323 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -59,6 +59,7 @@ - #define SUSPEND_SUSPEND3 (0x08) - #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ - SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) -+#define MAC_ADDR_LEN (6) - - struct smsc95xx_priv { - u32 mac_cr; -@@ -74,6 +75,10 @@ static bool turbo_mode = true; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - -+static char *macaddr = ":"; -+module_param(macaddr, charp, 0); -+MODULE_PARM_DESC(macaddr, "MAC address"); -+ - static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, - u32 *data, int in_pm) - { -@@ -763,8 +768,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); - } - -+/* Check the macaddr module parameter for a MAC address */ -+static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) -+{ -+ int i, j, got_num, num; -+ u8 mtbl[MAC_ADDR_LEN]; -+ -+ if (macaddr[0] == ':') -+ return 0; -+ -+ i = 0; -+ j = 0; -+ num = 0; -+ got_num = 0; -+ while (j < MAC_ADDR_LEN) { -+ if (macaddr[i] && macaddr[i] != ':') { -+ got_num++; -+ if ('0' <= macaddr[i] && macaddr[i] <= '9') -+ num = num * 16 + macaddr[i] - '0'; -+ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') -+ num = num * 16 + 10 + macaddr[i] - 'A'; -+ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') -+ num = num * 16 + 10 + macaddr[i] - 'a'; -+ else -+ break; -+ i++; -+ } else if (got_num == 2) { -+ mtbl[j++] = (u8) num; -+ num = 0; -+ got_num = 0; -+ i++; -+ } else { -+ break; -+ } -+ } -+ -+ if (j == MAC_ADDR_LEN) { -+ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " -+ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], -+ mtbl[3], mtbl[4], mtbl[5]); -+ for (i = 0; i < MAC_ADDR_LEN; i++) -+ dev_mac[i] = mtbl[i]; -+ return 1; -+ } else { -+ return 0; -+ } -+} -+ - static void smsc95xx_init_mac_address(struct usbnet *dev) - { -+ /* Check module parameters */ -+ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) -+ return; -+ - /* try reading mac address from EEPROM */ - if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { - -From 03ecfd1c727358b884730a06b05d072ef28ebffd Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 027/216] 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 -See: https://github.com/raspberrypi/linux/pull/457 - -Add bitbanging pullups, use them for w1-gpio - -Allows parasite power to work, uses module option pullup=1 - -bcm2708: Ensure 1-wire pullup is disabled by default, and expose as module parameter - -Signed-off-by: Alex J Lennon - -w1-gpio: Add gpiopin module parameter and correctly free up gpio pull-up pin, if set - -Signed-off-by: Alex J Lennon ---- - arch/arm/mach-bcm2708/bcm2708.c | 29 ++++++++++++++++++++++ - drivers/w1/masters/w1-gpio.c | 55 +++++++++++++++++++++++++++++++++++++---- - drivers/w1/w1.h | 6 +++++ - drivers/w1/w1_int.c | 14 +++++++++++ - drivers/w1/w1_io.c | 18 +++++++++++--- - 5 files changed, 114 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 496cbcd..5873f8b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -79,12 +80,19 @@ - */ - #define DMA_MASK_BITS_COMMON 32 - -+// use GPIO 4 for the one-wire GPIO pin, if enabled -+#define W1_GPIO 4 -+// ensure one-wire GPIO pullup is disabled by default -+#define W1_PULLUP -1 -+ - /* command line parameters */ - static unsigned boardrev, serial; - static unsigned uart_clock = UART0_CLOCK; - static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; -+static unsigned w1_gpio_pin = W1_GPIO; -+static unsigned w1_gpio_pullup = W1_PULLUP; - - static unsigned use_dt = 0; - -@@ -256,6 +264,20 @@ static struct platform_device bcm2708_dmaengine_device = { - .id = -1, - }; - -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+static struct w1_gpio_platform_data w1_gpio_pdata = { -+ .pin = W1_GPIO, -+ .ext_pullup_enable_pin = W1_PULLUP, -+ .is_open_drain = 0, -+}; -+ -+static struct platform_device w1_device = { -+ .name = "w1-gpio", -+ .id = -1, -+ .dev.platform_data = &w1_gpio_pdata, -+}; -+#endif -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -715,6 +737,11 @@ void __init bcm2708_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device(&bcm2708_gpio_device); - #endif -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+ w1_gpio_pdata.pin = w1_gpio_pin; -+ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -+ bcm_register_device_dt(&w1_device); -+#endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); -@@ -925,3 +952,5 @@ module_param(uart_clock, uint, 0644); - module_param(disk_led_gpio, uint, 0644); - module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); -+module_param(w1_gpio_pin, uint, 0644); -+module_param(w1_gpio_pullup, uint, 0644); -diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c -index b99a932..3ad15cc 100644 ---- a/drivers/w1/masters/w1-gpio.c -+++ b/drivers/w1/masters/w1-gpio.c -@@ -23,6 +23,15 @@ - #include "../w1.h" - #include "../w1_int.h" - -+static int w1_gpio_pullup = -1; -+static int w1_gpio_pullup_orig = -1; -+module_param_named(pullup, w1_gpio_pullup, int, 0); -+MODULE_PARM_DESC(pullup, "GPIO pin pullup number"); -+static int w1_gpio_pin = -1; -+static int w1_gpio_pin_orig = -1; -+module_param_named(gpiopin, w1_gpio_pin, int, 0); -+MODULE_PARM_DESC(gpiopin, "GPIO pin number"); -+ - static u8 w1_gpio_set_pullup(void *data, int delay) - { - struct w1_gpio_platform_data *pdata = data; -@@ -67,6 +76,16 @@ static u8 w1_gpio_read_bit(void *data) - return gpio_get_value(pdata->pin) ? 1 : 0; - } - -+static void w1_gpio_bitbang_pullup(void *data, u8 on) -+{ -+ struct w1_gpio_platform_data *pdata = data; -+ -+ if (on) -+ gpio_direction_output(pdata->pin, 1); -+ else -+ gpio_direction_input(pdata->pin); -+} -+ - #if defined(CONFIG_OF) - static struct of_device_id w1_gpio_dt_ids[] = { - { .compatible = "w1-gpio" }, -@@ -113,13 +132,15 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - static int w1_gpio_probe(struct platform_device *pdev) - { - struct w1_bus_master *master; -- struct w1_gpio_platform_data *pdata; -+ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; - int err; - -- if (of_have_populated_dt()) { -- err = w1_gpio_probe_dt(pdev); -- if (err < 0) -- return err; -+ if(pdata == NULL) { -+ if (of_have_populated_dt()) { -+ err = w1_gpio_probe_dt(pdev); -+ if (err < 0) -+ return err; -+ } - } - - pdata = dev_get_platdata(&pdev->dev); -@@ -136,6 +157,19 @@ static int w1_gpio_probe(struct platform_device *pdev) - return -ENOMEM; - } - -+ w1_gpio_pin_orig = pdata->pin; -+ w1_gpio_pullup_orig = pdata->ext_pullup_enable_pin; -+ -+ if(gpio_is_valid(w1_gpio_pin)) { -+ pdata->pin = w1_gpio_pin; -+ pdata->ext_pullup_enable_pin = -1; -+ } -+ if(gpio_is_valid(w1_gpio_pullup)) { -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup; -+ } -+ -+ dev_info(&pdev->dev, "gpio pin %d, gpio pullup pin %d\n", pdata->pin, pdata->ext_pullup_enable_pin); -+ - err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); - if (err) { - dev_err(&pdev->dev, "gpio_request (pin) failed\n"); -@@ -165,6 +199,14 @@ static int w1_gpio_probe(struct platform_device *pdev) - master->set_pullup = w1_gpio_set_pullup; - } - -+ if (gpio_is_valid(w1_gpio_pullup)) { -+ if (pdata->is_open_drain) -+ printk(KERN_ERR "w1-gpio 'pullup' option " -+ "doesn't work with open drain GPIO\n"); -+ else -+ master->bitbang_pullup = w1_gpio_bitbang_pullup; -+ } -+ - err = w1_add_master_device(master); - if (err) { - dev_err(&pdev->dev, "w1_add_master device failed\n"); -@@ -195,6 +237,9 @@ static int w1_gpio_remove(struct platform_device *pdev) - - w1_remove_master_device(master); - -+ pdata->pin = w1_gpio_pin_orig; -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_orig; -+ - return 0; - } - -diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 56a49ba..881d728 100644 ---- a/drivers/w1/w1.h -+++ b/drivers/w1/w1.h -@@ -171,6 +171,12 @@ struct w1_bus_master - - u8 (*set_pullup)(void *, int); - -+ /** -+ * Turns the pullup on/off in bitbanging mode, takes an on/off argument. -+ * @return -1=Error, 0=completed -+ */ -+ void (*bitbang_pullup) (void *, u8); -+ - void (*search)(void *, struct w1_master *, - u8, w1_slave_found_callback); - }; -diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c -index 47249a3..a4b4a8d 100644 ---- a/drivers/w1/w1_int.c -+++ b/drivers/w1/w1_int.c -@@ -123,6 +123,20 @@ int w1_add_master_device(struct w1_bus_master *master) - return(-EINVAL); - } - -+ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup -+ * and takes care of timing itself */ -+ if (!master->write_byte && !master->touch_bit && master->set_pullup) { -+ printk(KERN_ERR "w1_add_master_device: set_pullup requires " -+ "write_byte or touch_bit, disabling\n"); -+ master->set_pullup = NULL; -+ } -+ -+ if (master->set_pullup && master->bitbang_pullup) { -+ printk(KERN_ERR "w1_add_master_device: set_pullup should not " -+ "be set when bitbang_pullup is used, disabling\n"); -+ master->set_pullup = NULL; -+ } -+ - /* Lock until the device is added (or not) to w1_masters. */ - mutex_lock(&w1_mlock); - /* Search for the first available id (starting at 1). */ -diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c -index 2820924..fd0550f 100644 ---- a/drivers/w1/w1_io.c -+++ b/drivers/w1/w1_io.c -@@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) - static void w1_post_write(struct w1_master *dev) - { - if (dev->pullup_duration) { -- if (dev->enable_pullup && dev->bus_master->set_pullup) -- dev->bus_master->set_pullup(dev->bus_master->data, 0); -- else -+ if (dev->enable_pullup) { -+ if (dev->bus_master->set_pullup) { -+ dev->bus_master->set_pullup(dev-> -+ bus_master->data, -+ 0); -+ } else if (dev->bus_master->bitbang_pullup) { -+ dev->bus_master-> -+ bitbang_pullup(dev->bus_master->data, 1); -+ msleep(dev->pullup_duration); -+ dev->bus_master-> -+ bitbang_pullup(dev->bus_master->data, 0); -+ } -+ } else { - msleep(dev->pullup_duration); -+ } -+ - dev->pullup_duration = 0; - } - } - -From 4624b823abd044524b26cb4d7111564f141e540f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 029/216] config: Enable CONFIG_MEMCG, but leave it disabled - (due to memory cost). Enable with cgroup_enable=memory. - ---- - kernel/cgroup.c | 23 +++++++++++++++++++++++ - mm/memcontrol.c | 1 + - 2 files changed, 24 insertions(+) - -diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index 29a7b2c..54fd2f0 100644 ---- a/kernel/cgroup.c -+++ b/kernel/cgroup.c -@@ -5393,6 +5393,29 @@ static int __init cgroup_disable(char *str) - } - __setup("cgroup_disable=", cgroup_disable); - -+static int __init cgroup_enable(char *str) -+{ -+ struct cgroup_subsys *ss; -+ char *token; -+ int i; -+ -+ while ((token = strsep(&str, ",")) != NULL) { -+ if (!*token) -+ continue; -+ -+ for_each_subsys(ss, i) { -+ if (!strcmp(token, ss->name)) { -+ ss->disabled = 0; -+ printk(KERN_INFO "Enabling %s control group" -+ " subsystem\n", ss->name); -+ break; -+ } -+ } -+ } -+ return 1; -+} -+__setup("cgroup_enable=", cgroup_enable); -+ - static int __init cgroup_set_legacy_files_on_dfl(char *str) - { - printk("cgroup: using legacy files on the default hierarchy\n"); -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index b34ef4a..c2aa348 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -5391,6 +5391,7 @@ struct cgroup_subsys memory_cgrp_subsys = { - .dfl_cftypes = memory_files, - .legacy_cftypes = mem_cgroup_legacy_files, - .early_init = 0, -+ .disabled = 1, - }; - - /** - -From 14913d5804e6cc14027404667dbacd69267fd032 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:33:38 +0100 -Subject: [PATCH 030/216] ASoC: Add support for BCM2708 - -This driver adds support for digital audio (I2S) -for the BCM2708 SoC that is used by the -Raspberry Pi. External audio codecs can be -connected to the Raspberry Pi via P5 header. - -It relies on cyclic DMA engine support for BCM2708. - -Signed-off-by: Florian Meier - -ASoC: BCM2708: Add 24 bit support - -This adds 24 bit support to the I2S driver of the BCM2708. -Besides enabling the 24 bit flags, it includes two bug fixes: - -MMAP is not supported. Claiming this leads to strange issues -when the format of driver and file do not match. - -The datasheet states that the width extension bit should be set -for widths greater than 24, but greater or equal would be correct. -This follows from the definition of the width field. - -Signed-off-by: Florian Meier - -bcm2708-i2s: Update bclk_ratio to more correct values - -Move GPIO setup to hw_params. - -This is used to stop the I2S driver from breaking -the GPIO setup for other uses of the PCM interface - -Configure GPIOs for I2S based on revision/card settings - -With RPi model B+, assignment of the I2S GPIO pins has changed. -This patch uses the board revision to auto-detect the GPIOs used -for I2S. It also allows sound card drivers to set the GPIOs that -should be used. This is especially important with the Compute -Module. - -bcm2708-i2s: Avoid leak from iomap when accessing gpio - -bcm2708: Eliminate i2s debugfs directory error - -Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') -to avoid the name clash when registering debugfs entries. ---- - sound/soc/bcm/Kconfig | 11 + - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/bcm2708-i2s.c | 1009 +++++++++++++++++++++++++++++++++++++++++++ - sound/soc/bcm/bcm2708-i2s.h | 35 ++ - 4 files changed, 1059 insertions(+) - create mode 100644 sound/soc/bcm/bcm2708-i2s.c - create mode 100644 sound/soc/bcm/bcm2708-i2s.h - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 6a834e1..8642296 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -7,3 +7,14 @@ config SND_BCM2835_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2835 I2S interface. You will also need - to select the audio interfaces to support below. -+ -+config SND_BCM2708_SOC_I2S -+ tristate "SoC Audio support for the Broadcom BCM2708 I2S module" -+ depends on MACH_BCM2708 || MACH_BCM2709 -+ select REGMAP_MMIO -+ select SND_SOC_DMAENGINE_PCM -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ help -+ Say Y or M if you want to add support for codecs attached to -+ the BCM2708 I2S interface. You will also need -+ to select the audio interfaces to support below. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index bc816b7..f8bbe1f 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o - - obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - -+# BCM2708 Platform Support -+snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c -new file mode 100644 -index 0000000..a3b65dc ---- /dev/null -+++ b/sound/soc/bcm/bcm2708-i2s.c -@@ -0,0 +1,1009 @@ -+/* -+ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * Based on -+ * Raspberry Pi PCM I2S ALSA Driver -+ * Copyright (c) by Phil Poole 2013 -+ * -+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor -+ * Vladimir Barinov, -+ * Copyright (C) 2007 MontaVista Software, Inc., -+ * -+ * OMAP ALSA SoC DAI driver using McBSP port -+ * Copyright (C) 2008 Nokia Corporation -+ * Contact: Jarkko Nikula -+ * Peter Ujfalusi -+ * -+ * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver -+ * Author: Timur Tabi -+ * Copyright 2007-2010 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include "bcm2708-i2s.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* Clock registers */ -+#define BCM2708_CLK_PCMCTL_REG 0x00 -+#define BCM2708_CLK_PCMDIV_REG 0x04 -+ -+/* Clock register settings */ -+#define BCM2708_CLK_PASSWD (0x5a000000) -+#define BCM2708_CLK_PASSWD_MASK (0xff000000) -+#define BCM2708_CLK_MASH(v) ((v) << 9) -+#define BCM2708_CLK_FLIP BIT(8) -+#define BCM2708_CLK_BUSY BIT(7) -+#define BCM2708_CLK_KILL BIT(5) -+#define BCM2708_CLK_ENAB BIT(4) -+#define BCM2708_CLK_SRC(v) (v) -+ -+#define BCM2708_CLK_SHIFT (12) -+#define BCM2708_CLK_DIVI(v) ((v) << BCM2708_CLK_SHIFT) -+#define BCM2708_CLK_DIVF(v) (v) -+#define BCM2708_CLK_DIVF_MASK (0xFFF) -+ -+enum { -+ BCM2708_CLK_MASH_0 = 0, -+ BCM2708_CLK_MASH_1, -+ BCM2708_CLK_MASH_2, -+ BCM2708_CLK_MASH_3, -+}; -+ -+enum { -+ BCM2708_CLK_SRC_GND = 0, -+ BCM2708_CLK_SRC_OSC, -+ BCM2708_CLK_SRC_DBG0, -+ BCM2708_CLK_SRC_DBG1, -+ BCM2708_CLK_SRC_PLLA, -+ BCM2708_CLK_SRC_PLLC, -+ BCM2708_CLK_SRC_PLLD, -+ BCM2708_CLK_SRC_HDMI, -+}; -+ -+/* Most clocks are not useable (freq = 0) */ -+static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = { -+ [BCM2708_CLK_SRC_GND] = 0, -+ [BCM2708_CLK_SRC_OSC] = 19200000, -+ [BCM2708_CLK_SRC_DBG0] = 0, -+ [BCM2708_CLK_SRC_DBG1] = 0, -+ [BCM2708_CLK_SRC_PLLA] = 0, -+ [BCM2708_CLK_SRC_PLLC] = 0, -+ [BCM2708_CLK_SRC_PLLD] = 500000000, -+ [BCM2708_CLK_SRC_HDMI] = 0, -+}; -+ -+/* I2S registers */ -+#define BCM2708_I2S_CS_A_REG 0x00 -+#define BCM2708_I2S_FIFO_A_REG 0x04 -+#define BCM2708_I2S_MODE_A_REG 0x08 -+#define BCM2708_I2S_RXC_A_REG 0x0c -+#define BCM2708_I2S_TXC_A_REG 0x10 -+#define BCM2708_I2S_DREQ_A_REG 0x14 -+#define BCM2708_I2S_INTEN_A_REG 0x18 -+#define BCM2708_I2S_INTSTC_A_REG 0x1c -+#define BCM2708_I2S_GRAY_REG 0x20 -+ -+/* I2S register settings */ -+#define BCM2708_I2S_STBY BIT(25) -+#define BCM2708_I2S_SYNC BIT(24) -+#define BCM2708_I2S_RXSEX BIT(23) -+#define BCM2708_I2S_RXF BIT(22) -+#define BCM2708_I2S_TXE BIT(21) -+#define BCM2708_I2S_RXD BIT(20) -+#define BCM2708_I2S_TXD BIT(19) -+#define BCM2708_I2S_RXR BIT(18) -+#define BCM2708_I2S_TXW BIT(17) -+#define BCM2708_I2S_CS_RXERR BIT(16) -+#define BCM2708_I2S_CS_TXERR BIT(15) -+#define BCM2708_I2S_RXSYNC BIT(14) -+#define BCM2708_I2S_TXSYNC BIT(13) -+#define BCM2708_I2S_DMAEN BIT(9) -+#define BCM2708_I2S_RXTHR(v) ((v) << 7) -+#define BCM2708_I2S_TXTHR(v) ((v) << 5) -+#define BCM2708_I2S_RXCLR BIT(4) -+#define BCM2708_I2S_TXCLR BIT(3) -+#define BCM2708_I2S_TXON BIT(2) -+#define BCM2708_I2S_RXON BIT(1) -+#define BCM2708_I2S_EN (1) -+ -+#define BCM2708_I2S_CLKDIS BIT(28) -+#define BCM2708_I2S_PDMN BIT(27) -+#define BCM2708_I2S_PDME BIT(26) -+#define BCM2708_I2S_FRXP BIT(25) -+#define BCM2708_I2S_FTXP BIT(24) -+#define BCM2708_I2S_CLKM BIT(23) -+#define BCM2708_I2S_CLKI BIT(22) -+#define BCM2708_I2S_FSM BIT(21) -+#define BCM2708_I2S_FSI BIT(20) -+#define BCM2708_I2S_FLEN(v) ((v) << 10) -+#define BCM2708_I2S_FSLEN(v) (v) -+ -+#define BCM2708_I2S_CHWEX BIT(15) -+#define BCM2708_I2S_CHEN BIT(14) -+#define BCM2708_I2S_CHPOS(v) ((v) << 4) -+#define BCM2708_I2S_CHWID(v) (v) -+#define BCM2708_I2S_CH1(v) ((v) << 16) -+#define BCM2708_I2S_CH2(v) (v) -+ -+#define BCM2708_I2S_TX_PANIC(v) ((v) << 24) -+#define BCM2708_I2S_RX_PANIC(v) ((v) << 16) -+#define BCM2708_I2S_TX(v) ((v) << 8) -+#define BCM2708_I2S_RX(v) (v) -+ -+#define BCM2708_I2S_INT_RXERR BIT(3) -+#define BCM2708_I2S_INT_TXERR BIT(2) -+#define BCM2708_I2S_INT_RXR BIT(1) -+#define BCM2708_I2S_INT_TXW BIT(0) -+ -+/* I2S DMA interface */ -+#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004 -+#define BCM2708_DMA_DREQ_PCM_TX 2 -+#define BCM2708_DMA_DREQ_PCM_RX 3 -+ -+/* I2S pin configuration */ -+static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO; -+ -+/* General device struct */ -+struct bcm2708_i2s_dev { -+ struct device *dev; -+ struct snd_dmaengine_dai_dma_data dma_data[2]; -+ unsigned int fmt; -+ unsigned int bclk_ratio; -+ -+ struct regmap *i2s_regmap; -+ struct regmap *clk_regmap; -+}; -+ -+void bcm2708_i2s_set_gpio(int gpio) { -+ bcm2708_i2s_gpio=gpio; -+} -+EXPORT_SYMBOL(bcm2708_i2s_set_gpio); -+ -+ -+static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev) -+{ -+ /* Start the clock if in master mode */ -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ -+ switch (master) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ case SND_SOC_DAIFMT_CBS_CFM: -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void bcm2708_i2s_stop_clock(struct bcm2708_i2s_dev *dev) -+{ -+ uint32_t clkreg; -+ int timeout = 1000; -+ -+ /* Stop clock */ -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD); -+ -+ /* Wait for the BUSY flag going down */ -+ while (--timeout) { -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ if (!(clkreg & BCM2708_CLK_BUSY)) -+ break; -+ } -+ -+ if (!timeout) { -+ /* KILL the clock */ -+ dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD_MASK, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD); -+ } -+} -+ -+static void bcm2708_i2s_clear_fifos(struct bcm2708_i2s_dev *dev, -+ bool tx, bool rx) -+{ -+ int timeout = 1000; -+ uint32_t syncval; -+ uint32_t csreg; -+ uint32_t i2s_active_state; -+ uint32_t clkreg; -+ uint32_t clk_active_state; -+ uint32_t off; -+ uint32_t clr; -+ -+ off = tx ? BCM2708_I2S_TXON : 0; -+ off |= rx ? BCM2708_I2S_RXON : 0; -+ -+ clr = tx ? BCM2708_I2S_TXCLR : 0; -+ clr |= rx ? BCM2708_I2S_RXCLR : 0; -+ -+ /* Backup the current state */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ i2s_active_state = csreg & (BCM2708_I2S_RXON | BCM2708_I2S_TXON); -+ -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ clk_active_state = clkreg & BCM2708_CLK_ENAB; -+ -+ /* Start clock if not running */ -+ if (!clk_active_state) { -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ } -+ -+ /* Stop I2S module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, off, 0); -+ -+ /* -+ * Clear the FIFOs -+ * Requires at least 2 PCM clock cycles to take effect -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, clr, clr); -+ -+ /* Wait for 2 PCM clock cycles */ -+ -+ /* -+ * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back -+ * FIXME: This does not seem to work for slave mode! -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &syncval); -+ syncval &= BCM2708_I2S_SYNC; -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_SYNC, ~syncval); -+ -+ /* Wait for the SYNC flag changing it's state */ -+ while (--timeout) { -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ if ((csreg & BCM2708_I2S_SYNC) != syncval) -+ break; -+ } -+ -+ if (!timeout) -+ dev_err(dev->dev, "I2S SYNC error!\n"); -+ -+ /* Stop clock if it was not running before */ -+ if (!clk_active_state) -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Restore I2S state */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXON | BCM2708_I2S_TXON, i2s_active_state); -+} -+ -+static int bcm2708_i2s_set_dai_fmt(struct snd_soc_dai *dai, -+ unsigned int fmt) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->fmt = fmt; -+ return 0; -+} -+ -+static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, -+ unsigned int ratio) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->bclk_ratio = ratio; -+ return 0; -+} -+ -+ -+static int bcm2708_i2s_set_function(unsigned offset, int function) -+{ -+ #define GPIOFSEL(x) (0x00+(x)*4) -+ void __iomem *gpio = __io_address(GPIO_BASE); -+ unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2; -+ unsigned gpiodir; -+ unsigned gpio_bank = offset / 10; -+ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; -+ -+ if (offset >= BCM2708_NR_GPIOS) -+ return -EINVAL; -+ -+ gpiodir = readl(gpio + GPIOFSEL(gpio_bank)); -+ gpiodir &= ~(7 << gpio_field_offset); -+ gpiodir |= alt << gpio_field_offset; -+ writel(gpiodir, gpio + GPIOFSEL(gpio_bank)); -+ return 0; -+} -+ -+static void bcm2708_i2s_setup_gpio(void) -+{ -+ /* -+ * This is the common way to handle the GPIO pins for -+ * the Raspberry Pi. -+ * TODO Better way would be to handle -+ * this in the device tree! -+ */ -+ int pin,pinconfig,startpin,alt; -+ -+ /* SPI is on different GPIOs on different boards */ -+ /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */ -+ if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) { -+ if ((system_rev & 0xffffff) >= 0x10) { -+ /* Model B+ */ -+ pinconfig=BCM2708_I2S_GPIO_PIN18; -+ } else { -+ /* original */ -+ pinconfig=BCM2708_I2S_GPIO_PIN28; -+ } -+ } else { -+ pinconfig=bcm2708_i2s_gpio; -+ } -+ -+ if (pinconfig==BCM2708_I2S_GPIO_PIN18) { -+ startpin=18; -+ alt=BCM2708_I2S_GPIO_PIN18_ALT; -+ } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) { -+ startpin=28; -+ alt=BCM2708_I2S_GPIO_PIN28_ALT; -+ } else { -+ printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig); -+ return; -+ } -+ -+ /* configure I2S pins to correct ALT mode */ -+ for (pin = startpin; pin <= startpin+3; pin++) { -+ bcm2708_i2s_set_function(pin, alt); -+ } -+} -+ -+static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ unsigned int sampling_rate = params_rate(params); -+ unsigned int data_length, data_delay, bclk_ratio; -+ unsigned int ch1pos, ch2pos, mode, format; -+ unsigned int mash = BCM2708_CLK_MASH_1; -+ unsigned int divi, divf, target_frequency; -+ int clk_src = -1; -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBS_CFM); -+ -+ bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBM_CFS); -+ uint32_t csreg; -+ -+ /* -+ * If a stream is already enabled, -+ * the registers are already set properly. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ -+ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON)) -+ return 0; -+ -+ -+ bcm2708_i2s_setup_gpio(); -+ -+ /* -+ * Adjust the data length according to the format. -+ * We prefill the half frame length with an integer -+ * divider of 2400 as explained at the clock settings. -+ * Maybe it is overwritten there, if the Integer mode -+ * does not apply. -+ */ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ data_length = 16; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ data_length = 24; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ data_length = 32; -+ bclk_ratio = 100; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* If bclk_ratio already set, use that one. */ -+ if (dev->bclk_ratio) -+ bclk_ratio = dev->bclk_ratio; -+ -+ /* -+ * Clock Settings -+ * -+ * The target frequency of the bit clock is -+ * sampling rate * frame length -+ * -+ * Integer mode: -+ * Sampling rates that are multiples of 8000 kHz -+ * can be driven by the oscillator of 19.2 MHz -+ * with an integer divider as long as the frame length -+ * is an integer divider of 19200000/8000=2400 as set up above. -+ * This is no longer possible if the sampling rate -+ * is too high (e.g. 192 kHz), because the oscillator is too slow. -+ * -+ * MASH mode: -+ * For all other sampling rates, it is not possible to -+ * have an integer divider. Approximate the clock -+ * with the MASH module that induces a slight frequency -+ * variance. To minimize that it is best to have the fastest -+ * clock here. That is PLLD with 500 MHz. -+ */ -+ target_frequency = sampling_rate * bclk_ratio; -+ clk_src = BCM2708_CLK_SRC_OSC; -+ mash = BCM2708_CLK_MASH_0; -+ -+ if (bcm2708_clk_freq[clk_src] % target_frequency == 0 -+ && bit_master && frame_master) { -+ divi = bcm2708_clk_freq[clk_src] / target_frequency; -+ divf = 0; -+ } else { -+ uint64_t dividend; -+ -+ if (!dev->bclk_ratio) { -+ /* -+ * Overwrite bclk_ratio, because the -+ * above trick is not needed or can -+ * not be used. -+ */ -+ bclk_ratio = 2 * data_length; -+ } -+ -+ target_frequency = sampling_rate * bclk_ratio; -+ -+ clk_src = BCM2708_CLK_SRC_PLLD; -+ mash = BCM2708_CLK_MASH_1; -+ -+ dividend = bcm2708_clk_freq[clk_src]; -+ dividend <<= BCM2708_CLK_SHIFT; -+ do_div(dividend, target_frequency); -+ divi = dividend >> BCM2708_CLK_SHIFT; -+ divf = dividend & BCM2708_CLK_DIVF_MASK; -+ } -+ -+ /* Clock should only be set up here if CPU is clock master */ -+ if (((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS) || -+ ((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFM)) { -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMDIV_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_DIVI(divi) -+ | BCM2708_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_MASH(mash) -+ | BCM2708_CLK_SRC(clk_src)); -+ } -+ -+ /* Setup the frame format */ -+ format = BCM2708_I2S_CHEN; -+ -+ if (data_length >= 24) -+ format |= BCM2708_I2S_CHWEX; -+ -+ format |= BCM2708_I2S_CHWID((data_length-8)&0xf); -+ -+ switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ data_delay = 1; -+ break; -+ default: -+ /* -+ * TODO -+ * Others are possible but are not implemented at the moment. -+ */ -+ dev_err(dev->dev, "%s:bad format\n", __func__); -+ return -EINVAL; -+ } -+ -+ ch1pos = data_delay; -+ ch2pos = bclk_ratio / 2 + data_delay; -+ -+ switch (params_channels(params)) { -+ case 2: -+ format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format); -+ format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos)); -+ format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * Set format for both streams. -+ * We cannot set another frame length -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_RXC_A_REG, format); -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_TXC_A_REG, format); -+ -+ /* Setup the I2S mode */ -+ mode = 0; -+ -+ if (data_length <= 16) { -+ /* -+ * Use frame packed mode (2 channels per 32 bit word) -+ * We cannot set another frame length in the second stream -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ mode |= BCM2708_I2S_FTXP | BCM2708_I2S_FRXP; -+ } -+ -+ mode |= BCM2708_I2S_FLEN(bclk_ratio - 1); -+ mode |= BCM2708_I2S_FSLEN(bclk_ratio / 2); -+ -+ /* Master or slave? */ -+ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* CPU is master */ -+ break; -+ case SND_SOC_DAIFMT_CBM_CFS: -+ /* -+ * CODEC is bit clock master -+ * CPU is frame master -+ */ -+ mode |= BCM2708_I2S_CLKM; -+ break; -+ case SND_SOC_DAIFMT_CBS_CFM: -+ /* -+ * CODEC is frame master -+ * CPU is bit clock master -+ */ -+ mode |= BCM2708_I2S_FSM; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ /* CODEC is master */ -+ mode |= BCM2708_I2S_CLKM; -+ mode |= BCM2708_I2S_FSM; -+ break; -+ default: -+ dev_err(dev->dev, "%s:bad master\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* -+ * Invert clocks? -+ * -+ * The BCM approach seems to be inverted to the classical I2S approach. -+ */ -+ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ /* None. Therefore, both for BCM */ -+ mode |= BCM2708_I2S_CLKI; -+ mode |= BCM2708_I2S_FSI; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ /* Both. Therefore, none for BCM */ -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ /* -+ * Invert only frame sync. Therefore, -+ * invert only bit clock for BCM -+ */ -+ mode |= BCM2708_I2S_CLKI; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ /* -+ * Invert only bit clock. Therefore, -+ * invert only frame sync for BCM -+ */ -+ mode |= BCM2708_I2S_FSI; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_MODE_A_REG, mode); -+ -+ /* Setup the DMA parameters */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXTHR(1) -+ | BCM2708_I2S_TXTHR(1) -+ | BCM2708_I2S_DMAEN, 0xffffffff); -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_DREQ_A_REG, -+ BCM2708_I2S_TX_PANIC(0x10) -+ | BCM2708_I2S_RX_PANIC(0x30) -+ | BCM2708_I2S_TX(0x30) -+ | BCM2708_I2S_RX(0x20), 0xffffffff); -+ -+ /* Clear FIFOs */ -+ bcm2708_i2s_clear_fifos(dev, true, true); -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_prepare(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t cs_reg; -+ -+ bcm2708_i2s_start_clock(dev); -+ -+ /* -+ * Clear both FIFOs if the one that should be started -+ * is not empty at the moment. This should only happen -+ * after overrun. Otherwise, hw_params would have cleared -+ * the FIFO. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &cs_reg); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK -+ && !(cs_reg & BCM2708_I2S_TXE)) -+ bcm2708_i2s_clear_fifos(dev, true, false); -+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE -+ && (cs_reg & BCM2708_I2S_RXD)) -+ bcm2708_i2s_clear_fifos(dev, false, true); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_stop(struct bcm2708_i2s_dev *dev, -+ struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ uint32_t mask; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, 0); -+ -+ /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ -+ if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static int bcm2708_i2s_trigger(struct snd_pcm_substream *substream, int cmd, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t mask; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ bcm2708_i2s_start_clock(dev); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, mask); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ bcm2708_i2s_stop(dev, substream, dai); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ if (dai->active) -+ return 0; -+ -+ /* Should this still be running stop it */ -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Enable PCM block */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, BCM2708_I2S_EN); -+ -+ /* -+ * Disable STBY. -+ * Requires at least 4 PCM clock cycles to take effect. -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_STBY, BCM2708_I2S_STBY); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ bcm2708_i2s_stop(dev, substream, dai); -+ -+ /* If both streams are stopped, disable module and clock */ -+ if (dai->active) -+ return; -+ -+ /* Disable the module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, 0); -+ -+ /* -+ * Stopping clock is necessary, because stop does -+ * not stop the clock when SND_SOC_DAIFMT_CONT -+ */ -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static const struct snd_soc_dai_ops bcm2708_i2s_dai_ops = { -+ .startup = bcm2708_i2s_startup, -+ .shutdown = bcm2708_i2s_shutdown, -+ .prepare = bcm2708_i2s_prepare, -+ .trigger = bcm2708_i2s_trigger, -+ .hw_params = bcm2708_i2s_hw_params, -+ .set_fmt = bcm2708_i2s_set_dai_fmt, -+ .set_bclk_ratio = bcm2708_i2s_set_dai_bclk_ratio -+}; -+ -+static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; -+ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ return 0; -+} -+ -+static struct snd_soc_dai_driver bcm2708_i2s_dai = { -+ .name = "bcm2708-i2s", -+ .probe = bcm2708_i2s_dai_probe, -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .capture = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .ops = &bcm2708_i2s_dai_ops, -+ .symmetric_rates = 1 -+}; -+ -+static bool bcm2708_i2s_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_CS_A_REG: -+ case BCM2708_I2S_FIFO_A_REG: -+ case BCM2708_I2S_INTSTC_A_REG: -+ case BCM2708_I2S_GRAY_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_i2s_precious_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_FIFO_A_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_clk_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_CLK_PCMCTL_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config bcm2708_regmap_config[] = { -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_I2S_GRAY_REG, -+ .precious_reg = bcm2708_i2s_precious_reg, -+ .volatile_reg = bcm2708_i2s_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ .name = "i2s", -+ }, -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_CLK_PCMDIV_REG, -+ .volatile_reg = bcm2708_clk_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ .name = "clk", -+ }, -+}; -+ -+static const struct snd_soc_component_driver bcm2708_i2s_component = { -+ .name = "bcm2708-i2s-comp", -+}; -+ -+static const struct snd_pcm_hardware bcm2708_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_JOINT_DUPLEX, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE, -+ .period_bytes_min = 32, -+ .period_bytes_max = 64 * PAGE_SIZE, -+ .periods_min = 2, -+ .periods_max = 255, -+ .buffer_bytes_max = 128 * PAGE_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &bcm2708_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ -+ -+static int bcm2708_i2s_probe(struct platform_device *pdev) -+{ -+ struct bcm2708_i2s_dev *dev; -+ int i; -+ int ret; -+ struct regmap *regmap[2]; -+ struct resource *mem[2]; -+ -+ /* Request both ioareas */ -+ for (i = 0; i <= 1; i++) { -+ void __iomem *base; -+ -+ mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); -+ base = devm_ioremap_resource(&pdev->dev, mem[i]); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, -+ &bcm2708_regmap_config[i]); -+ if (IS_ERR(regmap[i])) { -+ dev_err(&pdev->dev, "I2S probe: regmap init failed\n"); -+ return PTR_ERR(regmap[i]); -+ } -+ } -+ -+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), -+ GFP_KERNEL); -+ if (IS_ERR(dev)) -+ return PTR_ERR(dev); -+ -+ dev->i2s_regmap = regmap[0]; -+ dev->clk_regmap = regmap[1]; -+ -+ /* Set the DMA address */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ /* Set the DREQ */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id = -+ BCM2708_DMA_DREQ_PCM_TX; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id = -+ BCM2708_DMA_DREQ_PCM_RX; -+ -+ /* Set the bus width */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ -+ /* Set burst */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; -+ -+ /* BCLK ratio - use default */ -+ dev->bclk_ratio = 0; -+ -+ /* Store the pdev */ -+ dev->dev = &pdev->dev; -+ dev_set_drvdata(&pdev->dev, dev); -+ -+ ret = snd_soc_register_component(&pdev->dev, -+ &bcm2708_i2s_component, &bcm2708_i2s_dai, 1); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); -+ ret = -ENOMEM; -+ return ret; -+ } -+ -+ ret = snd_dmaengine_pcm_register(&pdev->dev, -+ &bcm2708_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); -+ snd_soc_unregister_component(&pdev->dev); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_remove(struct platform_device *pdev) -+{ -+ snd_dmaengine_pcm_unregister(&pdev->dev); -+ snd_soc_unregister_component(&pdev->dev); -+ return 0; -+} -+ -+static const struct of_device_id bcm2708_i2s_of_match[] = { -+ { .compatible = "brcm,bcm2708-i2s", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_i2s_of_match); -+ -+static struct platform_driver bcm2708_i2s_driver = { -+ .probe = bcm2708_i2s_probe, -+ .remove = bcm2708_i2s_remove, -+ .driver = { -+ .name = "bcm2708-i2s", -+ .owner = THIS_MODULE, -+ .of_match_table = bcm2708_i2s_of_match, -+ }, -+}; -+ -+module_platform_driver(bcm2708_i2s_driver); -+ -+MODULE_ALIAS("platform:bcm2708-i2s"); -+MODULE_DESCRIPTION("BCM2708 I2S interface"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/bcm/bcm2708-i2s.h b/sound/soc/bcm/bcm2708-i2s.h -new file mode 100644 -index 0000000..6fdcbc1 ---- /dev/null -+++ b/sound/soc/bcm/bcm2708-i2s.h -@@ -0,0 +1,35 @@ -+/* -+ * I2S configuration for sound cards. -+ * -+ * Copyright (c) 2014 Daniel Matuschek -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef BCM2708_I2S_H -+#define BCM2708_I2S_H -+ -+/* I2S pin assignment */ -+#define BCM2708_I2S_GPIO_AUTO 0 -+#define BCM2708_I2S_GPIO_PIN18 1 -+#define BCM2708_I2S_GPIO_PIN28 2 -+ -+/* Alt mode to enable I2S */ -+#define BCM2708_I2S_GPIO_PIN18_ALT 0 -+#define BCM2708_I2S_GPIO_PIN28_ALT 2 -+ -+extern void bcm2708_i2s_set_gpio(int gpio); -+ -+#endif - -From 95f9b87c32e716eb0276c9d6d1228db5a9e38a0e Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 031/216] ASoC: Add support for PCM5102A codec - -Some definitions to support the PCM5102A codec -by Texas Instruments. - -Signed-off-by: Florian Meier ---- - sound/soc/codecs/Kconfig | 4 +++ - sound/soc/codecs/Makefile | 2 ++ - sound/soc/codecs/pcm5102a.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 69 insertions(+) - create mode 100644 sound/soc/codecs/pcm5102a.c - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index ea9f0e3..bc39bbc 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -82,6 +82,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM512x_I2C if I2C - select SND_SOC_PCM512x_SPI if SPI_MASTER - select SND_SOC_RT286 if I2C -+ select SND_SOC_PCM5102A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -506,6 +507,9 @@ config SND_SOC_RT286 - tristate - depends on I2C - -+config SND_SOC_PCM5102A -+ tristate -+ - config SND_SOC_RT5631 - tristate "Realtek ALC5631/RT5631 CODEC" - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 69b8666..905ef6f 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -77,6 +77,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rt286-objs := rt286.o -+snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-rt5645-objs := rt5645.o -@@ -259,6 +260,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o -+obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o - obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -new file mode 100644 -index 0000000..126f1e9 ---- /dev/null -+++ b/sound/soc/codecs/pcm5102a.c -@@ -0,0 +1,63 @@ -+/* -+ * Driver for the PCM5102A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm5102a_dai = { -+ .name = "pcm5102a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; -+ -+static int pcm5102a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, -+ &pcm5102a_dai, 1); -+} -+ -+static int pcm5102a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm5102a_codec_driver = { -+ .probe = pcm5102a_probe, -+ .remove = pcm5102a_remove, -+ .driver = { -+ .name = "pcm5102a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm5102a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From b8442f0526d6de697deec639e36023a92a2d178a Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:04:54 +0100 -Subject: [PATCH 032/216] BCM2708: Add I2S support to board file - -Adds the required initializations for I2S -to the board file of mach-bcm2708. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5873f8b..7f4ebf4 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -613,6 +613,28 @@ static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; - -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+static struct resource bcm2708_i2s_resources[] = { -+ { -+ .start = I2S_BASE, -+ .end = I2S_BASE + 0x20, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = PCM_CLOCK_BASE, -+ .end = PCM_CLOCK_BASE + 0x02, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_i2s_device = { -+ .name = "bcm2708-i2s", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), -+ .resource = bcm2708_i2s_resources, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -762,6 +784,10 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); - -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+ bcm_register_device_dt(&bcm2708_i2s_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - -From 40cf34f896f3ac88ad775464619175b5167ddacb Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 033/216] ASoC: Add support for HifiBerry DAC - -This adds a machine driver for the HifiBerry DAC. -It is a sound card that can -be stacked onto the Raspberry Pi. - -Signed-off-by: Florian Meier ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 5 +++ - sound/soc/bcm/hifiberry_dac.c | 100 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 112 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8642296..a92adb2 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -18,3 +18,10 @@ config SND_BCM2708_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2708 I2S interface. You will also need - to select the audio interfaces to support below. -+ -+config SND_BCM2708_SOC_HIFIBERRY_DAC -+ tristate "Support for HifiBerry DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM5102A -+ help -+ Say Y or M if you want to add support for HifiBerry DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index f8bbe1f..be90a49cb 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,3 +7,8 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o - - obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -+ -+# BCM2708 Machine Support -+snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -new file mode 100644 -index 0000000..4b70b45 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,100 @@ -+/* -+ * ASoC Driver for HifiBerry DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dac_ops = { -+ .hw_params = snd_rpi_hifiberry_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { -+{ -+ .name = "HifiBerry DAC", -+ .stream_name = "HifiBerry DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm5102a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm5102a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dac_ops, -+ .init = snd_rpi_hifiberry_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dac = { -+ .name = "snd_rpi_hifiberry_dac", -+ .dai_link = snd_rpi_hifiberry_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), -+}; -+ -+static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_dac_driver = { -+ .driver = { -+ .name = "snd-hifiberry-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_dac_probe, -+ .remove = snd_rpi_hifiberry_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); -+MODULE_LICENSE("GPL v2"); - -From c2ef063e2adb0e41654dc580ae959a86cde6f6f5 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:21:34 +0100 -Subject: [PATCH 034/216] BCM2708: Add HifiBerry DAC to board file - -This adds the initalization of the HifiBerry DAC -to the mach-bcm2708 board file. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7f4ebf4..94ce8fc 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -635,6 +635,20 @@ static struct platform_device bcm2708_i2s_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+static struct platform_device snd_hifiberry_dac_device = { -+ .name = "snd-hifiberry-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm5102a_codec_device = { -+ .name = "pcm5102a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -788,6 +802,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2708_i2s_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_dac_device); -+ bcm_register_device_dt(&snd_pcm5102a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - -From 1de129c2113a6fb145e654260b683e6c7e30bb51 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 6 Dec 2013 20:50:28 +0100 -Subject: [PATCH 035/216] ASoC: BCM2708: Add support for RPi-DAC - -This adds a machine driver for the RPi-DAC. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-dac.c | 97 +++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/Kconfig | 4 ++ - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm1794a.c | 62 ++++++++++++++++++++++++++ - 7 files changed, 193 insertions(+) - create mode 100644 sound/soc/bcm/rpi-dac.c - create mode 100644 sound/soc/codecs/pcm1794a.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 94ce8fc..fb955755 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,20 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+static struct platform_device snd_rpi_dac_device = { -+ .name = "snd-rpi-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm1794a_codec_device = { -+ .name = "pcm1794a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -807,6 +821,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_dac_device); -+ bcm_register_device_dt(&snd_pcm1794a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index a92adb2..64c61ac 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -25,3 +25,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - select SND_SOC_PCM5102A - help - Say Y or M if you want to add support for HifiBerry DAC. -+ -+config SND_BCM2708_SOC_RPI_DAC -+ tristate "Support for RPi-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM1794A -+ help -+ Say Y or M if you want to add support for RPi-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index be90a49cb..ccc9809 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,5 +10,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-rpi-dac-objs := rpi-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c -new file mode 100644 -index 0000000..6d6e0ba ---- /dev/null -+++ b/sound/soc/bcm/rpi-dac.c -@@ -0,0 +1,97 @@ -+/* -+ * ASoC Driver for RPi-DAC. -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_rpi_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_rpi_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_rpi_dac_ops = { -+ .hw_params = snd_rpi_rpi_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = { -+{ -+ .name = "RPi-DAC", -+ .stream_name = "RPi-DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm1794a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm1794a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_rpi_dac_ops, -+ .init = snd_rpi_rpi_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_rpi_dac = { -+ .name = "snd_rpi_rpi_dac", -+ .dai_link = snd_rpi_rpi_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_rpi_dac_dai), -+}; -+ -+static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_rpi_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_rpi_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_rpi_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_rpi_dac); -+} -+ -+static struct platform_driver snd_rpi_rpi_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_rpi_dac_probe, -+ .remove = snd_rpi_rpi_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_rpi_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index bc39bbc..8682bcf 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -83,6 +83,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM512x_SPI if SPI_MASTER - select SND_SOC_RT286 if I2C - select SND_SOC_PCM5102A if I2C -+ select SND_SOC_PCM1794A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -507,6 +508,9 @@ config SND_SOC_RT286 - tristate - depends on I2C - -+config SND_SOC_PCM1794A -+ tristate -+ - config SND_SOC_PCM5102A - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 905ef6f..c9bceba 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -77,6 +77,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rt286-objs := rt286.o -+snd-soc-pcm1794a-objs := pcm1794a.o - snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o -@@ -260,6 +261,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o -+obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o - obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o -diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c -new file mode 100644 -index 0000000..b4eaa44 ---- /dev/null -+++ b/sound/soc/codecs/pcm1794a.c -@@ -0,0 +1,62 @@ -+/* -+ * Driver for the PCM1794A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm1794a_dai = { -+ .name = "pcm1794a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm1794a; -+ -+static int pcm1794a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm1794a, -+ &pcm1794a_dai, 1); -+} -+ -+static int pcm1794a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm1794a_codec_driver = { -+ .probe = pcm1794a_probe, -+ .remove = pcm1794a_remove, -+ .driver = { -+ .name = "pcm1794a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm1794a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 11dea4325311685b8d38b791b519e74a561476ca Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 036/216] 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 - additional mclk_div divider, it is now possible to control the behaviour. - This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It - should allow lower jitter and better signal quality. The behavior has to be - controlled by the sound card driver, because some sample frequency share the - same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only - difference is the MCLK divider. - -This also added support for 32bit data. - -Signed-off-by: Daniel Matuschek ---- - sound/soc/codecs/wm8804.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index b2b0e68..ba2a0f8 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -278,6 +278,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, - blen = 0x1; - break; - case 24: -+ case 32: - blen = 0x2; - break; - default: -@@ -621,7 +622,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { - }; - - #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ -- SNDRV_PCM_FMTBIT_S24_LE) -+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) - - #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ - -From 84aed3cc8e8d60407b60cd132fe7a673024fb1a4 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 037/216] ASoC: BCM:Add support for HiFiBerry Digi. Driver is - based on the patched WM8804 driver. - -Signed-off-by: Daniel Matuschek ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 153 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 162 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_digi.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 64c61ac..d4a00fc 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - help - Say Y or M if you want to add support for HifiBerry DAC. - -+config SND_BCM2708_SOC_HIFIBERRY_DIGI -+ tristate "Support for HifiBerry Digi" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index ccc9809..826df7d 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,7 +10,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -new file mode 100644 -index 0000000..446ecdd ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,153 @@ -+/* -+ * ASoC Driver for HifiBerry Digi -+ * -+ * Author: Daniel Matuschek -+ * based on the HifiBerry DAC driver by Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8804.h" -+ -+static int samplerate=44100; -+ -+static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ int sysclk = 27000000; /* This is fixed on this board */ -+ -+ long mclk_freq=0; -+ int mclk_div=1; -+ -+ int ret; -+ -+ samplerate = params_rate(params); -+ -+ switch (samplerate) { -+ case 44100: -+ case 48000: -+ case 88200: -+ case 96000: -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ break; -+ case 176400: -+ case 192000: -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate\n"); -+ } -+ -+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); -+ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, -+ sysclk, SND_SOC_CLOCK_OUT); -+ if (ret < 0) { -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ -+ /* Enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ /* Power on */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { -+ .hw_params = snd_rpi_hifiberry_digi_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { -+{ -+ .name = "HifiBerry Digi", -+ .stream_name = "HifiBerry Digi HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8804-spdif", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_rpi_hifiberry_digi_ops, -+ .init = snd_rpi_hifiberry_digi_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_digi = { -+ .name = "snd_rpi_hifiberry_digi", -+ .dai_link = snd_rpi_hifiberry_digi_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), -+}; -+ -+static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_digi.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_digi_driver = { -+ .driver = { -+ .name = "snd-hifiberry-digi", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_digi_probe, -+ .remove = snd_rpi_hifiberry_digi_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_digi_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); -+MODULE_LICENSE("GPL v2"); - -From 4d5dd3c3d6019cf233add726cbe3aac6e543c540 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Thu, 16 Jan 2014 07:26:08 +0100 -Subject: [PATCH 038/216] BCM2708: Added support for HiFiBerry Digi board Board - initalization by I2C - -Signed-off-by: Daniel Matuschek ---- - arch/arm/mach-bcm2708/bcm2708.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index fb955755..0ad5343 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,21 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+static struct platform_device snd_hifiberry_digi_device = { -+ .name = "snd-hifiberry-digi", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("wm8804", 0x3b) -+ }, -+}; -+ -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - static struct platform_device snd_rpi_dac_device = { - .name = "snd-rpi-dac", -@@ -821,6 +836,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_digi_device); -+ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - bcm_register_device_dt(&snd_rpi_dac_device); - bcm_register_device_dt(&snd_pcm1794a_codec_device); - -From 963fd96f5747dd0c693a87cbb23bc1239d3bda72 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Thu, 16 Jan 2014 07:36:35 +0100 -Subject: [PATCH 039/216] ASoC: wm8804: Set idle_bias_off to false Idle bias - has been change to remove warning on driver startup - -Signed-off-by: Daniel Matuschek ---- - sound/soc/codecs/wm8804.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index ba2a0f8..91974f9 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -653,7 +653,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { - .probe = wm8804_probe, - .remove = wm8804_remove, - .set_bias_level = wm8804_set_bias_level, -- .idle_bias_off = true, -+ .idle_bias_off = false, - - .controls = wm8804_snd_controls, - .num_controls = ARRAY_SIZE(wm8804_snd_controls), - -From f5995e9c2cc2d801d5b05e3f4be0bdafb184943a Mon Sep 17 00:00:00 2001 -From: Gordon Garrity -Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 040/216] Add IQaudIO Sound Card support for Raspberry Pi - ---- - arch/arm/mach-bcm2708/bcm2708.c | 22 ++++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio-dac.c | 111 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 142 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio-dac.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0ad5343..a812b51 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -678,6 +678,22 @@ static struct platform_device snd_pcm1794a_codec_device = { - }; - #endif - -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+static struct platform_device snd_rpi_iqaudio_dac_device = { -+ .name = "snd-rpi-iqaudio-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+// Use the actual device name rather than generic driver name -+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4c) -+ }, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -846,6 +862,12 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm1794a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); -+#endif -+ -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index d4a00fc..faa89ef 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -39,3 +39,10 @@ config SND_BCM2708_SOC_RPI_DAC - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. -+ -+config SND_BCM2708_SOC_IQAUDIO_DAC -+ tristate "Support for IQaudIO-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ help -+ Say Y or M if you want to add support for IQaudIO-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 826df7d..d597fb0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,7 +12,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -new file mode 100644 -index 0000000..8d0e2ae ---- /dev/null -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,111 @@ -+/* -+ * ASoC Driver for IQaudIO DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { -+ .hw_params = snd_rpi_iqaudio_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { -+{ -+ .name = "IQaudIO DAC", -+ .stream_name = "IQaudIO DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_iqaudio_dac_ops, -+ .init = snd_rpi_iqaudio_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_dac = { -+ .name = "IQaudIODAC", -+ .dai_link = snd_rpi_iqaudio_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), -+}; -+ -+static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); -+} -+ -+static const struct of_device_id iqaudio_of_match[] = { -+ { .compatible = "iqaudio,iqaudio-dac", }, -+ {}, -+}; -+ -+static struct platform_driver snd_rpi_iqaudio_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-iqaudio-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = iqaudio_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_dac_probe, -+ .remove = snd_rpi_iqaudio_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); -+MODULE_LICENSE("GPL v2"); - -From 5d1809ba161ed01404974ad13403d23a008bd181 Mon Sep 17 00:00:00 2001 -From: Howard Mitchell -Date: Mon, 2 Mar 2015 17:28:02 +0000 -Subject: [PATCH 041/216] Set a limit of 0dB on Digital Volume Control - -The main volume control in the PCM512x DAC has a range up to -+24dB. This is dangerously loud and can potentially cause massive -clipping in the output stages. Therefore this sets a sensible -limit of 0dB for this control. ---- - sound/soc/bcm/iqaudio-dac.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -index 8d0e2ae..aff7377 100644 ---- a/sound/soc/bcm/iqaudio-dac.c -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -25,7 +25,13 @@ - - static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) - { --// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ ret = snd_soc_limit_volume(codec, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); - - return 0; - } - -From 8dbd2bddafe5d604e9f03a702d5ae50c0dd791e6 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 042/216] vmstat: Workaround for issue where dirty page count - goes negative - -See: -https://github.com/raspberrypi/linux/issues/617 -http://www.spinics.net/lists/linux-mm/msg72236.html ---- - include/linux/vmstat.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h -index 82e7db7..f87d16d 100644 ---- a/include/linux/vmstat.h -+++ b/include/linux/vmstat.h -@@ -241,7 +241,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) - static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) - { - atomic_long_dec(&zone->vm_stat[item]); -+ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&zone->vm_stat[item]) < 0)) -+ atomic_long_set(&zone->vm_stat[item], 0); - atomic_long_dec(&vm_stat[item]); -+ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&vm_stat[item]) < 0)) -+ atomic_long_set(&vm_stat[item], 0); - } - - static inline void __inc_zone_page_state(struct page *page, - -From 15bf30debd62320326c6a474f69eabbf3b43029e Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 18:55:53 +0100 -Subject: [PATCH 043/216] BCM2708: armctrl: Add IRQ Device Tree support - -Add Device Tree IRQ support for BCM2708. -Usage is the same as for irq-bcm2835. -See binding document: brcm,bcm2835-armctrl-ic.txt - -A bank 3 is added to handle GPIO interrupts. This is done because -armctrl also handles GPIO interrupts. - -Signed-off-by: Noralf Tronnes - -BCM2708: armctrl: remove irq bank 3 - -irq bank 3 was needed by the pinctrl-bcm2708 and bcm2708_gpio -combination. It is no longer required. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/mach-bcm2708/armctrl.c | 96 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 96 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index 96fa9b9..74bacb3 100644 ---- a/arch/arm/mach-bcm2708/armctrl.c -+++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -23,6 +23,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -79,6 +81,99 @@ static void armctrl_unmask_irq(struct irq_data *d) - } - } - -+#ifdef CONFIG_OF -+ -+#define NR_IRQS_BANK0 21 -+#define NR_BANKS 3 -+#define IRQS_PER_BANK 32 -+ -+/* from drivers/irqchip/irq-bcm2835.c */ -+static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, -+ const u32 *intspec, unsigned int intsize, -+ unsigned long *out_hwirq, unsigned int *out_type) -+{ -+ if (WARN_ON(intsize != 2)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[0] >= NR_BANKS)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) -+ return -EINVAL; -+ -+ if (intspec[0] == 0) -+ *out_hwirq = ARM_IRQ0_BASE + intspec[1]; -+ else if (intspec[0] == 1) -+ *out_hwirq = ARM_IRQ1_BASE + intspec[1]; -+ else -+ *out_hwirq = ARM_IRQ2_BASE + intspec[1]; -+ -+ /* reverse remap_irqs[] */ -+ switch (*out_hwirq) { -+ case INTERRUPT_VC_JPEG: -+ *out_hwirq = INTERRUPT_JPEG; -+ break; -+ case INTERRUPT_VC_USB: -+ *out_hwirq = INTERRUPT_USB; -+ break; -+ case INTERRUPT_VC_3D: -+ *out_hwirq = INTERRUPT_3D; -+ break; -+ case INTERRUPT_VC_DMA2: -+ *out_hwirq = INTERRUPT_DMA2; -+ break; -+ case INTERRUPT_VC_DMA3: -+ *out_hwirq = INTERRUPT_DMA3; -+ break; -+ case INTERRUPT_VC_I2C: -+ *out_hwirq = INTERRUPT_I2C; -+ break; -+ case INTERRUPT_VC_SPI: -+ *out_hwirq = INTERRUPT_SPI; -+ break; -+ case INTERRUPT_VC_I2SPCM: -+ *out_hwirq = INTERRUPT_I2SPCM; -+ break; -+ case INTERRUPT_VC_SDIO: -+ *out_hwirq = INTERRUPT_SDIO; -+ break; -+ case INTERRUPT_VC_UART: -+ *out_hwirq = INTERRUPT_UART; -+ break; -+ case INTERRUPT_VC_ARASANSDIO: -+ *out_hwirq = INTERRUPT_ARASANSDIO; -+ break; -+ } -+ -+ *out_type = IRQ_TYPE_NONE; -+ return 0; -+} -+ -+static struct irq_domain_ops armctrl_ops = { -+ .xlate = armctrl_xlate -+}; -+ -+void __init armctrl_dt_init(void) -+{ -+ struct device_node *np; -+ struct irq_domain *domain; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); -+ if (!np) -+ return; -+ -+ domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, -+ IRQ_ARMCTRL_START, 0, -+ &armctrl_ops, NULL); -+ WARN_ON(!domain); -+} -+#else -+void __init armctrl_dt_init(void) { } -+#endif /* CONFIG_OF */ -+ - #if defined(CONFIG_PM) - - /* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ -@@ -215,5 +310,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, - - armctrl_pm_register(base, irq_start, resume_sources); - init_FIQ(FIQ_START); -+ armctrl_dt_init(); - return 0; - } - -From e85c6248222486f0aca8f09ea4bf7ad463b15487 Mon Sep 17 00:00:00 2001 -From: notro -Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 044/216] BCM2708: use pinctrl-bcm2835 - -Use pinctrl-bcm2835 instead of the pinctrl-bcm2708 and bcm2708_gpio -combination. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/mach-bcm2708/Kconfig | 3 +++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - drivers/pinctrl/pinctrl-bcm2835.c | 2 +- - 3 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 182e7ba..4cfae55 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -14,6 +14,9 @@ config BCM2708_DT - depends on MACH_BCM2708 - default n - select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 - help - Enable Device Tree support for BCM2708 - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a812b51..a207ad8 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -816,7 +816,7 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO -- bcm_register_device(&bcm2708_gpio_device); -+ bcm_register_device_dt(&bcm2708_gpio_device); - #endif - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index 9aa8a3f..9d1149e 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -382,7 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = { - .get = bcm2835_gpio_get, - .set = bcm2835_gpio_set, - .to_irq = bcm2835_gpio_to_irq, -- .base = -1, -+ .base = 0, - .ngpio = BCM2835_NUM_GPIOS, - .can_sleep = false, - }; - -From d00f2dcc5c02b51e10e6516e12570db41509ffe5 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 27 Jul 2014 20:12:58 +0200 -Subject: [PATCH 045/216] spi: bcm2708: add device tree support - -Add DT support to driver and add to .dtsi file. -Setup pins and spidev in .dts file. -SPI is disabled by default. - -Signed-off-by: Noralf Tronnes - -BCM2708: don't register SPI controller when using DT - -The device for the SPI controller is in the Device Tree. -Only register the device when not using DT. - -Signed-off-by: Noralf Tronnes - -spi: bcm2835: make driver available on ARCH_BCM2708 - -Make this driver available on ARCH_BCM2708 - -Signed-off-by: Noralf Tronnes - -bcm2708: Remove the prohibition on mixing SPIDEV and DT ---- - arch/arm/boot/dts/bcm2708.dtsi | 8 ++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 7 ++++--- - drivers/spi/Kconfig | 4 ++-- - drivers/spi/spi-bcm2708.c | 8 ++++++++ - 4 files changed, 22 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 96b7311..93f009a 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -82,5 +82,13 @@ - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; - }; - }; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a207ad8..e366bb4 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -836,7 +836,7 @@ void __init bcm2708_init(void) - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); - -- bcm_register_device(&bcm2708_spi_device); -+ bcm_register_device_dt(&bcm2708_spi_device); - bcm_register_device(&bcm2708_bsc0_device); - bcm_register_device(&bcm2708_bsc1_device); - -@@ -876,8 +876,9 @@ void __init bcm2708_init(void) - system_serial_low = serial; - - #ifdef CONFIG_BCM2708_SPIDEV -- spi_register_board_info(bcm2708_spi_devices, -- ARRAY_SIZE(bcm2708_spi_devices)); -+ if (!use_dt) -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); - #endif - } - -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 9628e75..113bf64 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -77,7 +77,7 @@ config SPI_ATMEL - - config SPI_BCM2835 - tristate "BCM2835 SPI controller" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -88,7 +88,7 @@ config SPI_BCM2835 - - config SPI_BCM2708 - tristate "BCM2708 SPI controller driver (SPI0)" -- depends on MACH_BCM2708 -+ depends on MACH_BCM2708 || MACH_BCM2709 - help - This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This - driver is not compatible with the "Universal SPI Master" or the SPI slave -diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c -index 349d21f..041b5e2 100644 ---- a/drivers/spi/spi-bcm2708.c -+++ b/drivers/spi/spi-bcm2708.c -@@ -512,6 +512,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - master->setup = bcm2708_spi_setup; - master->transfer = bcm2708_spi_transfer; - master->cleanup = bcm2708_spi_cleanup; -+ master->dev.of_node = pdev->dev.of_node; - platform_set_drvdata(pdev, master); - - bs = spi_master_get_devdata(master); -@@ -596,10 +597,17 @@ static int bcm2708_spi_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm2708_spi_match[] = { -+ { .compatible = "brcm,bcm2708-spi", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_spi_match); -+ - static struct platform_driver bcm2708_spi_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_spi_match, - }, - .probe = bcm2708_spi_probe, - .remove = bcm2708_spi_remove, - -From 13cf0c2ef8f80ef3e128343e2d07cd3d31eb9860 Mon Sep 17 00:00:00 2001 -From: notro -Date: Tue, 29 Jul 2014 11:04:49 +0200 -Subject: [PATCH 046/216] i2c: bcm2708: add device tree support - -Add DT support to driver and add to .dtsi file. -Setup pins in .dts file. -i2c is disabled by default. - -Signed-off-by: Noralf Tronnes - -bcm2708: don't register i2c controllers when using DT - -The devices for the i2c controllers are in the Device Tree. -Only register devices when not using DT. - -Signed-off-by: Noralf Tronnes - -i2c: bcm2835: make driver available on ARCH_BCM2708 - -Make this driver available on ARCH_BCM2708 - -Signed-off-by: Noralf Tronnes ---- - arch/arm/boot/dts/bcm2708.dtsi | 7 +++++++ - arch/arm/mach-bcm2708/bcm2708.c | 4 ++-- - drivers/i2c/busses/Kconfig | 4 ++-- - drivers/i2c/busses/i2c-bcm2708.c | 24 ++++++++++++++++++++++++ - 4 files changed, 35 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 93f009a..0a916a4 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -83,6 +83,13 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ - clk_spi: clock@2 { - compatible = "fixed-clock"; - reg = <2>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e366bb4..a81200e 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -837,8 +837,8 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device(&bcm2708_bsc0_device); -- bcm_register_device(&bcm2708_bsc1_device); -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 00c7baa..92009dc 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -10,7 +10,7 @@ comment "PC SMBus host controller drivers" - - config I2C_BCM2708 - tristate "BCM2708 BSC" -- depends on MACH_BCM2708 -+ depends on MACH_BCM2708 || MACH_BCM2709 - help - Enabling this option will add BSC (Broadcom Serial Controller) - support for the BCM2708. BSC is a Broadcom proprietary bus compatible -@@ -381,7 +381,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 7d385a3..526129b 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -303,6 +304,21 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - unsigned long bus_hz; - u32 cdiv; - -+ if (pdev->dev.of_node) { -+ u32 bus_clk_rate; -+ pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c"); -+ if (pdev->id < 0) { -+ dev_err(&pdev->dev, "alias is missing\n"); -+ return -EINVAL; -+ } -+ if (!of_property_read_u32(pdev->dev.of_node, -+ "clock-frequency", &bus_clk_rate)) -+ baudrate = bus_clk_rate; -+ else -+ dev_warn(&pdev->dev, -+ "Could not read clock-frequency property\n"); -+ } -+ - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(&pdev->dev, "could not get IO memory\n"); -@@ -336,6 +352,7 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; - strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ adap->dev.of_node = pdev->dev.of_node; - - switch (pdev->id) { - case 0: -@@ -416,10 +433,17 @@ static int bcm2708_i2c_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm2708_i2c_of_match[] = { -+ { .compatible = "brcm,bcm2708-i2c" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match); -+ - static struct platform_driver bcm2708_i2c_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_i2c_of_match, - }, - .probe = bcm2708_i2c_probe, - .remove = bcm2708_i2c_remove, - -From b36757e9c2eb66112c0cebce20ac608f1f94cbe4 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 047/216] hid: Reduce default mouse polling interval to 60Hz - -Reduces overhead when using X ---- - drivers/hid/usbhid/hid-core.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index bfbe1be..a738b25 100644 ---- a/drivers/hid/usbhid/hid-core.c -+++ b/drivers/hid/usbhid/hid-core.c -@@ -49,7 +49,7 @@ - * Module parameters. - */ - --static unsigned int hid_mousepoll_interval; -+static unsigned int hid_mousepoll_interval = ~0; - module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); - MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -@@ -1090,8 +1090,12 @@ static int usbhid_start(struct hid_device *hid) - } - - /* Change the polling interval of mice. */ -- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) -- interval = hid_mousepoll_interval; -+ if (hid->collection->usage == HID_GD_MOUSE) { -+ if (hid_mousepoll_interval == ~0 && interval < 16) -+ interval = 16; -+ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) -+ interval = hid_mousepoll_interval; -+ } - - ret = -ENOMEM; - if (usb_endpoint_dir_in(endpoint)) { - -From 72f91c3f7d8b2944ccadbe7d3d57128c1fc08a8b Mon Sep 17 00:00:00 2001 -From: P33M -Date: Thu, 24 Jul 2014 21:24:03 +0100 -Subject: [PATCH 048/216] usb: core: make overcurrent messages more prominent - -Hub overcurrent messages are more serious than "debug". Increase loglevel. ---- - drivers/usb/core/hub.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 3b71516..8324c14 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4922,7 +4922,7 @@ static void port_event(struct usb_hub *hub, int port1) - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - u16 status = 0, unused; - -- dev_dbg(&port_dev->dev, "over-current change\n"); -+ dev_notice(&port_dev->dev, "over-current change\n"); - usb_clear_port_feature(hdev, port1, - USB_PORT_FEAT_C_OVER_CURRENT); - msleep(100); /* Cool down */ - -From cf880d700f626df4e4910b8dedea887720bf6018 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 7 Aug 2014 02:03:50 +0100 -Subject: [PATCH 049/216] Revert "ARM: dma: Use dma_pfn_offset for dma address - translation" - -This reverts commit 6ce0d20016925d031f1e24d64302e4c976d7cec6. ---- - arch/arm/include/asm/dma-mapping.h | 18 +----------------- - 1 file changed, 1 insertion(+), 17 deletions(-) - -diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h -index b52101d3..f5572d9 100644 ---- a/arch/arm/include/asm/dma-mapping.h -+++ b/arch/arm/include/asm/dma-mapping.h -@@ -58,37 +58,21 @@ static inline int dma_set_mask(struct device *dev, u64 mask) - #ifndef __arch_pfn_to_dma - static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) - { -- if (dev) -- pfn -= dev->dma_pfn_offset; - return (dma_addr_t)__pfn_to_bus(pfn); - } - - static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) - { -- unsigned long pfn = __bus_to_pfn(addr); -- -- if (dev) -- pfn += dev->dma_pfn_offset; -- -- return pfn; -+ return __bus_to_pfn(addr); - } - - static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) - { -- if (dev) { -- unsigned long pfn = dma_to_pfn(dev, addr); -- -- return phys_to_virt(__pfn_to_phys(pfn)); -- } -- - return (void *)__bus_to_virt((unsigned long)addr); - } - - static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) - { -- if (dev) -- return pfn_to_dma(dev, virt_to_pfn(addr)); -- - return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); - } - - -From 3492b141fbae950fd9614cb643257658e5d89329 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 050/216] 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. ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 119 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 147 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dacplus.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a81200e..5f7df9e 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,20 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+static struct platform_device snd_rpi_hifiberry_dacplus_device = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4d) -+ }, -+}; -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) - static struct platform_device snd_hifiberry_digi_device = { - .name = "snd-hifiberry-digi", -@@ -852,6 +866,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) - bcm_register_device_dt(&snd_hifiberry_digi_device); - i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index faa89ef..7675501 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - help - Say Y or M if you want to add support for HifiBerry DAC. - -+config SND_BCM2708_SOC_HIFIBERRY_DACPLUS -+ tristate "Support for HifiBerry DAC+" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM512x -+ help -+ Say Y or M if you want to add support for HifiBerry DAC+. -+ - config SND_BCM2708_SOC_HIFIBERRY_DIGI - tristate "Support for HifiBerry Digi" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index d597fb0..c02e3a2 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -new file mode 100644 -index 0000000..c63387b ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,119 @@ -+/* -+ * ASoC Driver for HiFiBerry DAC+ -+ * -+ * Author: Daniel Matuschek -+ * Copyright 2014 -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/pcm512x.h" -+ -+static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+static int snd_rpi_hifiberry_dacplus_startup(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_dacplus_shutdown(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { -+ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, -+ .startup = snd_rpi_hifiberry_dacplus_startup, -+ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { -+{ -+ .name = "HiFiBerry DAC+", -+ .stream_name = "HiFiBerry DAC+ HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004d", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dacplus_ops, -+ .init = snd_rpi_hifiberry_dacplus_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dacplus = { -+ .name = "snd_rpi_hifiberry_dacplus", -+ .dai_link = snd_rpi_hifiberry_dacplus_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -+}; -+ -+static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { -+ .driver = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_dacplus_probe, -+ .remove = snd_rpi_hifiberry_dacplus_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dacplus_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); -+MODULE_LICENSE("GPL v2"); - -From 3663a863bd1a077dfe48177181118e464a1d6f08 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 051/216] 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. ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 +++ - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 106 ++++++++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 362 ++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/tas5713.h | 210 +++++++++++++++++++++++ - 8 files changed, 712 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_amp.c - create mode 100644 sound/soc/codecs/tas5713.c - create mode 100644 sound/soc/codecs/tas5713.h - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5f7df9e..66bc839 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -678,6 +678,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { - - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+static struct platform_device snd_hifiberry_amp_device = { -+ .name = "snd-hifiberry-amp", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("tas5713", 0x1b) -+ }, -+}; -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - static struct platform_device snd_rpi_dac_device = { - .name = "snd-rpi-dac", -@@ -876,6 +890,11 @@ void __init bcm2708_init(void) - i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_amp_device); -+ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - bcm_register_device_dt(&snd_rpi_dac_device); - bcm_register_device_dt(&snd_pcm1794a_codec_device); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7675501..40d27c1 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - -+config SND_BCM2708_SOC_HIFIBERRY_AMP -+ tristate "Support for the HifiBerry Amp" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_TAS5713 -+ help -+ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index c02e3a2..17ea2b0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -new file mode 100644 -index 0000000..1e87ee06 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,106 @@ -+/* -+ * ASoC Driver for HifiBerry AMP -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ // ToDo: init of the dsp-registers. -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params ) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -+ .hw_params = snd_rpi_hifiberry_amp_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -+ { -+ .name = "HifiBerry AMP", -+ .stream_name = "HifiBerry AMP HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "tas5713-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "tas5713.1-001b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_amp_ops, -+ .init = snd_rpi_hifiberry_amp_init, -+ }, -+}; -+ -+ -+static struct snd_soc_card snd_rpi_hifiberry_amp = { -+ .name = "snd_rpi_hifiberry_amp", -+ .dai_link = snd_rpi_hifiberry_amp_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -+}; -+ -+ -+static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_amp.dev = &pdev->dev; -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -+ -+ if (ret != 0) { -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); -+} -+ -+ -+static struct platform_driver snd_rpi_hifiberry_amp_driver = { -+ .driver = { -+ .name = "snd-hifiberry-amp", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_amp_probe, -+ .remove = snd_rpi_hifiberry_amp_remove, -+}; -+ -+ -+module_platform_driver(snd_rpi_hifiberry_amp_driver); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 8682bcf..f49e15d 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -108,6 +108,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -+ select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4 if I2C -@@ -618,6 +619,9 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - -+config SND_SOC_TAS5713 -+ tristate -+ - config SND_SOC_TLV320AIC23 - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index c9bceba..078943d 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -108,6 +108,7 @@ snd-soc-sta529-objs := sta529.o - snd-soc-stac9766-objs := stac9766.o - snd-soc-tas5086-objs := tas5086.o - snd-soc-tfa9879-objs := tfa9879.o -+snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -289,6 +290,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o - obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o - obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o -+obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -new file mode 100644 -index 0000000..a24c1da ---- /dev/null -+++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,362 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "tas5713.h" -+ -+ -+static struct i2c_client *i2c; -+ -+struct tas5713_priv { -+ struct regmap *regmap; -+ int mclk_div; -+ struct snd_soc_codec *codec; -+}; -+ -+static struct tas5713_priv *priv_data; -+ -+ -+ -+ -+/* -+ * _ _ ___ _ ___ _ _ -+ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -+ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -+ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -+ * -+ */ -+ -+static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -+ -+ -+static const struct snd_kcontrol_new tas5713_snd_controls[] = { -+ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -+ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) -+}; -+ -+ -+ -+ -+/* -+ * __ __ _ _ ___ _ -+ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -+ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -+ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ u16 blen = 0x00; -+ -+ struct snd_soc_codec *codec; -+ codec = dai->codec; -+ priv_data->codec = dai->codec; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ blen = 0x03; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ blen = 0x1; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ blen = 0x04; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ blen = 0x05; -+ break; -+ default: -+ dev_err(dai->dev, "Unsupported word length: %u\n", -+ params_format(params)); -+ return -EINVAL; -+ } -+ -+ // set word length -+ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -+ -+ return 0; -+} -+ -+ -+static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ unsigned int val = 0; -+ -+ struct tas5713_priv *tas5713; -+ struct snd_soc_codec *codec = dai->codec; -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ if (mute) { -+ val = TAS5713_SOFT_MUTE_ALL; -+ } -+ -+ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); -+} -+ -+ -+static const struct snd_soc_dai_ops tas5713_dai_ops = { -+ .hw_params = tas5713_hw_params, -+ .mute_stream = tas5713_mute_stream, -+}; -+ -+ -+static struct snd_soc_dai_driver tas5713_dai = { -+ .name = "tas5713-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_48000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -+ }, -+ .ops = &tas5713_dai_ops, -+}; -+ -+ -+ -+ -+/* -+ * ___ _ ___ _ -+ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -+ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -+ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_remove(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ return 0; -+} -+ -+ -+static int tas5713_probe(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ int i, ret; -+ -+ i2c = container_of(codec->dev, struct i2c_client, dev); -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ -+ // Trim oscillator -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ msleep(1000); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ -+ // Clock mode: 44/48kHz, MCLK=64xfs -+ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ -+ // I2S 24bit -+ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ -+ // Set volume to 0db -+ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ -+ // Now start programming the default initialization sequence -+ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -+ ret = i2c_master_send(i2c, -+ tas5713_init_sequence[i].data, -+ tas5713_init_sequence[i].size); -+ -+ if (ret < 0) { -+ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -+ } -+ } -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -+ .probe = tas5713_probe, -+ .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+}; -+ -+ -+ -+ -+/* -+ * ___ ___ ___ ___ _ -+ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -+ * | | / / (__ | |) | '_| \ V / -_) '_| -+ * |___/___\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static const struct reg_default tas5713_reg_defaults[] = { -+ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -+ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -+ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -+ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB -+}; -+ -+ -+static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case TAS5713_DEVICE_ID: -+ case TAS5713_ERROR_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+ -+static const struct of_device_id tas5713_of_match[] = { -+ { .compatible = "ti,tas5713", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, tas5713_of_match); -+ -+ -+static struct regmap_config tas5713_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = TAS5713_MAX_REGISTER, -+ .volatile_reg = tas5713_reg_volatile, -+ -+ .cache_type = REGCACHE_RBTREE, -+ .reg_defaults = tas5713_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), -+}; -+ -+ -+static int tas5713_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ int ret; -+ -+ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -+ if (IS_ERR(priv_data->regmap)) { -+ ret = PTR_ERR(priv_data->regmap); -+ return ret; -+ } -+ -+ i2c_set_clientdata(i2c, priv_data); -+ -+ ret = snd_soc_register_codec(&i2c->dev, -+ &soc_codec_dev_tas5713, &tas5713_dai, 1); -+ -+ return ret; -+} -+ -+ -+static int tas5713_i2c_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_codec(&i2c->dev); -+ i2c_set_clientdata(i2c, NULL); -+ -+ kfree(priv_data); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id tas5713_i2c_id[] = { -+ { "tas5713", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -+ -+ -+static struct i2c_driver tas5713_i2c_driver = { -+ .driver = { -+ .name = "tas5713", -+ .owner = THIS_MODULE, -+ .of_match_table = tas5713_of_match, -+ }, -+ .probe = tas5713_i2c_probe, -+ .remove = tas5713_i2c_remove, -+ .id_table = tas5713_i2c_id -+}; -+ -+ -+static int __init tas5713_modinit(void) -+{ -+ int ret = 0; -+ -+ ret = i2c_add_driver(&tas5713_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -+ ret); -+ } -+ -+ return ret; -+} -+module_init(tas5713_modinit); -+ -+ -+static void __exit tas5713_exit(void) -+{ -+ i2c_del_driver(&tas5713_i2c_driver); -+} -+module_exit(tas5713_exit); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for TAS5713"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h -new file mode 100644 -index 0000000..8f019e0 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.h -@@ -0,0 +1,210 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#ifndef _TAS5713_H -+#define _TAS5713_H -+ -+ -+// TAS5713 I2C-bus register addresses -+ -+#define TAS5713_CLOCK_CTRL 0x00 -+#define TAS5713_DEVICE_ID 0x01 -+#define TAS5713_ERROR_STATUS 0x02 -+#define TAS5713_SYSTEM_CTRL1 0x03 -+#define TAS5713_SERIAL_DATA_INTERFACE 0x04 -+#define TAS5713_SYSTEM_CTRL2 0x05 -+#define TAS5713_SOFT_MUTE 0x06 -+#define TAS5713_VOL_MASTER 0x07 -+#define TAS5713_VOL_CH1 0x08 -+#define TAS5713_VOL_CH2 0x09 -+#define TAS5713_VOL_HEADPHONE 0x0A -+#define TAS5713_VOL_CONFIG 0x0E -+#define TAS5713_MODULATION_LIMIT 0x10 -+#define TAS5713_IC_DLY_CH1 0x11 -+#define TAS5713_IC_DLY_CH2 0x12 -+#define TAS5713_IC_DLY_CH3 0x13 -+#define TAS5713_IC_DLY_CH4 0x14 -+ -+#define TAS5713_START_STOP_PERIOD 0x1A -+#define TAS5713_OSC_TRIM 0x1B -+#define TAS5713_BKND_ERR 0x1C -+ -+#define TAS5713_INPUT_MUX 0x20 -+#define TAS5713_SRC_SELECT_CH4 0x21 -+#define TAS5713_PWM_MUX 0x25 -+ -+#define TAS5713_CH1_BQ0 0x29 -+#define TAS5713_CH1_BQ1 0x2A -+#define TAS5713_CH1_BQ2 0x2B -+#define TAS5713_CH1_BQ3 0x2C -+#define TAS5713_CH1_BQ4 0x2D -+#define TAS5713_CH1_BQ5 0x2E -+#define TAS5713_CH1_BQ6 0x2F -+#define TAS5713_CH1_BQ7 0x58 -+#define TAS5713_CH1_BQ8 0x59 -+ -+#define TAS5713_CH2_BQ0 0x30 -+#define TAS5713_CH2_BQ1 0x31 -+#define TAS5713_CH2_BQ2 0x32 -+#define TAS5713_CH2_BQ3 0x33 -+#define TAS5713_CH2_BQ4 0x34 -+#define TAS5713_CH2_BQ5 0x35 -+#define TAS5713_CH2_BQ6 0x36 -+#define TAS5713_CH2_BQ7 0x5C -+#define TAS5713_CH2_BQ8 0x5D -+ -+#define TAS5713_CH4_BQ0 0x5A -+#define TAS5713_CH4_BQ1 0x5B -+#define TAS5713_CH3_BQ0 0x5E -+#define TAS5713_CH3_BQ1 0x5F -+ -+#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B -+#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C -+#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E -+#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F -+#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 -+#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 -+#define TAS5713_DRC_CTRL 0x46 -+ -+#define TAS5713_BANK_SW_CTRL 0x50 -+#define TAS5713_CH1_OUTPUT_MIXER 0x51 -+#define TAS5713_CH2_OUTPUT_MIXER 0x52 -+#define TAS5713_CH1_INPUT_MIXER 0x53 -+#define TAS5713_CH2_INPUT_MIXER 0x54 -+#define TAS5713_OUTPUT_POST_SCALE 0x56 -+#define TAS5713_OUTPUT_PRESCALE 0x57 -+ -+#define TAS5713_IDF_POST_SCALE 0x62 -+ -+#define TAS5713_CH1_INLINE_MIXER 0x70 -+#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 -+#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 -+#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 -+#define TAS5713_CH2_INLINE_MIXER 0x74 -+#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 -+#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 -+#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -+ -+#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 -+#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -+ -+#define TAS5713_REGISTER_COUNT 0x46 -+#define TAS5713_MAX_REGISTER 0xF9 -+ -+ -+// Bitmasks for registers -+#define TAS5713_SOFT_MUTE_ALL 0x07 -+ -+ -+ -+struct tas5713_init_command { -+ const int size; -+ const char *const data; -+}; -+ -+static const struct tas5713_init_command tas5713_init_sequence[] = { -+ -+ // Trim oscillator -+ { .size = 2, .data = "\x1B\x00" }, -+ // System control register 1 (0x03): block DC -+ { .size = 2, .data = "\x03\x80" }, -+ // Mute everything -+ { .size = 2, .data = "\x05\x40" }, -+ // Modulation limit register (0x10): 97.7% -+ { .size = 2, .data = "\x10\x02" }, -+ // Interchannel delay registers -+ // (0x11, 0x12, 0x13, and 0x14): BD mode -+ { .size = 2, .data = "\x11\xB8" }, -+ { .size = 2, .data = "\x12\x60" }, -+ { .size = 2, .data = "\x13\xA0" }, -+ { .size = 2, .data = "\x14\x48" }, -+ // PWM shutdown group register (0x19): no shutdown -+ { .size = 2, .data = "\x19\x00" }, -+ // Input multiplexer register (0x20): BD mode -+ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -+ // PWM output mux register (0x25) -+ // Channel 1 --> OUTA, channel 1 neg --> OUTB -+ // Channel 2 --> OUTC, channel 2 neg --> OUTD -+ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -+ // DRC control (0x46): DRC off -+ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -+ // BKND_ERR register (0x1C): 299ms reset period -+ { .size = 2, .data = "\x1C\x07" }, -+ // Mute channel 3 -+ { .size = 2, .data = "\x0A\xFF" }, -+ // Volume configuration register (0x0E): volume slew 512 steps -+ { .size = 2, .data = "\x0E\x90" }, -+ // Clock control register (0x00): 44/48kHz, MCLK=64xfs -+ { .size = 2, .data = "\x00\x60" }, -+ // Bank switch and eq control (0x50): no bank switching -+ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -+ // Volume registers (0x07, 0x08, 0x09, 0x0A) -+ { .size = 2, .data = "\x07\x20" }, -+ { .size = 2, .data = "\x08\x30" }, -+ { .size = 2, .data = "\x09\x30" }, -+ { .size = 2, .data = "\x0A\xFF" }, -+ // 0x72, 0x73, 0x76, 0x77 input mixer: -+ // no intermix between channels -+ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -+ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -+ // no inline DRC inmix -+ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -+ // 0x56, 0x57 Output scale -+ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -+ // 0x3B, 0x3c -+ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ // 0x51, 0x52: output mixer -+ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ // PEQ defaults -+ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+}; -+ -+ -+#endif /* _TAS5713_H */ - -From 5cd70cb7da74d3817f6037213f1a79ff31254d89 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Apr 2015 19:14:18 +0100 -Subject: [PATCH 052/216] bcm2708: Allow option card devices to be configured - via DT - -If the kernel is built with Device Tree support, and if a DT blob -is provided for the kernel at boot time, then the platform devices -for option cards are not created. This avoids both the need to -blacklist unwanted devices, and the need to update the board -support code with each new device. ---- - sound/soc/bcm/bcm2835-i2s.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 03fa1cb..c816526 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -861,6 +861,7 @@ static const struct of_device_id bcm2835_i2s_of_match[] = { - { .compatible = "brcm,bcm2835-i2s", }, - {}, - }; -+MODULE_DEVICE_TABLE(of, bcm2835_i2s_of_match); - - static struct platform_driver bcm2835_i2s_driver = { - .probe = bcm2835_i2s_probe, - -From b2ee40fa3d362faf4071abda9f1e273b6e80ec78 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 18:45:39 +0100 -Subject: [PATCH 053/216] Adding Device Tree support for some RPi audio cards - ---- - arch/arm/boot/dts/hifiberry-dac-overlay.dts | 34 +++++++++++++++++++++ - arch/arm/boot/dts/hifiberry-dacplus-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/hifiberry-digi-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/iqaudio-dac-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/iqaudio-dacplus-overlay.dts | 39 +++++++++++++++++++++++++ - sound/soc/bcm/hifiberry_dac.c | 22 ++++++++++++++ - sound/soc/bcm/hifiberry_dacplus.c | 22 ++++++++++++++ - sound/soc/bcm/hifiberry_digi.c | 22 ++++++++++++++ - sound/soc/bcm/iqaudio-dac.c | 16 ++++++++++ - sound/soc/codecs/pcm5102a.c | 7 +++++ - 10 files changed, 279 insertions(+) - create mode 100644 arch/arm/boot/dts/hifiberry-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/hifiberry-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/hifiberry-digi-overlay.dts - create mode 100644 arch/arm/boot/dts/iqaudio-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/iqaudio-dacplus-overlay.dts - -diff --git a/arch/arm/boot/dts/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -new file mode 100644 -index 0000000..5e7633a ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for HiFiBerry DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -new file mode 100644 -index 0000000..deb9c625 ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dacplus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4d { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4d>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -new file mode 100644 -index 0000000..d0e0d8a ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Digi -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-digi"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8804@3b { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -new file mode 100644 -index 0000000..ea8173e ---- /dev/null -+++ b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -new file mode 100644 -index 0000000..735d8ab ---- /dev/null -+++ b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -index 4b70b45..3ab0f47 100644 ---- a/sound/soc/bcm/hifiberry_dac.c -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -72,6 +72,21 @@ static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -@@ -84,10 +99,17 @@ static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); - } - -+static const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_dac_driver = { - .driver = { - .name = "snd-hifiberry-dac", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dac_of_match, - }, - .probe = snd_rpi_hifiberry_dac_probe, - .remove = snd_rpi_hifiberry_dac_remove, -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -index c63387b..11e4f39 100644 ---- a/sound/soc/bcm/hifiberry_dacplus.c -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -90,6 +90,21 @@ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dacplus_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); - if (ret) - dev_err(&pdev->dev, -@@ -103,10 +118,17 @@ static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); - } - -+static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dacplus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { - .driver = { - .name = "snd-rpi-hifiberry-dacplus", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, - }, - .probe = snd_rpi_hifiberry_dacplus_probe, - .remove = snd_rpi_hifiberry_dacplus_remove, -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 446ecdd..74a8c73 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -125,6 +125,21 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_digi.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -@@ -137,10 +152,17 @@ static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); - } - -+static const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_digi_driver = { - .driver = { - .name = "snd-hifiberry-digi", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_digi_of_match, - }, - .probe = snd_rpi_hifiberry_digi_probe, - .remove = snd_rpi_hifiberry_digi_remove, -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -index aff7377..a38e874 100644 ---- a/sound/soc/bcm/iqaudio-dac.c -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -82,6 +82,21 @@ static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); - if (ret) - dev_err(&pdev->dev, -@@ -99,6 +114,7 @@ static const struct of_device_id iqaudio_of_match[] = { - { .compatible = "iqaudio,iqaudio-dac", }, - {}, - }; -+MODULE_DEVICE_TABLE(of, iqaudio_of_match); - - static struct platform_driver snd_rpi_iqaudio_dac_driver = { - .driver = { -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -index 126f1e9..7c6598e 100644 ---- a/sound/soc/codecs/pcm5102a.c -+++ b/sound/soc/codecs/pcm5102a.c -@@ -47,12 +47,19 @@ static int pcm5102a_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id pcm5102a_of_match[] = { -+ { .compatible = "ti,pcm5102a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm5102a_of_match); -+ - static struct platform_driver pcm5102a_codec_driver = { - .probe = pcm5102a_probe, - .remove = pcm5102a_remove, - .driver = { - .name = "pcm5102a-codec", - .owner = THIS_MODULE, -+ .of_match_table = pcm5102a_of_match, - }, - }; - - -From ea3aad745389e9631e71c1b175e37d6874ee980b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 054/216] fdt: Add support for the CONFIG_CMDLINE_EXTEND option - ---- - drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- - 1 file changed, 24 insertions(+), 5 deletions(-) - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 3a896c9..0320a6f 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -915,19 +915,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); -- if (p != NULL && l > 0) -- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE - * is set in which case we override whatever was found earlier. -+ * -+ * However, it can be useful to be able to treat the default as -+ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. - */ -+ ((char *)data)[0] = '\0'; -+ - #ifdef CONFIG_CMDLINE --#ifndef CONFIG_CMDLINE_FORCE -- if (!((char *)data)[0]) -+ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ -+ if (p != NULL && l > 0) { -+#if defined(CONFIG_CMDLINE_EXTEND) -+ int len = strlen(data); -+ if (len > 0) { -+ strlcat(data, " ", COMMAND_LINE_SIZE); -+ len++; -+ } -+ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); -+#elif defined(CONFIG_CMDLINE_FORCE) -+ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); -+#else -+ /* Neither extend nor force - just override */ -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ } -+#else /* CONFIG_CMDLINE */ -+ if (p != NULL && l > 0) { -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", (char*)data); - -From a9a57c353bdccbc5cd60d995c53d6146addf78fc Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 16 Dec 2014 10:23:48 +0000 -Subject: [PATCH 055/216] DT: Add overrides to enable i2c0, i2c1, spi and i2s - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 10 ++++++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 10 ++++++++++ - 2 files changed, 20 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 983c23f..d9886c3 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -79,3 +79,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; -+ -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index d8c6d15..167b22b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -79,3 +79,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; -+ -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ }; -+}; - -From 4bdc71b8c2f9444a8ec6fe833cb92ba4fd4130f7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 18 Dec 2014 16:48:32 +0000 -Subject: [PATCH 056/216] lirc-rpi: Add device tree support, and a suitable - overlay - -The overlay supports DT parameters that match the old module -parameters, except that gpio_in_pull should be set using the -strings "up", "down" or "off". - -lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode ---- - arch/arm/boot/dts/lirc-rpi-overlay.dts | 57 ++++++++++++ - drivers/staging/media/lirc/lirc_rpi.c | 154 +++++++++++++++++++++++++++------ - 2 files changed, 183 insertions(+), 28 deletions(-) - create mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts - -diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts -new file mode 100644 -index 0000000..7d5d82b ---- /dev/null -+++ b/arch/arm/boot/dts/lirc-rpi-overlay.dts -@@ -0,0 +1,57 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ lirc_rpi: lirc_rpi { -+ compatible = "rpi,lirc-rpi"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lirc_pins>; -+ status = "okay"; -+ -+ // Override autodetection of IR receiver circuit -+ // (0 = active high, 1 = active low, -1 = no override ) -+ rpi,sense = <0xffffffff>; -+ -+ // Software carrier -+ // (0 = off, 1 = on) -+ rpi,softcarrier = <1>; -+ -+ // Invert output -+ // (0 = off, 1 = on) -+ rpi,invert = <0>; -+ -+ // Enable debugging messages -+ // (0 = off, 1 = on) -+ rpi,debug = <0>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ lirc_pins: lirc_pins { -+ brcm,pins = <17 18>; -+ brcm,function = <1 0>; // out in -+ brcm,pull = <0 1>; // off down -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -+ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -+ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -+ -+ sense = <&lirc_rpi>,"rpi,sense:0"; -+ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -+ invert = <&lirc_rpi>,"rpi,invert:0"; -+ debug = <&lirc_rpi>,"rpi,debug:0"; -+ }; -+}; -diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c -index 8aa452d..24563ec 100644 ---- a/drivers/staging/media/lirc/lirc_rpi.c -+++ b/drivers/staging/media/lirc/lirc_rpi.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - - #include - -@@ -303,32 +304,117 @@ static int is_right_chip(struct gpio_chip *chip, void *data) - return 0; - } - -+static inline int read_bool_property(const struct device_node *np, -+ const char *propname, -+ bool *out_value) -+{ -+ u32 value = 0; -+ int err = of_property_read_u32(np, propname, &value); -+ if (err == 0) -+ *out_value = (value != 0); -+ return err; -+} -+ -+static void read_pin_settings(struct device_node *node) -+{ -+ u32 pin; -+ int index; -+ -+ for (index = 0; -+ of_property_read_u32_index( -+ node, -+ "brcm,pins", -+ index, -+ &pin) == 0; -+ index++) { -+ u32 function; -+ int err; -+ err = of_property_read_u32_index( -+ node, -+ "brcm,function", -+ index, -+ &function); -+ if (err == 0) { -+ if (function == 1) /* Output */ -+ gpio_out_pin = pin; -+ else if (function == 0) /* Input */ -+ gpio_in_pin = pin; -+ } -+ } -+} -+ - static int init_port(void) - { - int i, nlow, nhigh, ret; -+ struct device_node *node; -+ -+ node = lirc_rpi_dev->dev.of_node; - - gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip); - -- if (!gpiochip) -+ /* -+ * Because of the lack of a setpull function, only support -+ * pinctrl-bcm2835 if using device tree. -+ */ -+ if (!gpiochip && node) -+ gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip); -+ -+ if (!gpiochip) { -+ pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n"); - return -ENODEV; -+ } -+ -+ if (node) { -+ struct device_node *pins_node; -+ -+ pins_node = of_parse_phandle(node, "pinctrl-0", 0); -+ if (!pins_node) { -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": pinctrl settings not found!\n"); -+ ret = -EINVAL; -+ goto exit_init_port; -+ } -+ -+ read_pin_settings(pins_node); -+ -+ of_property_read_u32(node, "rpi,sense", &sense); -+ -+ read_bool_property(node, "rpi,softcarrier", &softcarrier); -+ -+ read_bool_property(node, "rpi,invert", &invert); -+ -+ read_bool_property(node, "rpi,debug", &debug); - -- if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -- printk(KERN_ALERT LIRC_DRIVER_NAME -- ": cant claim gpio pin %d\n", gpio_out_pin); -- ret = -ENODEV; -- goto exit_init_port; - } -+ else -+ { -+ if (gpio_in_pin >= BCM2708_NR_GPIOS || -+ gpio_out_pin >= BCM2708_NR_GPIOS) { -+ ret = -EINVAL; -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": invalid GPIO pin(s) specified!\n"); -+ goto exit_init_port; -+ } - -- if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -- printk(KERN_ALERT LIRC_DRIVER_NAME -- ": cant claim gpio pin %d\n", gpio_in_pin); -- ret = -ENODEV; -- goto exit_gpio_free_out_pin; -+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_out_pin); -+ ret = -ENODEV; -+ goto exit_init_port; -+ } -+ -+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_in_pin); -+ ret = -ENODEV; -+ goto exit_gpio_free_out_pin; -+ } -+ -+ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -+ gpiochip->direction_input(gpiochip, gpio_in_pin); -+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); - } - -- bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -- gpiochip->direction_input(gpiochip, gpio_in_pin); -- gpiochip->direction_output(gpiochip, gpio_out_pin, 1); - gpiochip->set(gpiochip, gpio_out_pin, invert); - - irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin); -@@ -522,15 +608,23 @@ static struct lirc_driver driver = { - .owner = THIS_MODULE, - }; - -+static const struct of_device_id lirc_rpi_of_match[] = { -+ { .compatible = "rpi,lirc-rpi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, lirc_rpi_of_match); -+ - static struct platform_driver lirc_rpi_driver = { - .driver = { - .name = LIRC_DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(lirc_rpi_of_match), - }, - }; - - static int __init lirc_rpi_init(void) - { -+ struct device_node *node; - int result; - - /* Init read buffer. */ -@@ -545,15 +639,26 @@ static int __init lirc_rpi_init(void) - goto exit_buffer_free; - } - -- lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -- if (!lirc_rpi_dev) { -- result = -ENOMEM; -- goto exit_driver_unregister; -+ node = of_find_compatible_node(NULL, NULL, -+ lirc_rpi_of_match[0].compatible); -+ -+ if (node) { -+ /* DT-enabled */ -+ lirc_rpi_dev = of_find_device_by_node(node); -+ WARN_ON(lirc_rpi_dev->dev.of_node != node); -+ of_node_put(node); - } -+ else { -+ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -+ if (!lirc_rpi_dev) { -+ result = -ENOMEM; -+ goto exit_driver_unregister; -+ } - -- result = platform_device_add(lirc_rpi_dev); -- if (result) -- goto exit_device_put; -+ result = platform_device_add(lirc_rpi_dev); -+ if (result) -+ goto exit_device_put; -+ } - - return 0; - -@@ -585,13 +690,6 @@ static int __init lirc_rpi_init_module(void) - if (result) - return result; - -- if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) { -- result = -EINVAL; -- printk(KERN_ERR LIRC_DRIVER_NAME -- ": invalid GPIO pin(s) specified!\n"); -- goto exit_rpi; -- } -- - result = init_port(); - if (result < 0) - goto exit_rpi; - -From fb3c953810dfcbba431ad3c70eb5751d014db152 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Jan 2015 12:06:55 +0000 -Subject: [PATCH 057/216] Fix the activity LED in DT mode - -Add a "leds" node to the base DTBs, and a subnode for the activity -LED. You can change the LED function like this: - - dtparam=act_led_trigger=heartbeat - -Add aliases for the other main nodes (soc, intc). - -Issue: linux #757 ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 18 ++++++++++++++---- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 18 ++++++++++++++---- - arch/arm/boot/dts/bcm2708.dtsi | 11 ++++++++++- - 3 files changed, 38 insertions(+), 9 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index d9886c3..95f03ba 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -7,11 +7,14 @@ - model = "Raspberry Pi Model B+"; - - aliases { -+ soc = &soc; - spi0 = &spi0; - i2c0 = &i2c0; - i2c1 = &i2c1; - i2s = &i2s; - gpio = &gpio; -+ intc = &intc; -+ leds = &leds; - sound = &sound; - }; - -@@ -80,12 +83,19 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&act_led { -+ gpios = <&gpio 47 0>; -+}; - - / { - __overrides__ { -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 167b22b..0631f45 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -7,11 +7,14 @@ - model = "Raspberry Pi Model B"; - - aliases { -+ soc = &soc; - spi0 = &spi0; - i2c0 = &i2c0; - i2c1 = &i2c1; - i2s = &i2s; - gpio = &gpio; -+ intc = &intc; -+ leds = &leds; - sound = &sound; - }; - -@@ -80,12 +83,19 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&act_led { -+ gpios = <&gpio 16 1>; -+}; - - / { - __overrides__ { -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 0a916a4..d879316 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -11,7 +11,7 @@ - bootargs = ""; - }; - -- soc { -+ soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; -@@ -76,6 +76,15 @@ - #size-cells = <0>; - status = "disabled"; - }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ -+ act_led: act { -+ label = "ACT"; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; - }; - - clocks { - -From 1c9f91aafc02bd624edc56899972cb13f48f921d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 15 Jan 2015 10:39:06 +0000 -Subject: [PATCH 058/216] Adding w1-gpio device tree overlays - -N.B. Requires firmware supporting multi-target overrides - -w1-gpio-overlay: - Use if a pullup pin is not required. - Parameters: - gpiopin= // default 4 - -w1-gpio-pullup-overlay: - Use if a pullup pin is required. - Parameters: - gpiopin= // default 4 - pullup= // default 5 ---- - arch/arm/boot/dts/w1-gpio-overlay.dts | 37 ++++++++++++++++++++++++++ - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 39 ++++++++++++++++++++++++++++ - 2 files changed, 76 insertions(+) - create mode 100644 arch/arm/boot/dts/w1-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/w1-gpio-pullup-overlay.dts - -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -new file mode 100644 -index 0000000..b2c5ee2 ---- /dev/null -+++ b/arch/arm/boot/dts/w1-gpio-overlay.dts -@@ -0,0 +1,37 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4>; -+ brcm,function = <0>; // in (initially) -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -new file mode 100644 -index 0000000..b3e97c2 ---- /dev/null -+++ b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>, <&gpio 5 1>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4 5>; -+ brcm,function = <0 1>; // in out -+ brcm,pull = <0 0>; // off off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"gpios:16", -+ <&w1_pins>,"brcm,pins:4"; -+ }; -+}; - -From 740e2da8a9fa6f84e95707ee0a10b4a4cfeaed4a Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Fri, 23 Jan 2015 16:41:17 +0100 -Subject: [PATCH 059/216] TAS5713: return error if initialisation fails - -Existing TAS5713 driver logs errors during initialisation, but does not return -an error code. Therefore even if initialisation fails, the driver will still be -loaded, but won't work. This patch fixes this. I2C communication error will now -reported correctly by a non-zero return code. ---- - sound/soc/codecs/tas5713.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -index a24c1da..9b27138 100644 ---- a/sound/soc/codecs/tas5713.c -+++ b/sound/soc/codecs/tas5713.c -@@ -182,33 +182,40 @@ static int tas5713_probe(struct snd_soc_codec *codec) - - // Reset error - ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; - - // Trim oscillator -- ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ if (ret < 0) return ret; - msleep(1000); - - // Reset error - ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; - - // Clock mode: 44/48kHz, MCLK=64xfs - ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ if (ret < 0) return ret; - - // I2S 24bit - ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ if (ret < 0) return ret; - - // Unmute - ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; - ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ if (ret < 0) return ret; - - // Set volume to 0db - ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ if (ret < 0) return ret; - - // Now start programming the default initialization sequence - for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { - ret = i2c_master_send(i2c, - tas5713_init_sequence[i].data, - tas5713_init_sequence[i].size); -- - if (ret < 0) { - printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); - } -@@ -216,7 +223,7 @@ static int tas5713_probe(struct snd_soc_codec *codec) - - // Unmute - ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -- -+ if (ret < 0) return ret; - - return 0; - } - -From 9615583a44fc9449d77a247d0207b35eab1db982 Mon Sep 17 00:00:00 2001 +From 0ecc87e37d9107eb533346a4a482bbf78920d16c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 23 Jan 2015 14:48:55 +0000 -Subject: [PATCH 060/216] scripts/dtc: Update to upstream version with overlay +Subject: [PATCH 23/77] scripts/dtc: Update to upstream version with overlay patches --- @@ -123717,736 +117880,716 @@ index 54d4e904..d644002 100644 -#define DTC_VERSION "DTC 1.4.0-dirty" +#define DTC_VERSION "DTC 1.4.1-g36c70742" -From 453099dc662c02d1308039ab2dabb176e052eabf Mon Sep 17 00:00:00 2001 +From 4cccd63c16e3ef4e2a35144e2806d1d1c56bc381 Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 23 Jan 2015 15:18:03 +0000 -Subject: [PATCH 061/216] BCM2708_DT: Build the overlays as well +Date: Mon, 11 May 2015 09:00:42 +0100 +Subject: [PATCH 24/77] scripts: Add mkknlimg and knlinfo scripts from tools + repo +The Raspberry Pi firmware looks for a trailer on the kernel image to +determine whether it was compiled with Device Tree support enabled. +If the firmware finds a kernel without this trailer, or which has a +trailer indicating that it isn't DT-capable, it disables DT support +and reverts to using ATAGs. + +The mkknlimg utility adds that trailer, having first analysed the +image to look for signs of DT support and the kernel version string. + +knlinfo displays the contents of the trailer in the given kernel image. + +scripts/mkknlimg: Add support for ARCH_BCM2835 + +Add a new trailer field indicating whether this is an ARCH_BCM2835 +build, as opposed to MACH_BCM2708/9. If the loader finds this flag +is set it changes the default base dtb file name from bcm270x... +to bcm283y... + +Also update knlinfo to show the status of the field. --- - arch/arm/boot/dts/Makefile | 9 +++++++++ - 1 file changed, 9 insertions(+) + scripts/knlinfo | 168 +++++++++++++++++++++++++++++++++ + scripts/mkknlimg | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 443 insertions(+) + create mode 100755 scripts/knlinfo + create mode 100755 scripts/mkknlimg -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 25fbf52..63d902c 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,15 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+ - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC - -From b39dde193e6242ec53938122e553e3af4cd528ed Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Sun, 25 Jan 2015 19:41:06 +0100 -Subject: [PATCH 062/216] Add device tree overlay for HiFiBerry Amp/Amp+ - -This patch add the missing device tree file for the HiFiBerry Amp and Amp+ boards. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hifiberry-amp-overlay.dts | 39 +++++++++++++++++++++++++++++ - 2 files changed, 40 insertions(+) - create mode 100644 arch/arm/boot/dts/hifiberry-amp-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 63d902c..63d89df 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -15,6 +15,7 @@ endif - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -new file mode 100644 -index 0000000..2c81448 +diff --git a/scripts/knlinfo b/scripts/knlinfo +new file mode 100755 +index 0000000..a0e8663 --- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Amp/Amp+ -+/dts-v1/; -+/plugin/; ++++ b/scripts/knlinfo +@@ -0,0 +1,168 @@ ++#!/usr/bin/env perl ++# ---------------------------------------------------------------------- ++# knlinfo by Phil Elwell for Raspberry Pi ++# ++# (c) 2014,2015 Raspberry Pi (Trading) Limited ++# ++# Licensed under the terms of the GNU General Public License. ++# ---------------------------------------------------------------------- + -+/ { -+ compatible = "brcm,bcm2708"; ++use strict; ++use integer; + -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-amp"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; ++use Fcntl ":seek"; + -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; ++my $trailer_magic = 'RPTL'; + -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; ++my %atom_formats = ++( ++ 'DTOK' => \&format_bool, ++ 'KVer' => \&format_string, ++ '283x' => \&format_bool, ++); + -+ tas5713@1b { -+ #sound-dai-cells = <0>; -+ compatible = "ti,tas5713"; -+ reg = <0x1b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From da11da093a2c65a9faa481e0688b0f242476ee78 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 26 Jan 2015 09:18:24 +0000 -Subject: [PATCH 063/216] Add pps-gpio DT overlay - -Parameters: - gpiopin= // Default 18 ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pps-gpio-overlay.dts | 34 ++++++++++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+) - create mode 100644 arch/arm/boot/dts/pps-gpio-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 63d89df..18637de 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - -diff --git a/arch/arm/boot/dts/pps-gpio-overlay.dts b/arch/arm/boot/dts/pps-gpio-overlay.dts -new file mode 100644 -index 0000000..40bf0e1 ---- /dev/null -+++ b/arch/arm/boot/dts/pps-gpio-overlay.dts -@@ -0,0 +1,34 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ pps: pps { -+ compatible = "pps-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pps_pins>; -+ gpios = <&gpio 18 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pps_pins: pps_pins { -+ brcm,pins = <18>; -+ brcm,function = <0>; // in -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&pps>,"gpios:4", -+ <&pps_pins>,"brcm,pins:0"; -+ }; -+}; - -From 4cddfa6e3758e34eaeeb8457e0f012965436bc1c Mon Sep 17 00:00:00 2001 -From: Timo Kokkonen -Date: Wed, 29 Oct 2014 23:30:30 -0700 -Subject: [PATCH 064/216] Added support to reserve/enable a GPIO pin to be used - from pps-gpio module (LinuxPPS). Enable PPS modules in default config for - RPi. - ---- - arch/arm/mach-bcm2708/bcm2708.c | 27 +++++++++++++++++++++++++++ - arch/arm/mach-bcm2709/bcm2709.c | 27 +++++++++++++++++++++++++++ - 2 files changed, 54 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 66bc839..cc3e56c 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -93,6 +94,7 @@ static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; -+static int pps_gpio_pin = -1; - - static unsigned use_dt = 0; - -@@ -278,6 +280,19 @@ static struct platform_device w1_device = { - }; - #endif - -+static struct pps_gpio_platform_data pps_gpio_info = { -+ .assert_falling_edge = false, -+ .capture_clear = false, -+ .gpio_pin = -1, -+ .gpio_label = "PPS", -+}; -+ -+static struct platform_device pps_gpio_device = { -+ .name = "pps-gpio", -+ .id = PLATFORM_DEVID_NONE, -+ .dev.platform_data = &pps_gpio_info, -+}; -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -846,6 +861,16 @@ void __init bcm2708_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -+ -+#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) -+ if (!use_dt && (pps_gpio_pin >= 0)) { -+ pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); -+ pps_gpio_info.gpio_pin = pps_gpio_pin; -+ pps_gpio_device.id = pps_gpio_pin; -+ bcm_register_device(&pps_gpio_device); -+ } -+#endif -+ - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -@@ -1099,3 +1124,5 @@ module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); - module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); -+module_param(pps_gpio_pin, int, 0644); -+MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index c4bd0a4..914c970 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -95,6 +96,7 @@ static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; -+static int pps_gpio_pin = -1; - - static unsigned use_dt = 0; - -@@ -288,6 +290,19 @@ static struct platform_device w1_device = { - }; - #endif - -+static struct pps_gpio_platform_data pps_gpio_info = { -+ .assert_falling_edge = false, -+ .capture_clear = false, -+ .gpio_pin = -1, -+ .gpio_label = "PPS", -+}; -+ -+static struct platform_device pps_gpio_device = { -+ .name = "pps-gpio", -+ .id = PLATFORM_DEVID_NONE, -+ .dev.platform_data = &pps_gpio_info, -+}; -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -868,6 +883,16 @@ void __init bcm2709_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -+ -+#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) -+ if (!use_dt && (pps_gpio_pin >= 0)) { -+ pr_info("bcm2709: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); -+ pps_gpio_info.gpio_pin = pps_gpio_pin; -+ pps_gpio_device.id = pps_gpio_pin; -+ bcm_register_device(&pps_gpio_device); -+ } -+#endif -+ - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -@@ -1267,3 +1292,5 @@ module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); - module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); -+module_param(pps_gpio_pin, int, 0644); -+MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); - -From 2ff35a0e682880dbae67c842805ea848285b373f Mon Sep 17 00:00:00 2001 -From: Serge Schneider -Date: Wed, 3 Sep 2014 14:44:22 +0100 -Subject: [PATCH 065/216] I2C: Only register the I2C device for the current - board revision - ---- - arch/arm/mach-bcm2708/bcm2708.c | 14 ++++++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 14 ++++++++++++-- - 2 files changed, 24 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cc3e56c..c8aea5b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -95,6 +95,7 @@ static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; - static int pps_gpio_pin = -1; -+static bool vc_i2c_override = false; - - static unsigned use_dt = 0; - -@@ -890,8 +891,15 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device_dt(&bcm2708_bsc0_device); -- bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ if (vc_i2c_override) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ } else { -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -@@ -1126,3 +1134,5 @@ module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); - module_param(pps_gpio_pin, int, 0644); - MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -+module_param(vc_i2c_override, bool, 0644); -+MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 914c970..259d552 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -97,6 +97,7 @@ static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; - static int pps_gpio_pin = -1; -+static bool vc_i2c_override = false; - - static unsigned use_dt = 0; - -@@ -914,8 +915,15 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device_dt(&bcm2708_bsc0_device); -- bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ if (vc_i2c_override) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ } else { -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -@@ -1294,3 +1302,5 @@ module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); - module_param(pps_gpio_pin, int, 0644); - MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -+module_param(vc_i2c_override, bool, 0644); -+MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); - -From 32bee38e1fca47be55a48205e850c16901127982 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 28 Jan 2015 16:22:04 +0000 -Subject: [PATCH 066/216] BCM2708_DT: Add pcf8523-rtc overlay - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pcf8523-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/pcf8523-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 18637de..c909f7b 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -diff --git a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -new file mode 100644 -index 0000000..0071f62 ---- /dev/null -+++ b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF8523 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From 7358633426ec4c3897c26cb1575a0ab7309e4f73 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Sat, 31 Jan 2015 16:07:56 +0100 -Subject: [PATCH 067/216] Add a parameter to turn off SPDIF output if no audio - is playing - -This patch adds the paramater auto_shutdown_output to the kernel module. -Default behaviour of the module is the same, but when auto_shutdown_output -is set to 1, the SPDIF oputput will shutdown if no stream is playing. ---- - sound/soc/bcm/hifiberry_digi.c | 29 ++++++++++++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 74a8c73..a245995 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -26,6 +26,11 @@ - - #include "../codecs/wm8804.h" - -+static short int auto_shutdown_output = 0; -+module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); -+ -+ - static int samplerate=44100; - - static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) -@@ -38,6 +43,25 @@ static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - return 0; - } - -+static int snd_rpi_hifiberry_digi_startup(struct snd_pcm_substream *substream) { -+ /* turn on digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ return 0; ++if (@ARGV != 1) ++{ ++ print ("Usage: knlinfo \n"); ++ exit(1); +} + -+static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { -+ /* turn off output */ -+ if (auto_shutdown_output) { -+ /* turn off output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++my $kernel_file = $ARGV[0]; ++ ++ ++my ($atoms, $pos) = read_trailer($kernel_file); ++ ++exit(1) if (!$atoms); ++ ++printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos); ++ ++foreach my $atom (@$atoms) ++{ ++ printf(" %s: %s\n", $atom->[0], format_atom($atom)); ++} ++ ++exit(0); ++ ++sub read_trailer ++{ ++ my ($kernel_file) = @_; ++ my $fh; ++ ++ if (!open($fh, '<', $kernel_file)) ++ { ++ print ("* Failed to open '$kernel_file'\n"); ++ return undef; + } ++ ++ if (!seek($fh, -12, SEEK_END)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ my $last_bytes; ++ sysread($fh, $last_bytes, 12); ++ ++ my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes); ++ ++ if (($magic ne $trailer_magic) || ($data_len != 4)) ++ { ++ print ("* no trailer\n"); ++ return undef; ++ } ++ if (!seek($fh, -12, SEEK_END)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ $trailer_len -= 12; ++ ++ while ($trailer_len > 0) ++ { ++ if ($trailer_len < 8) ++ { ++ print ("* truncated atom header in trailer\n"); ++ return undef; ++ } ++ if (!seek($fh, -8, SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ $trailer_len -= 8; ++ ++ my $atom_hdr; ++ sysread($fh, $atom_hdr, 8); ++ my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr); ++ ++ if ($trailer_len < $atom_len) ++ { ++ print ("* truncated atom data in trailer\n"); ++ return undef; ++ } ++ ++ my $rounded_len = (($atom_len + 3) & ~3); ++ if (!seek($fh, -(8 + $rounded_len), SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ $trailer_len -= $rounded_len; ++ ++ my $atom_data; ++ sysread($fh, $atom_data, $atom_len); ++ ++ if (!seek($fh, -$atom_len, SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ push @$atoms, [ $atom_type, $atom_data ]; ++ } ++ ++ if (($$atoms[-1][0] eq "\x00\x00\x00\x00") && ++ ($$atoms[-1][1] eq "")) ++ { ++ pop @$atoms; ++ } ++ else ++ { ++ print ("* end marker missing from trailer\n"); ++ } ++ ++ return ($atoms, tell($fh)); ++} ++ ++sub format_atom ++{ ++ my ($atom) = @_; ++ ++ my $format_func = $atom_formats{$atom->[0]} || \&format_hex; ++ return $format_func->($atom->[1]); ++} ++ ++sub format_bool ++{ ++ my ($data) = @_; ++ return unpack('V', $data) ? 'true' : 'false'; ++} ++ ++sub format_int ++{ ++ my ($data) = @_; ++ return unpack('V', $data); ++} ++ ++sub format_string ++{ ++ my ($data) = @_; ++ return '"'.$data.'"'; ++} ++ ++sub format_hex ++{ ++ my ($data) = @_; ++ return unpack('H*', $data); ++} +diff --git a/scripts/mkknlimg b/scripts/mkknlimg +new file mode 100755 +index 0000000..3dff948 +--- /dev/null ++++ b/scripts/mkknlimg +@@ -0,0 +1,275 @@ ++#!/usr/bin/env perl ++# ---------------------------------------------------------------------- ++# mkknlimg by Phil Elwell for Raspberry Pi ++# based on extract-ikconfig by Dick Streefland ++# ++# (c) 2009,2010 Dick Streefland ++# (c) 2014,2015 Raspberry Pi (Trading) Limited ++# ++# Licensed under the terms of the GNU General Public License. ++# ---------------------------------------------------------------------- ++ ++use strict; ++use warnings; ++use integer; ++ ++my $trailer_magic = 'RPTL'; ++ ++my $tmpfile1 = "/tmp/mkknlimg_$$.1"; ++my $tmpfile2 = "/tmp/mkknlimg_$$.2"; ++ ++my $dtok = 0; ++my $is_283x = 0; ++ ++while (@ARGV && ($ARGV[0] =~ /^-/)) ++{ ++ my $arg = shift(@ARGV); ++ if ($arg eq '--dtok') ++ { ++ $dtok = 1; ++ } ++ elsif ($arg eq '--283x') ++ { ++ $is_283x = 1; ++ } ++ else ++ { ++ print ("* Unknown option '$arg'\n"); ++ usage(); ++ } ++} ++ ++usage() if (@ARGV != 2); ++ ++my $kernel_file = $ARGV[0]; ++my $out_file = $ARGV[1]; ++ ++if (! -r $kernel_file) ++{ ++ print ("* File '$kernel_file' not found\n"); ++ usage(); ++} ++ ++my @wanted_config_lines = ++( ++ 'CONFIG_BCM2708_DT', ++ 'CONFIG_ARCH_BCM2835' ++); ++ ++my @wanted_strings = ++( ++ 'bcm2708_fb', ++ 'brcm,bcm2835-mmc', ++ 'brcm,bcm2835-sdhost', ++ 'brcm,bcm2708-pinctrl', ++ 'brcm,bcm2835-gpio', ++ 'brcm,bcm2835-pm-wdt' ++); ++ ++my $res = try_extract($kernel_file, $tmpfile1); ++$res = try_decompress('\037\213\010', 'xy', 'gunzip', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('BZh', 'xy', 'bunzip2', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\211\114\132', 'xy', 'lzop -d', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++ ++my $append_trailer; ++my $trailer; ++my $kver = '?'; ++ ++$append_trailer = $dtok; ++ ++if ($res) ++{ ++ $kver = $res->{''} || '?'; ++ print("Version: $kver\n"); ++ ++ $append_trailer = $dtok; ++ if (!$dtok) ++ { ++ if (config_bool($res, 'bcm2708_fb') || ++ config_bool($res, 'brcm,bcm2835-mmc') || ++ config_bool($res, 'brcm,bcm2835-sdhost')) ++ { ++ $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); ++ $dtok ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); ++ $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); ++ $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); ++ $is_283x ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); ++ $is_283x ||= config_bool($res, 'brcm,bcm2835-pm-wdt'); ++ $append_trailer = 1; ++ } ++ else ++ { ++ print ("* This doesn't look like a Raspberry Pi kernel. In pass-through mode.\n"); ++ } ++ } ++} ++elsif (!$dtok) ++{ ++ print ("* Is this a valid kernel? In pass-through mode.\n"); ++} ++ ++if ($append_trailer) ++{ ++ printf("DT: %s\n", $dtok ? "y" : "n"); ++ printf("283x: %s\n", $is_283x ? "y" : "n"); ++ ++ my @atoms; ++ ++ push @atoms, [ $trailer_magic, pack('V', 0) ]; ++ push @atoms, [ 'KVer', $kver ]; ++ push @atoms, [ 'DTOK', pack('V', $dtok) ]; ++ push @atoms, [ '283x', pack('V', $is_283x) ]; ++ ++ $trailer = pack_trailer(\@atoms); ++ $atoms[0]->[1] = pack('V', length($trailer)); ++ ++ $trailer = pack_trailer(\@atoms); ++} ++ ++my $ofh; ++my $total_len = 0; ++ ++if ($out_file eq $kernel_file) ++{ ++ die "* Failed to open '$out_file' for append\n" ++ if (!open($ofh, '>>', $out_file)); ++ $total_len = tell($ofh); ++} ++else ++{ ++ die "* Failed to open '$kernel_file'\n" ++ if (!open(my $ifh, '<', $kernel_file)); ++ die "* Failed to create '$out_file'\n" ++ if (!open($ofh, '>', $out_file)); ++ ++ my $copybuf; ++ while (1) ++ { ++ my $bytes = sysread($ifh, $copybuf, 64*1024); ++ last if (!$bytes); ++ syswrite($ofh, $copybuf, $bytes); ++ $total_len += $bytes; ++ } ++ close($ifh); ++} ++ ++if ($trailer) ++{ ++ # Pad to word-alignment ++ syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3)); ++ syswrite($ofh, $trailer); ++} ++ ++close($ofh); ++ ++exit($trailer ? 0 : 1); ++ ++END { ++ unlink($tmpfile1) if ($tmpfile1); ++ unlink($tmpfile2) if ($tmpfile2); +} + + - static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) - { -@@ -70,7 +94,8 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - break; - default: - dev_err(codec->dev, -- "Failed to set WM8804 SYSCLK, unsupported samplerate\n"); -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); - } - - snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -@@ -96,6 +121,8 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - /* machine stream operations */ - static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { - .hw_params = snd_rpi_hifiberry_digi_hw_params, -+ .startup = snd_rpi_hifiberry_digi_startup, -+ .shutdown = snd_rpi_hifiberry_digi_shutdown, - }; - - static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { - -From fdcfdf08df6289445d33e8acaf68faa5f5b4923b Mon Sep 17 00:00:00 2001 -From: Joerg Hohensohn -Date: Sun, 1 Feb 2015 22:08:03 +0100 -Subject: [PATCH 068/216] bugfix for 32kHz sample rate, was missing - ---- - sound/soc/bcm/hifiberry_digi.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index a245995..a294a1b 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -80,6 +80,7 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - samplerate = params_rate(params); - - switch (samplerate) { -+ case 32000: - case 44100: - case 48000: - case 88200: - -From 601bc9883a6bf209e736d2b1cc5991176ed1abf3 Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 069/216] Update ds1307 driver for device-tree support - -Signed-off-by: Ryan Coe ---- - drivers/rtc/rtc-ds1307.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index 4ffabb3..c6789a7 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -1242,6 +1242,14 @@ static int ds1307_remove(struct i2c_client *client) - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id ds1307_of_match[] = { -+ { .compatible = "maxim,ds1307" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ds1307_of_match); -+#endif ++sub usage ++{ ++ print ("Usage: mkknlimg [--dtok] [--283x] \n"); ++ exit(1); ++} + - static struct i2c_driver ds1307_driver = { - .driver = { - .name = "rtc-ds1307", - -From c6e4ebd2dec4446f061cab8fa0a860e0fe7fd30a Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:26:03 -0700 -Subject: [PATCH 070/216] Add device-tree overlay for ds1307 - -Signed-off-by: Ryan Coe ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/ds1307-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/ds1307-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index c909f7b..7755a84 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -diff --git a/arch/arm/boot/dts/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -new file mode 100644 -index 0000000..7d27044 ---- /dev/null -+++ b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for DS1307 Real Time Clock -+/dts-v1/; -+/plugin/; ++sub try_extract ++{ ++ my ($knl, $tmp) = @_; + -+/ { -+ compatible = "brcm,bcm2708"; ++ my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`; + -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; ++ return undef if (!$ver); + -+ ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; ++ chomp($ver); ++ ++ my $res = { ''=>$ver }; ++ my $string_pattern = '^('.join('|', @wanted_strings).')$'; ++ ++ my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`; ++ foreach my $match (@matches) ++ { ++ chomp($match); ++ $res->{$match} = 1; ++ } ++ ++ my $config_pattern = '^('.join('|', @wanted_config_lines).')=(.*)$'; ++ my $cf1 = 'IKCFG_ST\037\213\010'; ++ my $cf2 = '0123456789'; ++ ++ my $pos = `tr "$cf1\n$cf2" "\n$cf2=" < "$knl" | grep -abo "^$cf2"`; ++ if ($pos) ++ { ++ $pos =~ s/:.*[\r\n]*$//s; ++ $pos += 8; ++ my $err = (system("tail -c+$pos \"$knl\" | zcat > $tmp 2> /dev/null") >> 8); ++ if (($err == 0) || ($err == 2)) ++ { ++ if (open(my $fh, '<', $tmp)) ++ { ++ while (my $line = <$fh>) ++ { ++ chomp($line); ++ $res->{$1} = $2 if ($line =~ /$config_pattern/); ++ } ++ ++ close($fh); ++ } ++ } ++ } ++ ++ return $res; ++} ++ ++ ++sub try_decompress ++{ ++ my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_; ++ ++ my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`; ++ if ($pos) ++ { ++ chomp($pos); ++ $pos = (split(/[\r\n]+/, $pos))[$idx]; ++ return undef if (!defined($pos)); ++ $pos =~ s/:.*[\r\n]*$//s; ++ my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null"; ++ my $err = (system($cmd) >> 8); ++ return undef if (($err != 0) && ($err != 2)); ++ ++ return try_extract($tmp2, $tmp1); ++ } ++ ++ return undef; ++} ++ ++sub pack_trailer ++{ ++ my ($atoms) = @_; ++ my $trailer = pack('VV', 0, 0); ++ for (my $i = $#$atoms; $i>=0; $i--) ++ { ++ my $atom = $atoms->[$i]; ++ $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]); ++ } ++ return $trailer; ++} ++ ++sub config_bool ++{ ++ my ($configs, $wanted) = @_; ++ my $val = $configs->{$wanted} || 'n'; ++ return (($val eq 'y') || ($val eq '1')); ++} -From 7abd2997600af8ee74045e490c6db3a41f716636 Mon Sep 17 00:00:00 2001 +From 780d72c0e43679ff58f9f3f005ef17a5fa79ee9f Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 071/216] BCM270x_DT: Add pwr_led, and the required "input" - trigger +Date: Fri, 5 Dec 2014 17:26:26 +0000 +Subject: [PATCH 25/77] fdt: Add support for the CONFIG_CMDLINE_EXTEND option -The "input" trigger makes the associated GPIO an input. This is to support -the Raspberry Pi PWR LED, which is driven by external hardware in normal use. - -N.B. pwr_led is not available on Model A or B boards. --- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 18 ++++- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 8 ++- - arch/arm/boot/dts/bcm2708.dtsi | 7 +- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 115 +++++++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 5 -- - drivers/leds/trigger/Kconfig | 7 ++ - drivers/leds/trigger/Makefile | 1 + - drivers/leds/trigger/ledtrig-input.c | 65 +++++++++++++++++ - 8 files changed, 213 insertions(+), 13 deletions(-) + drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index cde35c5d01..dd7fbfe 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -933,19 +933,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, + + /* Retrieve command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); +- if (p != NULL && l > 0) +- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else + * managed to set the command line, unless CONFIG_CMDLINE_FORCE + * is set in which case we override whatever was found earlier. ++ * ++ * However, it can be useful to be able to treat the default as ++ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. + */ ++ ((char *)data)[0] = '\0'; ++ + #ifdef CONFIG_CMDLINE +-#ifndef CONFIG_CMDLINE_FORCE +- if (!((char *)data)[0]) ++ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); ++ ++ if (p != NULL && l > 0) { ++#if defined(CONFIG_CMDLINE_EXTEND) ++ int len = strlen(data); ++ if (len > 0) { ++ strlcat(data, " ", COMMAND_LINE_SIZE); ++ len++; ++ } ++ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); ++#elif defined(CONFIG_CMDLINE_FORCE) ++ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); ++#else ++ /* Neither extend nor force - just override */ ++ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + #endif +- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); ++ } ++#else /* CONFIG_CMDLINE */ ++ if (p != NULL && l > 0) { ++ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + #endif /* CONFIG_CMDLINE */ + + pr_debug("Command line is: %s\n", (char*)data); + +From 7ff1afbc6732a16d87c5640be8fec1de73a39770 Mon Sep 17 00:00:00 2001 +From: notro +Date: Wed, 9 Jul 2014 14:46:08 +0200 +Subject: [PATCH 26/77] BCM2708: Add core Device Tree support + +Add the bare minimum needed to boot BCM2708 from a Device Tree. + +Signed-off-by: Noralf Tronnes + +BCM2708: DT: change 'axi' nodename to 'soc' + +Change DT node named 'axi' to 'soc' so it matches ARCH_BCM2835. +The VC4 bootloader fills in certain properties in the 'axi' subtree, +but since this is part of an upstreaming effort, the name is changed. + +Signed-off-by: Noralf Tronnes notro@tronnes.org + +BCM2708_DT: Correct length of the peripheral space +--- + arch/arm/boot/dts/Makefile | 27 ++ + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 140 ++++++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 130 ++++++ + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 18 + + arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 51 +++ + arch/arm/boot/dts/bcm2708.dtsi | 19 + + arch/arm/boot/dts/bcm2708_common.dtsi | 230 ++++++++++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 140 ++++++ + arch/arm/boot/dts/bcm2709.dtsi | 70 +++ + arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 45 +- + arch/arm/boot/dts/bcm2835-rpi-b.dts | 29 +- + arch/arm/boot/dts/bcm2835-rpi.dtsi | 97 +++- + arch/arm/boot/dts/bcm2835.dtsi | 45 +- + arch/arm/boot/dts/overlays/Makefile | 57 +++ + arch/arm/boot/dts/overlays/README | 493 +++++++++++++++++++++ + arch/arm/boot/dts/overlays/ads7846-overlay.dts | 83 ++++ + .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + + arch/arm/boot/dts/overlays/dht11-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 50 +++ + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 ++ + .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 ++ + .../dts/overlays/hifiberry-dacplus-overlay.dts | 39 ++ + .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 87 ++++ + arch/arm/boot/dts/overlays/hy28b-overlay.dts | 142 ++++++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 49 ++ + arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts | 13 + + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 39 ++ + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 +++ + .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 69 +++ + arch/arm/boot/dts/overlays/mmc-overlay.dts | 19 + + arch/arm/boot/dts/overlays/mz61581-overlay.dts | 109 +++++ + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 96 ++++ + .../dts/overlays/pitft28-resistive-overlay.dts | 115 +++++ + arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 34 ++ + arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 34 ++ + arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 82 ++++ + arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 78 ++++ + arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts | 18 + + arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts | 18 + + arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 216 +++++++++ + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 ++ + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 ++ + 45 files changed, 3316 insertions(+), 54 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts + create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi create mode 100644 arch/arm/boot/dts/bcm2709-rpi-2-b.dts - create mode 100644 drivers/leds/trigger/ledtrig-input.c + create mode 100644 arch/arm/boot/dts/bcm2709.dtsi + create mode 100644 arch/arm/boot/dts/overlays/Makefile + create mode 100644 arch/arm/boot/dts/overlays/README + create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/dht11-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-display-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 992736b..12de305 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1,5 +1,21 @@ + ifeq ($(CONFIG_OF),y) + ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb ++dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb ++ ++# Raspberry Pi ++ifeq ($(CONFIG_BCM2708_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_BCM2709_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_ARCH_BCM2835),y) ++ RPI_DT_OVERLAYS=y ++endif ++ + dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb + dtb-$(CONFIG_MACH_ASM9260) += \ +@@ -660,7 +676,18 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt6592-evb.dtb \ + mt8127-moose.dtb \ + mt8135-evbp1.dtb ++ ++targets += dtbs dtbs_install ++targets += $(dtb-y) ++ + endif + + always := $(dtb-y) + clean-files := *.dtb ++ ++# Enable fixups to support overlays on BCM2708 platforms ++ifeq ($(RPI_DT_OVERLAYS),y) ++ DTC_FLAGS ?= -@ ++endif ++ ++subdir-y += overlays diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 95f03ba..b409c2c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -83,8 +83,18 @@ - pinctrl-0 = <&i2s_pins>; - }; - --&act_led { -- gpios = <&gpio 47 0>; -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+ -+ pwr_led: pwr { -+ label = "led1"; -+ linux,default-trigger = "input"; -+ gpios = <&gpio 35 0>; -+ }; - }; - - / { -@@ -97,5 +107,9 @@ - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ pwr_led_gpio = <&pwr_led>,"gpios:4"; -+ pwr_led_activelow = <&pwr_led>,"gpios:8"; -+ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 0631f45..1ecd1a1 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -83,8 +83,12 @@ - pinctrl-0 = <&i2s_pins>; - }; - --&act_led { -- gpios = <&gpio 16 1>; -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 16 1>; -+ }; - }; - - / { -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index d879316..0713a1ed 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -79,11 +79,10 @@ - - leds: leds { - compatible = "gpio-leds"; -+ }; - -- act_led: act { -- label = "ACT"; -- linux,default-trigger = "mmc0"; -- }; -+ arm-pmu { -+ compatible = "arm,arm1176-pmu"; - }; - }; - -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000..46f4908 +index 0000000..0fa2210 --- /dev/null -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,115 @@ ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -0,0 +1,140 @@ +/dts-v1/; + -+/include/ "bcm2709.dtsi" ++/include/ "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; -+ model = "Raspberry Pi 2 Model B"; ++ compatible = "brcm,bcm2708"; ++ model = "Raspberry Pi Model B+"; + + aliases { + soc = &soc; @@ -124457,7 +118600,11 @@ index 0000000..46f4908 + gpio = &gpio; + intc = &intc; + leds = &leds; ++ audio = &audio; + sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; + }; + + sound: sound { @@ -124486,6 +118633,19 @@ index 0000000..46f4908 + }; +}; + ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; @@ -124541,10 +118701,14 @@ index 0000000..46f4908 + +/ { + __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; @@ -124553,24 +118717,8655 @@ index 0000000..46f4908 + pwr_led_gpio = <&pwr_led>,"gpios:4"; + pwr_led_activelow = <&pwr_led>,"gpios:8"; + pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts +new file mode 100644 +index 0000000..3fd49d0 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -0,0 +1,130 @@ ++/dts-v1/; ++ ++/include/ "bcm2708.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ model = "Raspberry Pi Model B"; ++ ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <28 29 30 31>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 16 1>; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +new file mode 100755 +index 0000000..238bd65 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -0,0 +1,18 @@ ++/dts-v1/; ++ ++/include/ "bcm2708-rpi-cm.dtsi" ++ ++/ { ++ model = "Raspberry Pi Compute Module"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi +new file mode 100644 +index 0000000..3da7d3b +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi +@@ -0,0 +1,51 @@ ++/include/ "bcm2708.dtsi" ++ ++/ { ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&audio { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +new file mode 100644 +index 0000000..0d47427 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708.dtsi +@@ -0,0 +1,19 @@ ++/include/ "bcm2708_common.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ model = "BCM2708"; ++ ++ chosen { ++ /* No padding required - the boot loader can do that. */ ++ bootargs = ""; ++ }; ++ ++ soc { ++ ranges = <0x7e000000 0x20000000 0x01000000>; ++ ++ arm-pmu { ++ compatible = "arm,arm1176-pmu"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi +new file mode 100644 +index 0000000..8caa234 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708_common.dtsi +@@ -0,0 +1,230 @@ ++/include/ "skeleton.dtsi" ++ ++/ { ++ interrupt-parent = <&intc>; ++ ++ /* Onboard audio */ ++ audio: audio { ++ compatible = "brcm,bcm2835-audio"; ++ brcm,pwm-channels = <8>; ++ status = "disabled"; ++ }; ++ ++ soc: soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ dma: dma@7e007000 { ++ compatible = "brcm,bcm2835-dma"; ++ reg = <0x7e007000 0xf00>; ++ interrupts = <1 16>, ++ <1 17>, ++ <1 18>, ++ <1 19>, ++ <1 20>, ++ <1 21>, ++ <1 22>, ++ <1 23>, ++ <1 24>, ++ <1 25>, ++ <1 26>, ++ <1 27>, ++ <1 28>; ++ ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ ++ intc: interrupt-controller { ++ compatible = "brcm,bcm2708-armctrl-ic"; ++ reg = <0x7e00b200 0x200>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ watchdog: watchdog@7e100000 { ++ compatible = "brcm,bcm2835-pm-wdt"; ++ reg = <0x7e100000 0x28>; ++ status = "disabled"; ++ }; ++ ++ random: rng@7e104000 { ++ compatible = "brcm,bcm2835-rng"; ++ reg = <0x7e104000 0x10>; ++ status = "disabled"; ++ }; ++ ++ mailbox: mailbox@7e00b800 { ++ compatible = "brcm,bcm2708-vcio"; ++ reg = <0x7e00b880 0x40>; ++ interrupts = <0 1>; ++ }; ++ ++ gpio: gpio { ++ compatible = "brcm,bcm2835-gpio"; ++ reg = <0x7e200000 0xb4>; ++ interrupts = <2 17>, <2 18>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; ++ reg = <0x7e300000 0x100>; ++ interrupts = <2 30>; ++ clocks = <&clk_mmc>; ++ dmas = <&dma 11>, ++ <&dma 11>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@7e201000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7e201000 0x1000>; ++ interrupts = <2 25>; ++ clocks = <&clk_uart0 &clk_apb_p>; ++ clock-names = "uartclk","apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; // For an explanation, see ++ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 ++ status = "disabled"; ++ }; ++ ++ i2s: i2s@7e203000 { ++ compatible = "brcm,bcm2708-i2s"; ++ reg = <0x7e203000 0x20>, ++ <0x7e101098 0x02>; ++ ++ //dmas = <&dma 2>, ++ // <&dma 3>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@7e204000 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7e204000 0x1000>; ++ interrupts = <2 22>; ++ clocks = <&clk_spi>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ /* the dma channels */ ++ dmas = <&dma 6>, <&dma 7>; ++ dma-names = "tx", "rx"; ++ /* the chipselects used - <0> means native GPIO ++ * add more gpios if necessary as <&gpio 6 1> ++ * (but do not forget to make them output!) ++ */ ++ cs-gpios = <0>, <0>; ++ }; ++ ++ i2c0: i2c@7e205000 { ++ compatible = "brcm,bcm2708-i2c"; ++ reg = <0x7e205000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clk_i2c>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@7e215040 { ++ compatible = "brcm,bcm2835-aux-uart", "ns16550"; ++ reg = <0x7e215040 0x40>; ++ interrupts = <1 29>; ++ clock-frequency = <500000000>; ++ reg-shift = <2>; ++ no-loopback-test; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@7e804000 { ++ compatible = "brcm,bcm2708-i2c"; ++ reg = <0x7e804000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clk_i2c>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usb: usb@7e980000 { ++ compatible = "brcm,bcm2708-usb"; ++ reg = <0x7e980000 0x10000>, ++ <0x7e006000 0x1000>; ++ interrupts = <2 0>, ++ <1 9>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ status = "disabled"; ++ }; ++ ++ vchiq: vchiq { ++ compatible = "brcm,bcm2835-vchiq"; ++ reg = <0x7e00b840 0xf>; ++ interrupts = <0 2>; ++ }; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2835-thermal"; ++ }; ++ }; ++ ++ clocks: clocks { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_mmc: clock@0 { ++ compatible = "fixed-clock"; ++ reg = <0>; ++ #clock-cells = <0>; ++ clock-output-names = "mmc"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_i2c: clock@1 { ++ compatible = "fixed-clock"; ++ reg = <1>; ++ #clock-cells = <0>; ++ clock-output-names = "i2c"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_spi: clock@2 { ++ compatible = "fixed-clock"; ++ reg = <2>; ++ #clock-cells = <0>; ++ clock-output-names = "spi"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_uart0: clock@3 { ++ compatible = "fixed-clock"; ++ reg = <3>; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <3000000>; ++ }; ++ ++ clk_apb_p: clock@4 { ++ compatible = "fixed-clock"; ++ reg = <4>; ++ #clock-cells = <0>; ++ clock-output-names = "apb_pclk"; ++ clock-frequency = <126000000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +new file mode 100644 +index 0000000..8aaaf1f +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -0,0 +1,140 @@ ++/dts-v1/; ++ ++/include/ "bcm2709.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2709"; ++ model = "Raspberry Pi 2 Model B"; ++ ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++ ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&gpio 35 0>; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; + }; +}; diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 15c7e65..34d2226 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi +new file mode 100644 +index 0000000..5e0b935 +--- /dev/null +++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -79,11 +79,6 @@ +@@ -0,0 +1,70 @@ ++/include/ "bcm2708_common.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2709"; ++ model = "BCM2709"; ++ ++ chosen { ++ /* No padding required - the boot loader can do that. */ ++ bootargs = ""; ++ }; ++ ++ soc { ++ ranges = <0x7e000000 0x3f000000 0x01000000>; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <3 9>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ clock-frequency = <19200000>; ++ interrupts = <3 0>, // PHYS_SECURE_PPI ++ <3 1>, // PHYS_NONSECURE_PPI ++ <3 3>, // VIRT_PPI ++ <3 2>; // HYP_PPI ++ always-on; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ v7_cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf00>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf01>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf02>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf03>; ++ clock-frequency = <800000000>; ++ }; ++ }; ++ ++ __overrides__ { ++ arm_freq = <&v7_cpu0>, "clock-frequency:0", ++ <&v7_cpu1>, "clock-frequency:0", ++ <&v7_cpu2>, "clock-frequency:0", ++ <&v7_cpu3>, "clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +index e479515..b0fb0e8 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +@@ -4,27 +4,40 @@ + / { + compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; + model = "Raspberry Pi Model B+"; ++}; ++ ++&gpio { ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; - leds: leds { - compatible = "gpio-leds"; +- leds { +- act { +- gpios = <&gpio 47 0>; +- }; ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&act_led { ++ gpios = <&gpio 47 0>; ++}; + +- pwr { +- label = "PWR"; +- gpios = <&gpio 35 0>; +- default-state = "keep"; +- linux,default-trigger = "default-on"; +- }; ++&leds { ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&gpio 35 0>; + }; + }; + +-&gpio { +- pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; + +- /* I2S interface */ +- i2s_alt0: i2s_alt0 { +- brcm,pins = <18 19 20 21>; +- brcm,function = <4>; /* alt0 */ ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; + }; + }; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts +index bafa46f..b867224 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts +@@ -5,19 +5,28 @@ + compatible = "raspberrypi,model-b", "brcm,bcm2835"; + model = "Raspberry Pi Model B"; + +- leds { +- act { +- gpios = <&gpio 16 1>; +- }; +- }; + }; + + &gpio { +- pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - -- act_led: act { -- label = "led0"; -- linux,default-trigger = "mmc0"; -- }; +- /* I2S interface */ +- i2s_alt2: i2s_alt2 { ++ i2s_pins: i2s { + brcm,pins = <28 29 30 31>; +- brcm,function = <6>; /* alt2 */ ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&act_led { ++ gpios = <&gpio 16 1>; ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; + }; + }; +diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi +index c706448..466f02b 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -1,51 +1,112 @@ + /include/ "bcm2835.dtsi" + + / { ++ /* This is left here in case u-boot needs it */ + memory { + reg = <0 0x10000000>; + }; + +- leds { ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ sound = &sound; ++ }; ++ ++ leds: leds { + compatible = "gpio-leds"; + +- act { +- label = "ACT"; +- default-state = "keep"; +- linux,default-trigger = "heartbeat"; ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; + }; + }; ++ ++ /* Onboard audio */ ++ audio: audio { ++ compatible = "brcm,bcm2835-audio"; ++ brcm,pwm-channels = <8>; ++ status = "disabled"; ++ }; ++ ++ /* External sound card */ ++ sound: sound { ++ }; + }; + + &gpio { +- pinctrl-names = "default"; ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; + +- gpioout: gpioout { +- brcm,pins = <6>; +- brcm,function = <1>; /* GPIO out */ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; + }; + +- alt0: alt0 { +- brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; +- brcm,function = <4>; /* alt0 */ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; + }; + +- alt3: alt3 { +- brcm,pins = <48 49 50 51 52 53>; +- brcm,function = <7>; /* alt3 */ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; + }; + }; + + &i2c0 { +- status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; + }; + + &i2c1 { +- status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; + }; + +-&sdhci { ++&mmc { + status = "okay"; + bus-width = <4>; + }; ++ ++&fb { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ audio = <&audio>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi +index 3342cb1..4b6dd65f 100644 +--- a/arch/arm/boot/dts/bcm2835.dtsi ++++ b/arch/arm/boot/dts/bcm2835.dtsi +@@ -6,14 +6,15 @@ + interrupt-parent = <&intc>; + + chosen { +- bootargs = "earlyprintk console=ttyAMA0"; ++ bootargs = ""; + }; + +- soc { ++ soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x7e000000 0x20000000 0x02000000>; ++ dma-ranges = <0x40000000 0x00000000 0x20000000>; + + timer@7e003000 { + compatible = "brcm,bcm2835-system-timer"; +@@ -50,16 +51,22 @@ + #interrupt-cells = <2>; }; +- watchdog@7e100000 { ++ watchdog: watchdog@7e100000 { + compatible = "brcm,bcm2835-pm-wdt"; + reg = <0x7e100000 0x28>; + }; + +- rng@7e104000 { ++ random: rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + }; + ++ mailbox: mailbox@7e00b800 { ++ compatible = "brcm,bcm2708-vcio"; ++ reg = <0x7e00b880 0x40>; ++ interrupts = <0 1>; ++ }; ++ + gpio: gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; +@@ -83,7 +90,7 @@ + #interrupt-cells = <2>; + }; + +- uart@7e201000 { ++ uart0: uart@7e201000 { + compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; + reg = <0x7e201000 0x1000>; + interrupts = <2 25>; +@@ -102,7 +109,7 @@ + status = "disabled"; + }; + +- spi: spi@7e204000 { ++ spi0: spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; +@@ -122,11 +129,14 @@ + status = "disabled"; + }; + +- sdhci: sdhci@7e300000 { +- compatible = "brcm,bcm2835-sdhci"; ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; + reg = <0x7e300000 0x100>; + interrupts = <2 30>; + clocks = <&clk_mmc>; ++ dmas = <&dma 11>, ++ <&dma 11>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -140,7 +150,7 @@ + status = "disabled"; + }; + +- usb@7e980000 { ++ usb: usb@7e980000 { + compatible = "brcm,bcm2835-usb"; + reg = <0x7e980000 0x10000>; + interrupts = <1 9>; +@@ -149,6 +159,21 @@ arm-pmu { + compatible = "arm,arm1176-pmu"; + }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ status = "disabled"; ++ }; ++ ++ vchiq: vchiq { ++ compatible = "brcm,bcm2835-vchiq"; ++ reg = <0x7e00b840 0xf>; ++ interrupts = <0 2>; ++ }; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2835-thermal"; ++ }; + }; + + clocks { +@@ -161,7 +186,7 @@ + reg = <0>; + #clock-cells = <0>; + clock-output-names = "mmc"; +- clock-frequency = <100000000>; ++ clock-frequency = <250000000>; + }; + + clk_i2c: clock@1 { +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +new file mode 100644 +index 0000000..6947556 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -0,0 +1,57 @@ ++ifeq ($(CONFIG_OF),y) ++ ++# Overlays for the Raspberry Pi platform ++ ++ifeq ($(CONFIG_BCM2708_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_BCM2709_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_ARCH_BCM2835),y) ++ RPI_DT_OVERLAYS=y ++endif ++ ++dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += dht11-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += i2s-mmap-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mcp2515-can0-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb ++ ++targets += dtbs dtbs_install ++targets += $(dtb-y) ++ ++endif ++ ++always := $(dtb-y) ++clean-files := *.dtb ++ ++# Enable fixups to support overlays on BCM2708 platforms ++ifeq ($(RPI_DT_OVERLAYS),y) ++ DTC_FLAGS ?= -@ ++endif +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +new file mode 100644 +index 0000000..3e08f98 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/README +@@ -0,0 +1,493 @@ ++Introduction ++============ ++ ++This directory contains Device Tree overlays. Device Tree makes it possible ++to support many hardware configurations with a single kernel and without the ++need to explicitly load or blacklist kernel modules. Note that this isn't a ++"pure" Device Tree configuration (c.f. MACH_BCM2835) - some on-board devices ++are still configured by the board support code, but the intention is to ++eventually reach that goal. ++ ++On Raspberry Pi, Device Tree usage is controlled from /boot/config.txt. By ++default, the Raspberry Pi kernel boots with device tree enabled. You can ++completely disable DT usage (for now) by adding: ++ ++ device_tree= ++ ++to your config.txt, which should cause your Pi to revert to the old way of ++doing things after a reboot. ++ ++In /boot you will find a .dtb for each base platform. This describes the ++hardware that is part of the Raspberry Pi board. The loader (start.elf and its ++siblings) selects the .dtb file appropriate for the platform by name, and reads ++it into memory. At this point, all of the optional interfaces (i2c, i2s, spi) ++are disabled, but they can be enabled using Device Tree parameters: ++ ++ dtparam=i2c=on,i2s=on,spi=on ++ ++However, this shouldn't be necessary in many use cases because loading an ++overlay that requires one of those interfaces will cause it to be enabled ++automatically, and it is advisable to only enable interfaces if they are ++needed. ++ ++Configuring additional, optional hardware is done using Device Tree overlays ++(see below). ++ ++raspi-config ++============ ++ ++The Advanced Options section of the raspi-config utility can enable and disable ++Device Tree use, as well as toggling the I2C and SPI interfaces. Note that it ++is possible to both enable an interface and blacklist the driver, if for some ++reason you should want to defer the loading. ++ ++Modules ++======= ++ ++As well as describing the hardware, Device Tree also gives enough information ++to allow suitable driver modules to be located and loaded, with the corollary ++that unneeded modules are not loaded. As a result it should be possible to ++remove lines from /etc/modules, and /etc/modprobe.d/raspi-blacklist.conf can ++have its contents deleted (or commented out). ++ ++Using Overlays ++============== ++ ++Overlays are loaded using the "dtoverlay" directive. As an example, consider the ++popular lirc-rpi module, the Linux Infrared Remote Control driver. In the ++pre-DT world this would be loaded from /etc/modules, with an explicit ++"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled, ++this becomes a line in config.txt: ++ ++ dtoverlay=lirc-rpi ++ ++This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By ++default it will use GPIOs 17 (out) and 18 (in), but this can be modified using ++DT parameters: ++ ++ dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13 ++ ++Parameters always have default values, although in some cases (e.g. "w1-gpio") ++it is necessary to provided multiple overlays in order to get the desired ++behaviour. See the list of overlays below for a description of the parameters and their defaults. ++ ++The Overlay and Parameter Reference ++=================================== ++ ++Name: ++Info: Configures the base Raspberry Pi hardware ++Load: ++Params: ++ audio Set to "on" to disable the onboard ALSA audio ++ interface (default "off") ++ ++ i2c_arm Set to "on" to enable the ARM's i2c interface ++ (default "off") ++ ++ i2c_vc Set to "on" to enable the i2c interface ++ usually reserved for the VideoCore processor ++ (default "off") ++ ++ i2c An alias for i2c_arm ++ ++ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface ++ (default "100000") ++ ++ i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface ++ (default "100000") ++ ++ i2c_baudrate An alias for i2c_arm_baudrate ++ ++ i2s Set to "on" to enable the i2s interface ++ (default "off") ++ ++ spi Set to "on" to enable the spi interfaces ++ (default "off") ++ ++ random Set to "on" to enable the hardware random ++ number generator (default "off") ++ ++ uart0 Set to "off" to disable uart0 (default "on") ++ ++ watchdog Set to "on" to enable the hardware watchdog ++ (default "off") ++ ++ act_led_trigger Choose which activity the LED tracks. ++ Use "heartbeat" for a nice load indicator. ++ (default "mmc") ++ ++ act_led_activelow Set to "on" to invert the sense of the LED ++ (default "off") ++ ++ act_led_gpio Set which GPIO to use for the activity LED ++ (in case you want to connect it to an external ++ device) ++ (default "16" on a non-Plus board, "47" on a ++ Plus or Pi 2) ++ ++ pwr_led_trigger ++ pwr_led_activelow ++ pwr_led_gpio ++ As for act_led_*, but using the PWR LED. ++ Not available on Model A/B boards. ++ ++ N.B. It is recommended to only enable those interfaces that are needed. ++ Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc ++ interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.) ++ Note also that i2c, i2c_arm and i2c_vc are aliases for the physical ++ interfaces i2c0 and i2c1. Use of the numeric variants is still possible ++ but deprecated because the ARM/VC assignments differ between board ++ revisions. The same board-specific mapping applies to i2c_baudrate, ++ and the other i2c baudrate parameters. ++ ++ ++Name: ads7846 ++Info: ADS7846 Touch controller ++Load: dtoverlay=ads7846,= ++Params: cs SPI bus Chip Select (default 1) ++ speed SPI bus speed (default 2Mhz, max 3.25MHz) ++ penirq GPIO used for PENIRQ. REQUIRED ++ penirq_pull Set GPIO pull (default 0=none, 2=pullup) ++ swapxy Swap x and y axis ++ xmin Minimum value on the X axis (default 0) ++ ymin Minimum value on the Y axis (default 0) ++ xmax Maximum value on the X axis (default 4095) ++ ymax Maximum value on the Y axis (default 4095) ++ pmin Minimum reported pressure value (default 0) ++ pmax Maximum reported pressure value (default 65535) ++ xohms Touchpanel sensitivity (X-plate resistance) ++ (default 400) ++ ++ penirq is required and usually xohms (60-100) has to be set as well. ++ Apart from that, pmax (255) and swapxy are also common. ++ The rest of the calibration can be done with xinput-calibrator. ++ See: github.com/notro/fbtft/wiki/FBTFT-on-Raspian ++ Device Tree binding document: ++ www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt ++ ++ ++Name: bmp085_i2c-sensor ++Info: Configures the BMP085/BMP180 digital barometric pressure and temperature ++ sensors from Bosch Sensortec ++Load: dtoverlay=bmp085_i2c-sensor ++Params: ++ ++ ++[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++Name: enc28j60 ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) ++Load: dtoverlay=enc28j60,= ++Params: int_pin GPIO used for INT (default 25) ++ ++ speed SPI bus speed (default 12000000) ++ ++ ++Name: hifiberry-amp ++Info: Configures the HifiBerry Amp and Amp+ audio cards ++Load: dtoverlay=hifiberry-amp ++Params: ++ ++ ++Name: hifiberry-dac ++Info: Configures the HifiBerry DAC audio card ++Load: dtoverlay=hifiberry-dac ++Params: ++ ++ ++Name: hifiberry-dacplus ++Info: Configures the HifiBerry DAC+ audio card ++Load: dtoverlay=hifiberry-dacplus ++Params: ++ ++ ++Name: hifiberry-digi ++Info: Configures the HifiBerry Digi audio card ++Load: dtoverlay=hifiberry-digi ++Params: ++ ++ ++Name: hy28a ++Info: HY28A - 2.8" TFT LCD Display Module by HAOYU Electronics ++ Default values match Texy's display shield ++Load: dtoverlay=hy28a,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ resetgpio GPIO used to reset controller ++ ++ ledgpio GPIO used to control backlight ++ ++ ++Name: hy28b ++Info: HY28B - 2.8" TFT LCD Display Module by HAOYU Electronics ++ Default values match Texy's display shield ++Load: dtoverlay=hy28b,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ resetgpio GPIO used to reset controller ++ ++ ledgpio GPIO used to control backlight ++ ++ ++Name: i2c-rtc ++Info: Adds support for a number of I2C Real Time Clock devices ++Load: dtoverlay=i2c-rtc, ++Params: ds1307 Select the DS1307 device ++ ++ ds3231 Select the DS3231 device ++ ++ pcf2127 Select the PCF2127 device ++ ++ pcf8523 Select the PCF8523 device ++ ++ pcf8563 Select the PCF8563 device ++ ++ ++Name: iqaudio-dac ++Info: Configures the IQaudio DAC audio card ++Load: dtoverlay=iqaudio-dac ++Params: ++ ++ ++Name: iqaudio-dacplus ++Info: Configures the IQaudio DAC+ audio card ++Load: dtoverlay=iqaudio-dacplus ++Params: ++ ++ ++Name: lirc-rpi ++Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi) ++ Consult the module documentation for more details. ++Load: dtoverlay=lirc-rpi,=,... ++Params: gpio_out_pin GPIO for output (default "17") ++ ++ gpio_in_pin GPIO for input (default "18") ++ ++ gpio_in_pull Pull up/down/off on the input pin ++ (default "down") ++ ++ sense Override the IR receive auto-detection logic: ++ "1" = force active high ++ "0" = force active low ++ "-1" = use auto-detection ++ (default "-1") ++ ++ softcarrier Turn the software carrier "on" or "off" ++ (default "on") ++ ++ invert "on" = invert the output pin (default "off") ++ ++ debug "on" = enable additional debug messages ++ (default "off") ++ ++ ++Name: mcp2515-can0 ++Info: Configures the MCP2515 CAN controller ++Load: dtoverlay=mcp2515-can0,= ++Params: oscillator Clock frequency for the CAN controller (Hz) ++ ++ spimaxfrequency Maximum SPI frequence (Hz) ++ ++ interrupt GPIO for interrupt signal ++ ++ ++Name: mmc ++Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock ++Load: dtoverlay=mmc,= ++Params: overclock_50 Clock (in MHz) to use when the MMC framework ++ requests 50MHz ++ force_pio Disable DMA support ++ ++ ++Name: mz61581 ++Info: MZ61581 display by Tontec ++Load: dtoverlay=mz61581,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++[ The pcf8523-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++[ The pcf8563-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++Name: piscreen ++Info: PiScreen display by OzzMaker.com ++Load: dtoverlay=piscreen,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++Name: pitft28-resistive ++Info: Adafruit PiTFT 2.8" resistive touch screen ++Load: dtoverlay=pitft28-resistive,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ ++Name: pps-gpio ++Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). ++Load: dtoverlay=pps-gpio,= ++Params: gpiopin Input GPIO (default "18") ++ ++ ++Name: rpi-dac ++Info: Configures the RPi DAC audio card ++Load: dtoverlay=rpi-dac ++Params: ++ ++ ++Name: rpi-display ++Info: RPi-Display - 2.8" Touch Display by Watterott ++Load: dtoverlay=rpi-display,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++Name: rpi-proto ++Info: Configures the RPi Proto audio card ++Load: dtoverlay=rpi-proto ++Params: ++ ++ ++Name: sdhost ++Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock ++Load: dtoverlay=sdhost,= ++Params: overclock_50 Clock (in MHz) to use when the MMC framework ++ requests 50MHz ++ force_pio Disable DMA support ++ ++ ++Name: spi-bcm2708 ++Info: Selects the bcm2708-spi SPI driver ++Load: dtoverlay=spi-bcm2708 ++Params: ++ ++ ++Name: spi-bcm2835 ++Info: Selects the bcm2835-spi SPI driver ++Load: dtoverlay=spi-bcm2835 ++Params: ++ ++ ++Name: tinylcd35 ++Info: 3.5" Color TFT Display by www.tinylcd.com ++ Options: Touch, RTC, keypad ++Load: dtoverlay=tinylcd35,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ touch Enable touch panel ++ ++ touchgpio Touch controller IRQ GPIO ++ ++ xohms Touchpanel: Resistance of X-plate in ohms ++ ++ rtc-pcf PCF8563 Real Time Clock ++ ++ rtc-ds DS1307 Real Time Clock ++ ++ keypad Enable keypad ++ ++ Examples: ++ Display with touchpanel, PCF8563 RTC and keypad: ++ dtoverlay=tinylcd35,touch,rtc-pcf,keypad ++ Old touch display: ++ dtoverlay=tinylcd35,touch,touchgpio=3 ++ ++ ++Name: w1-gpio ++Info: Configures the w1-gpio Onewire interface module. ++ Use this overlay if you *don't* need a GPIO to drive an external pullup. ++Load: dtoverlay=w1-gpio,= ++Params: gpiopin GPIO for I/O (default "4") ++ ++ pullup Non-zero, "on", or "y" to enable the parasitic ++ power (2-wire, power-on-data) feature ++ ++ ++Name: w1-gpio-pullup ++Info: Configures the w1-gpio Onewire interface module. ++ Use this overlay if you *do* need a GPIO to drive an external pullup. ++Load: dtoverlay=w1-gpio-pullup,=,... ++Params: gpiopin GPIO for I/O (default "4") ++ ++ pullup Non-zero, "on", or "y" to enable the parasitic ++ power (2-wire, power-on-data) feature ++ ++ extpullup GPIO for external pullup (default "5") ++ ++ ++Troubleshooting ++=============== ++ ++If you are experiencing problems that you think are DT-related, enable DT ++diagnostic output by adding this to /boot/config.txt: ++ ++ dtdebug=on ++ ++and rebooting. Then run: ++ ++ sudo vcdbg log msg ++ ++and look for relevant messages. ++ ++Further reading ++=============== ++ ++This is only meant to be a quick introduction to the subject of Device Tree on ++Raspberry Pi. There is a more complete explanation here: ++ ++http://www.raspberrypi.org/documentation/configuration/device-tree.md +diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts +new file mode 100644 +index 0000000..6a92cd1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts +@@ -0,0 +1,83 @@ ++/* ++ * Generic Device Tree overlay for the ADS7846 touch controller ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ ads7846_pins: ads7846_pins { ++ brcm,pins = <255>; /* illegal default value */ ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ads7846: ads7846@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ads7846_pins>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <255 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 255 0>; ++ ++ /* driver defaults */ ++ ti,x-min = /bits/ 16 <0>; ++ ti,y-min = /bits/ 16 <0>; ++ ti,x-max = /bits/ 16 <0x0FFF>; ++ ti,y-max = /bits/ 16 <0x0FFF>; ++ ti,pressure-min = /bits/ 16 <0>; ++ ti,pressure-max = /bits/ 16 <0xFFFF>; ++ ti,x-plate-ohms = /bits/ 16 <400>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ cs = <&ads7846>,"reg:0"; ++ speed = <&ads7846>,"spi-max-frequency:0"; ++ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ ++ <&ads7846>,"interrupts:0", ++ <&ads7846>,"pendown-gpio:4"; ++ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; ++ swapxy = <&ads7846>,"ti,swap-xy?"; ++ xmin = <&ads7846>,"ti,x-min;0"; ++ ymin = <&ads7846>,"ti,y-min;0"; ++ xmax = <&ads7846>,"ti,x-max;0"; ++ ymax = <&ads7846>,"ti,y-max;0"; ++ pmin = <&ads7846>,"ti,pressure-min;0"; ++ pmax = <&ads7846>,"ti,pressure-max;0"; ++ xohms = <&ads7846>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts +new file mode 100644 +index 0000000..b830bf2 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts +@@ -0,0 +1,23 @@ ++// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/dht11-overlay.dts b/arch/arm/boot/dts/overlays/dht11-overlay.dts +new file mode 100644 +index 0000000..9bf67fd +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts +@@ -0,0 +1,39 @@ ++/* ++ * Overlay for the DHT11/21/22 humidity/temperature sensor modules. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ dht11: dht11@0 { ++ compatible = "dht11"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dht11_pins>; ++ gpios = <&gpio 4 0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ dht11_pins: dht11_pins { ++ brcm,pins = <4>; ++ brcm,function = <0>; // in ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&dht11_pins>,"brcm,pins:0", ++ <&dht11>,"gpios:4"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts +new file mode 100644 +index 0000000..8fae869 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts +@@ -0,0 +1,50 @@ ++// Overlay for the Microchip ENC28J60 Ethernet Controller ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ eth1: enc28j60@0{ ++ compatible = "microchip,enc28j60"; ++ reg = <0>; /* CE0 */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð1_pins>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 0x2>; /* falling edge */ ++ spi-max-frequency = <12000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ eth1_pins: eth1_pins { ++ brcm,pins = <25>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <ð1>, "interrupts:0", ++ <ð1_pins>, "brcm,pins:0"; ++ speed = <ð1>, "spi-max-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +new file mode 100644 +index 0000000..2c81448 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry Amp/Amp+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-amp"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ tas5713@1b { ++ #sound-dai-cells = <0>; ++ compatible = "ti,tas5713"; ++ reg = <0x1b>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +new file mode 100644 +index 0000000..5e7633a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for HiFiBerry DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +new file mode 100644 +index 0000000..deb9c625 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry DAC+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-dacplus"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4d { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4d>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +new file mode 100644 +index 0000000..d0e0d8a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry Digi ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-digi"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8804@3b { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hy28a-overlay.dts b/arch/arm/boot/dts/overlays/hy28a-overlay.dts +new file mode 100644 +index 0000000..3cd3083 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts +@@ -0,0 +1,87 @@ ++/* ++ * Device Tree overlay for HY28A display ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ hy28a_pins: hy28a_pins { ++ brcm,pins = <17 25 18>; ++ brcm,function = <0 1 1>; /* in out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hy28a: hy28a@0{ ++ compatible = "ilitek,ili9320"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hy28a_pins>; ++ ++ spi-max-frequency = <32000000>; ++ spi-cpol; ++ spi-cpha; ++ rotate = <270>; ++ bgr; ++ fps = <50>; ++ buswidth = <8>; ++ startbyte = <0x70>; ++ reset-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ }; ++ ++ hy28a_ts: hy28a-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&hy28a>,"spi-max-frequency:0"; ++ rotate = <&hy28a>,"rotate:0"; ++ fps = <&hy28a>,"fps:0"; ++ debug = <&hy28a>,"debug:0"; ++ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; ++ resetgpio = <&hy28a>,"reset-gpios:4", ++ <&hy28a_pins>, "brcm,pins:1"; ++ ledgpio = <&hy28a>,"led-gpios:4", ++ <&hy28a_pins>, "brcm,pins:2"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hy28b-overlay.dts b/arch/arm/boot/dts/overlays/hy28b-overlay.dts +new file mode 100644 +index 0000000..f774c4a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts +@@ -0,0 +1,142 @@ ++/* ++ * Device Tree overlay for HY28b display shield by Texy ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ hy28b_pins: hy28b_pins { ++ brcm,pins = <17 25 18>; ++ brcm,function = <0 1 1>; /* in out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hy28b: hy28b@0{ ++ compatible = "ilitek,ili9325"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hy28b_pins>; ++ ++ spi-max-frequency = <48000000>; ++ spi-cpol; ++ spi-cpha; ++ rotate = <270>; ++ bgr; ++ fps = <50>; ++ buswidth = <8>; ++ startbyte = <0x70>; ++ reset-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 1>; ++ ++ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; ++ ++ init = <0x10000e7 0x0010 ++ 0x1000000 0x0001 ++ 0x1000001 0x0100 ++ 0x1000002 0x0700 ++ 0x1000003 0x1030 ++ 0x1000004 0x0000 ++ 0x1000008 0x0207 ++ 0x1000009 0x0000 ++ 0x100000a 0x0000 ++ 0x100000c 0x0001 ++ 0x100000d 0x0000 ++ 0x100000f 0x0000 ++ 0x1000010 0x0000 ++ 0x1000011 0x0007 ++ 0x1000012 0x0000 ++ 0x1000013 0x0000 ++ 0x2000032 ++ 0x1000010 0x1590 ++ 0x1000011 0x0227 ++ 0x2000032 ++ 0x1000012 0x009c ++ 0x2000032 ++ 0x1000013 0x1900 ++ 0x1000029 0x0023 ++ 0x100002b 0x000e ++ 0x2000032 ++ 0x1000020 0x0000 ++ 0x1000021 0x0000 ++ 0x2000032 ++ 0x1000050 0x0000 ++ 0x1000051 0x00ef ++ 0x1000052 0x0000 ++ 0x1000053 0x013f ++ 0x1000060 0xa700 ++ 0x1000061 0x0001 ++ 0x100006a 0x0000 ++ 0x1000080 0x0000 ++ 0x1000081 0x0000 ++ 0x1000082 0x0000 ++ 0x1000083 0x0000 ++ 0x1000084 0x0000 ++ 0x1000085 0x0000 ++ 0x1000090 0x0010 ++ 0x1000092 0x0000 ++ 0x1000093 0x0003 ++ 0x1000095 0x0110 ++ 0x1000097 0x0000 ++ 0x1000098 0x0000 ++ 0x1000007 0x0133 ++ 0x1000020 0x0000 ++ 0x1000021 0x0000 ++ 0x2000064>; ++ debug = <0>; ++ }; ++ ++ hy28b_ts: hy28b-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&hy28b>,"spi-max-frequency:0"; ++ rotate = <&hy28b>,"rotate:0"; ++ fps = <&hy28b>,"fps:0"; ++ debug = <&hy28b>,"debug:0"; ++ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; ++ resetgpio = <&hy28b>,"reset-gpios:4", ++ <&hy28b_pins>, "brcm,pins:1"; ++ ledgpio = <&hy28b>,"led-gpios:4", ++ <&hy28b_pins>, "brcm,pins:2"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +new file mode 100644 +index 0000000..6bccfdc +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +@@ -0,0 +1,49 @@ ++// Definitions for several I2C based Real Time Clocks ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ds1307: ds1307@68 { ++ compatible = "maxim,ds1307"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ ds3231: ds3231@68 { ++ compatible = "maxim,ds3231"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ pcf2127: pcf2127@51 { ++ compatible = "nxp,pcf2127"; ++ reg = <0x51>; ++ status = "disable"; ++ }; ++ pcf8523: pcf8523@68 { ++ compatible = "nxp,pcf8523"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ pcf8563: pcf8563@51 { ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ status = "disable"; ++ }; ++ }; ++ }; ++ __overrides__ { ++ ds1307 = <&ds1307>,"status"; ++ ds3231 = <&ds3231>,"status"; ++ pcf2127 = <&pcf2127>,"status"; ++ pcf8523 = <&pcf8523>,"status"; ++ pcf8563 = <&pcf8563>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts b/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts +new file mode 100644 +index 0000000..a11160a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ brcm,enable-mmap; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +new file mode 100644 +index 0000000..ea8173e +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for IQaudIO DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "iqaudio,iqaudio-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4c>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +new file mode 100644 +index 0000000..735d8ab +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for IQaudIO DAC+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "iqaudio,iqaudio-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4c>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts +new file mode 100644 +index 0000000..7d5d82b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts +@@ -0,0 +1,57 @@ ++// Definitions for lirc-rpi module ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ lirc_rpi: lirc_rpi { ++ compatible = "rpi,lirc-rpi"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lirc_pins>; ++ status = "okay"; ++ ++ // Override autodetection of IR receiver circuit ++ // (0 = active high, 1 = active low, -1 = no override ) ++ rpi,sense = <0xffffffff>; ++ ++ // Software carrier ++ // (0 = off, 1 = on) ++ rpi,softcarrier = <1>; ++ ++ // Invert output ++ // (0 = off, 1 = on) ++ rpi,invert = <0>; ++ ++ // Enable debugging messages ++ // (0 = off, 1 = on) ++ rpi,debug = <0>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ lirc_pins: lirc_pins { ++ brcm,pins = <17 18>; ++ brcm,function = <1 0>; // out in ++ brcm,pull = <0 1>; // off down ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; ++ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; ++ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; ++ ++ sense = <&lirc_rpi>,"rpi,sense:0"; ++ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; ++ invert = <&lirc_rpi>,"rpi,invert:0"; ++ debug = <&lirc_rpi>,"rpi,debug:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts +new file mode 100755 +index 0000000..398d59c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts +@@ -0,0 +1,69 @@ ++/* ++ * Device tree overlay for mcp251x/can0 on spi0.0 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* disable spi-dev for spi0.0 */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ spidev@0{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ /* the interrupt pin of the can-controller */ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ can0_pins: can0_pins { ++ brcm,pins = <25>; ++ brcm,function = <0>; /* input */ ++ }; ++ }; ++ }; ++ ++ /* the clock/oscillator of the can-controller */ ++ fragment@2 { ++ target-path = "/clocks"; ++ __overlay__ { ++ /* external oscillator of mcp2515 on SPI0.0 */ ++ can0_osc: can0_osc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ /* the spi config of the can-controller itself binding everything together */ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ can0: mcp2515@0 { ++ reg = <0>; ++ compatible = "microchip,mcp2515"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&can0_pins>; ++ spi-max-frequency = <10000000>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 0x2>; ++ clocks = <&can0_osc>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ oscillator = <&can0_osc>,"clock-frequency:0"; ++ spimaxfrequency = <&can0>,"spi-max-frequency:0"; ++ interrupt = <&can0_pins>,"brcm,pins:0",<&can0>,"interrupts:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts +new file mode 100644 +index 0000000..0a37cf4 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts +@@ -0,0 +1,19 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&mmc>; ++ ++ __overlay__ { ++ brcm,overclock-50 = <0>; ++ }; ++ }; ++ ++ __overrides__ { ++ overclock_50 = <&mmc>,"brcm,overclock-50:0"; ++ force_pio = <&mmc>,"brcm,force-pio?"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mz61581-overlay.dts b/arch/arm/boot/dts/overlays/mz61581-overlay.dts +new file mode 100644 +index 0000000..c06fe12 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts +@@ -0,0 +1,109 @@ ++/* ++ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ mz61581_pins: mz61581_pins { ++ brcm,pins = <4 15 18 25>; ++ brcm,function = <0 1 1 1>; /* in out out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mz61581: mz61581@0{ ++ compatible = "samsung,s6d02a1"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mz61581_pins>; ++ ++ spi-max-frequency = <128000000>; ++ spi-cpol; ++ spi-cpha; ++ ++ width = <320>; ++ height = <480>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ ++ reset-gpios = <&gpio 15 0>; ++ dc-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 0>; ++ ++ init = <0x10000b0 00 ++ 0x1000011 ++ 0x20000ff ++ 0x10000b3 0x02 0x00 0x00 0x00 ++ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 ++ 0x10000c1 0x08 0x16 0x08 0x08 ++ 0x10000c4 0x11 0x07 0x03 0x03 ++ 0x10000c6 0x00 ++ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 ++ 0x1000035 0x00 ++ 0x1000036 0xa0 ++ 0x100003a 0x55 ++ 0x1000044 0x00 0x01 ++ 0x10000d0 0x07 0x07 0x1d 0x03 ++ 0x10000d1 0x03 0x30 0x10 ++ 0x10000d2 0x03 0x14 0x04 ++ 0x1000029 ++ 0x100002c>; ++ ++ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ ++ debug = <3>; ++ }; ++ ++ mz61581_ts: mz61581_ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <4 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 4 0>; ++ ++ ti,x-plate-ohms = /bits/ 16 <60>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&mz61581>, "spi-max-frequency:0"; ++ rotate = <&mz61581>, "rotate:0"; ++ fps = <&mz61581>, "fps:0"; ++ debug = <&mz61581>, "debug:0"; ++ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts +new file mode 100644 +index 0000000..ba4ad33 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts +@@ -0,0 +1,96 @@ ++/* ++ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ piscreen_pins: piscreen_pins { ++ brcm,pins = <17 25 24 22>; ++ brcm,function = <0 1 1 1>; /* in out out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ piscreen: piscreen@0{ ++ compatible = "ilitek,ili9486"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&piscreen_pins>; ++ ++ spi-max-frequency = <24000000>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ regwidth = <16>; ++ reset-gpios = <&gpio 25 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 22 1>; ++ debug = <0>; ++ ++ init = <0x10000b0 0x00 ++ 0x1000011 ++ 0x20000ff ++ 0x100003a 0x55 ++ 0x1000036 0x28 ++ 0x10000c2 0x44 ++ 0x10000c5 0x00 0x00 0x00 0x00 ++ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 ++ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 ++ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 ++ 0x1000011 ++ 0x1000029>; ++ }; ++ ++ piscreen_ts: piscreen-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,swap-xy; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&piscreen>,"spi-max-frequency:0"; ++ rotate = <&piscreen>,"rotate:0"; ++ fps = <&piscreen>,"fps:0"; ++ debug = <&piscreen>,"debug:0"; ++ xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts +new file mode 100644 +index 0000000..d506eae +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts +@@ -0,0 +1,115 @@ ++/* ++ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pitft_pins: pitft_pins { ++ brcm,pins = <24 25>; ++ brcm,function = <0 1>; /* in out */ ++ brcm,pull = <2 0>; /* pullup none */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pitft: pitft@0{ ++ compatible = "ilitek,ili9340"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pitft_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <90>; ++ fps = <25>; ++ bgr; ++ buswidth = <8>; ++ dc-gpios = <&gpio 25 0>; ++ debug = <0>; ++ }; ++ ++ pitft_ts@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stmpe610"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ ++ interrupts = <24 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ interrupt-controller; ++ ++ stmpe_touchscreen { ++ compatible = "st,stmpe-ts"; ++ st,sample-time = <4>; ++ st,mod-12b = <1>; ++ st,ref-sel = <0>; ++ st,adc-freq = <2>; ++ st,ave-ctrl = <3>; ++ st,touch-det-delay = <4>; ++ st,settling = <2>; ++ st,fraction-z = <7>; ++ st,i-drive = <0>; ++ }; ++ ++ stmpe_gpio: stmpe_gpio { ++ #gpio-cells = <2>; ++ compatible = "st,stmpe-gpio"; ++ /* ++ * only GPIO2 is wired/available ++ * and it is wired to the backlight ++ */ ++ st,norequest-mask = <0x7b>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/soc"; ++ __overlay__ { ++ backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&stmpe_gpio 2 0>; ++ default-on; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&pitft>,"spi-max-frequency:0"; ++ rotate = <&pitft>,"rotate:0"; ++ fps = <&pitft>,"fps:0"; ++ debug = <&pitft>,"debug:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts +new file mode 100644 +index 0000000..40bf0e1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ pps: pps { ++ compatible = "pps-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pps_pins>; ++ gpios = <&gpio 18 0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pps_pins: pps_pins { ++ brcm,pins = <18>; ++ brcm,function = <0>; // in ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&pps>,"gpios:4", ++ <&pps_pins>,"brcm,pins:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts +new file mode 100644 +index 0000000..7fc6ac9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for RPi DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "rpi,rpi-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ pcm1794a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm1794a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts +new file mode 100644 +index 0000000..a8fa974 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts +@@ -0,0 +1,82 @@ ++/* ++ * Device Tree overlay for rpi-display by Watterott ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ rpi_display_pins: rpi_display_pins { ++ brcm,pins = <18 23 24 25>; ++ brcm,function = <1 1 1 0>; /* out out out in */ ++ brcm,pull = <0 0 0 2>; /* - - - up */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rpidisplay: rpi-display@0{ ++ compatible = "ilitek,ili9341"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rpi_display_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ reset-gpios = <&gpio 23 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ }; ++ ++ rpidisplay_ts: rpi-display-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <25 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 25 0>; ++ ti,x-plate-ohms = /bits/ 16 <60>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&rpidisplay>,"spi-max-frequency:0"; ++ rotate = <&rpidisplay>,"rotate:0"; ++ fps = <&rpidisplay>,"fps:0"; ++ debug = <&rpidisplay>,"debug:0"; ++ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts +new file mode 100644 +index 0000000..2029930 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for Rpi-Proto ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "rpi,rpi-proto"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8731@1a { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8731"; ++ reg = <0x1a>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +new file mode 100644 +index 0000000..8fb28e9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -0,0 +1,78 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&soc>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sdhost: sdhost@7e202000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7e202000 0x100>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdhost_pins>; ++ interrupts = <2 24>; ++ clocks = <&clk_sdhost>; ++ dmas = <&dma 13>, ++ <&dma 13>; ++ dma-names = "tx", "rx"; ++ brcm,delay-after-stop = <0>; ++ brcm,overclock-50 = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&clocks>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_sdhost: sdhost { ++ compatible = "fixed-clock"; ++ reg = <0>; ++ #clock-cells = <0>; ++ clock-output-names = "sdhost"; ++ clock-frequency = <250000000>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&gpio>; ++ __overlay__ { ++ sdhost_pins: sdhost_pins { ++ brcm,pins = <48 49 50 51 52 53>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&mmc>; ++ __overlay__ { ++ /* Find a way to disable the other driver */ ++ compatible = ""; ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/__overrides__"; ++ __overlay__ { ++ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; ++ }; ++ }; ++ ++ __overrides__ { ++ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; ++ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; ++ force_pio = <&sdhost>,"brcm,force-pio?"; ++ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts +new file mode 100644 +index 0000000..e378ef1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts +@@ -0,0 +1,18 @@ ++/* ++ * Device tree overlay for spi-bcm2835 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ compatible = "brcm,bcm2708-spi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts +new file mode 100644 +index 0000000..fc1e39b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts +@@ -0,0 +1,18 @@ ++/* ++ * Device tree overlay for spi-bcm2835 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ compatible = "brcm,bcm2835-spi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts +new file mode 100644 +index 0000000..f7102c8 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts +@@ -0,0 +1,216 @@ ++/* ++ * tinylcd35-overlay.dts ++ * ++ * ------------------------------------------------- ++ * www.tinlylcd.com ++ * ------------------------------------------------- ++ * Device---Driver-----BUS GPIO's ++ * display tinylcd35 spi0.0 25 24 18 ++ * touch ads7846 spi0.1 5 ++ * rtc ds1307 i2c1-0068 ++ * rtc pcf8563 i2c1-0051 ++ * keypad gpio-keys --------- 17 22 27 23 28 ++ * ++ * ++ * TinyLCD.com 3.5 inch TFT ++ * ++ * Version 001 ++ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework ++ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ tinylcd35_pins: tinylcd35_pins { ++ brcm,pins = <25 24 18>; ++ brcm,function = <1>; /* out */ ++ }; ++ tinylcd35_ts_pins: tinylcd35_ts_pins { ++ brcm,pins = <5>; ++ brcm,function = <0>; /* in */ ++ }; ++ keypad_pins: keypad_pins { ++ brcm,pins = <4 17 22 23 27>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <1>; /* down */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tinylcd35: tinylcd35@0{ ++ compatible = "neosec,tinylcd"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&tinylcd35_pins>, ++ <&tinylcd35_ts_pins>; ++ ++ spi-max-frequency = <48000000>; ++ rotate = <270>; ++ fps = <20>; ++ bgr; ++ buswidth = <8>; ++ reset-gpios = <&gpio 25 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ ++ init = <0x10000B0 0x80 ++ 0x10000C0 0x0A 0x0A ++ 0x10000C1 0x01 0x01 ++ 0x10000C2 0x33 ++ 0x10000C5 0x00 0x42 0x80 ++ 0x10000B1 0xD0 0x11 ++ 0x10000B4 0x02 ++ 0x10000B6 0x00 0x22 0x3B ++ 0x10000B7 0x07 ++ 0x1000036 0x58 ++ 0x10000F0 0x36 0xA5 0xD3 ++ 0x10000E5 0x80 ++ 0x10000E5 0x01 ++ 0x10000B3 0x00 ++ 0x10000E5 0x00 ++ 0x10000F0 0x36 0xA5 0x53 ++ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 ++ 0x100003A 0x55 ++ 0x1000011 ++ 0x2000001 ++ 0x1000029>; ++ }; ++ ++ tinylcd35_ts: tinylcd35_ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ status = "disabled"; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <5 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 5 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ ++ /* RTC */ ++ ++ fragment@3 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pcf8563: pcf8563@51 { ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ds1307: ds1307@68 { ++ compatible = "maxim,ds1307"; ++ reg = <0x68>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ /* ++ * Values for input event code is found under the ++ * 'Keys and buttons' heading in include/uapi/linux/input.h ++ */ ++ fragment@5 { ++ target-path = "/soc"; ++ __overlay__ { ++ keypad: keypad { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&keypad_pins>; ++ status = "disabled"; ++ autorepeat; ++ ++ button@17 { ++ label = "GPIO KEY_UP"; ++ linux,code = <103>; ++ gpios = <&gpio 17 0>; ++ }; ++ button@22 { ++ label = "GPIO KEY_DOWN"; ++ linux,code = <108>; ++ gpios = <&gpio 22 0>; ++ }; ++ button@27 { ++ label = "GPIO KEY_LEFT"; ++ linux,code = <105>; ++ gpios = <&gpio 27 0>; ++ }; ++ button@23 { ++ label = "GPIO KEY_RIGHT"; ++ linux,code = <106>; ++ gpios = <&gpio 23 0>; ++ }; ++ button@4 { ++ label = "GPIO KEY_ENTER"; ++ linux,code = <28>; ++ gpios = <&gpio 4 0>; ++ }; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&tinylcd35>,"spi-max-frequency:0"; ++ rotate = <&tinylcd35>,"rotate:0"; ++ fps = <&tinylcd35>,"fps:0"; ++ debug = <&tinylcd35>,"debug:0"; ++ touch = <&tinylcd35_ts>,"status"; ++ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", ++ <&tinylcd35_ts>,"interrupts:0", ++ <&tinylcd35_ts>,"pendown-gpio:4"; ++ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; ++ rtc-pcf = <&i2c1>,"status", ++ <&pcf8563>,"status"; ++ rtc-ds = <&i2c1>,"status", ++ <&ds1307>,"status"; ++ keypad = <&keypad>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts +new file mode 100644 +index 0000000..29a3b48 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for w1-gpio module (without external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&w1_pins>; ++ gpios = <&gpio 4 0>; ++ rpi,parasitic-power = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ w1_pins: w1_pins { ++ brcm,pins = <4>; ++ brcm,function = <0>; // in (initially) ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&w1>,"gpios:4", ++ <&w1_pins>,"brcm,pins:0"; ++ pullup = <&w1>,"rpi,parasitic-power:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +new file mode 100644 +index 0000000..66a98f6 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +@@ -0,0 +1,41 @@ ++// Definitions for w1-gpio module (with external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&w1_pins>; ++ gpios = <&gpio 4 0>, <&gpio 5 1>; ++ rpi,parasitic-power = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ w1_pins: w1_pins { ++ brcm,pins = <4 5>; ++ brcm,function = <0 1>; // in out ++ brcm,pull = <0 0>; // off off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&w1>,"gpios:4", ++ <&w1_pins>,"brcm,pins:0"; ++ extpullup = <&w1>,"gpios:16", ++ <&w1_pins>,"brcm,pins:4"; ++ pullup = <&w1>,"rpi,parasitic-power:0"; ++ }; ++}; + +From 4bd17cf8893beb8fb36fe6e321abfe2bc091eb17 Mon Sep 17 00:00:00 2001 +From: Siarhei Siamashka +Date: Mon, 17 Jun 2013 13:32:11 +0300 +Subject: [PATCH 27/77] fbdev: add FBIOCOPYAREA ioctl + +Based on the patch authored by Ali Gholami Rudi at + https://lkml.org/lkml/2009/7/13/153 + +Provide an ioctl for userspace applications, but only if this operation +is hardware accelerated (otherwide it does not make any sense). + +Signed-off-by: Siarhei Siamashka +--- + drivers/video/fbdev/core/fbmem.c | 30 ++++++++++++++++++++++++++++++ + include/uapi/linux/fb.h | 5 +++++ + 2 files changed, 35 insertions(+) + +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c +index 0705d88..771992a 100644 +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) + } + EXPORT_SYMBOL(fb_blank); + ++static int fb_copyarea_user(struct fb_info *info, ++ struct fb_copyarea *copy) ++{ ++ int ret = 0; ++ if (!lock_fb_info(info)) ++ return -ENODEV; ++ if (copy->dx + copy->width > info->var.xres || ++ copy->sx + copy->width > info->var.xres || ++ copy->dy + copy->height > info->var.yres || ++ copy->sy + copy->height > info->var.yres) { ++ ret = -EINVAL; ++ goto out; ++ } ++ info->fbops->fb_copyarea(info, copy); ++out: ++ unlock_fb_info(info); ++ return ret; ++} ++ + static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) + { +@@ -1094,6 +1113,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + struct fb_cmap cmap_from; + struct fb_cmap_user cmap; + struct fb_event event; ++ struct fb_copyarea copy; + void __user *argp = (void __user *)arg; + long ret = 0; + +@@ -1211,6 +1231,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unlock_fb_info(info); + console_unlock(); + break; ++ case FBIOCOPYAREA: ++ if (info->flags & FBINFO_HWACCEL_COPYAREA) { ++ /* only provide this ioctl if it is accelerated */ ++ if (copy_from_user(©, argp, sizeof(copy))) ++ return -EFAULT; ++ ret = fb_copyarea_user(info, ©); ++ break; ++ } ++ /* fall through */ + default: + if (!lock_fb_info(info)) + return -ENODEV; +@@ -1365,6 +1394,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, + case FBIOPAN_DISPLAY: + case FBIOGET_CON2FBMAP: + case FBIOPUT_CON2FBMAP: ++ case FBIOCOPYAREA: + arg = (unsigned long) compat_ptr(arg); + case FBIOBLANK: + ret = do_fb_ioctl(info, cmd, arg); +diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h +index fb795c3..fa72af0 100644 +--- a/include/uapi/linux/fb.h ++++ b/include/uapi/linux/fb.h +@@ -34,6 +34,11 @@ + #define FBIOPUT_MODEINFO 0x4617 + #define FBIOGET_DISPINFO 0x4618 + #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) ++/* ++ * HACK: use 'z' in order not to clash with any other ioctl numbers which might ++ * be concurrently added to the mainline kernel ++ */ ++#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) + + #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ + #define FB_TYPE_PLANES 1 /* Non interleaved planes */ + +From 54459bf0dcbd9019a1bc98cdc77a5c37811c1be5 Mon Sep 17 00:00:00 2001 +From: Harm Hanemaaijer +Date: Thu, 20 Jun 2013 20:21:39 +0200 +Subject: [PATCH 30/77] 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 +console monochrome imageblit function used to draw console text is +suboptimal for common pixel depths such as 16bpp and 32bpp. The existing +code is quite general and can deal with several pixel depths. By creating +special case functions for 16bpp and 32bpp, by far the most common pixel +formats used on modern systems, a significant speed-up is attained +which can be readily felt on ARM-based devices like the Raspberry Pi +and the Allwinner platform, but should help any platform using the +fb layer. + +The special case functions allow constant folding, eliminating a number +of instructions including divide operations, and allow the use of an +unrolled loop, eliminating instructions with a variable shift size, +reducing source memory access instructions, and eliminating excessive +branching. These unrolled loops also allow much better code optimization +by the C compiler. The code that selects which optimized variant is used +is also simplified, eliminating integer divide instructions. + +The speed-up, measured by timing 'cat file.txt' in the console, varies +between 40% and 70%, when testing on the Raspberry Pi and Allwinner +ARM-based platforms, depending on font size and the pixel depth, with +the greater benefit for 32bpp. + +Signed-off-by: Harm Hanemaaijer +--- + drivers/video/fbdev/core/cfbimgblt.c | 152 +++++++++++++++++++++++++++++++++-- + 1 file changed, 147 insertions(+), 5 deletions(-) + +diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c +index a2bb276..436494f 100644 +--- a/drivers/video/fbdev/core/cfbimgblt.c ++++ b/drivers/video/fbdev/core/cfbimgblt.c +@@ -28,6 +28,11 @@ + * + * Also need to add code to deal with cards endians that are different than + * the native cpu endians. I also need to deal with MSB position in the word. ++ * Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013: ++ * - Provide optimized versions of fast_imageblit for 16 and 32bpp that are ++ * significantly faster than the previous implementation. ++ * - Simplify the fast/slow_imageblit selection code, avoiding integer ++ * divides. + */ + #include + #include +@@ -262,6 +267,133 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * + } + } + ++/* ++ * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded ++ * into the code, main loop unrolled. ++ */ ++ ++static inline void fast_imageblit16(const struct fb_image *image, ++ struct fb_info *p, u8 __iomem * dst1, ++ u32 fgcolor, u32 bgcolor) ++{ ++ u32 fgx = fgcolor, bgx = bgcolor; ++ u32 spitch = (image->width + 7) / 8; ++ u32 end_mask, eorx; ++ const char *s = image->data, *src; ++ u32 __iomem *dst; ++ const u32 *tab = NULL; ++ int i, j, k; ++ ++ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; ++ ++ fgx <<= 16; ++ bgx <<= 16; ++ fgx |= fgcolor; ++ bgx |= bgcolor; ++ ++ eorx = fgx ^ bgx; ++ k = image->width / 2; ++ ++ for (i = image->height; i--;) { ++ dst = (u32 __iomem *) dst1; ++ src = s; ++ ++ j = k; ++ while (j >= 4) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 6) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 4) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 2) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[bits & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ src++; ++ j -= 4; ++ } ++ if (j != 0) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 6) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ if (j >= 2) { ++ end_mask = tab[(bits >> 4) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ if (j == 3) { ++ end_mask = tab[(bits >> 2) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst); ++ } ++ } ++ } ++ dst1 += p->fix.line_length; ++ s += spitch; ++ } ++} ++ ++/* ++ * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded ++ * into the code, main loop unrolled. ++ */ ++ ++static inline void fast_imageblit32(const struct fb_image *image, ++ struct fb_info *p, u8 __iomem * dst1, ++ u32 fgcolor, u32 bgcolor) ++{ ++ u32 fgx = fgcolor, bgx = bgcolor; ++ u32 spitch = (image->width + 7) / 8; ++ u32 end_mask, eorx; ++ const char *s = image->data, *src; ++ u32 __iomem *dst; ++ const u32 *tab = NULL; ++ int i, j, k; ++ ++ tab = cfb_tab32; ++ ++ eorx = fgx ^ bgx; ++ k = image->width; ++ ++ for (i = image->height; i--;) { ++ dst = (u32 __iomem *) dst1; ++ src = s; ++ ++ j = k; ++ while (j >= 8) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 6) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 5) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 4) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 3) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 2) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 1) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[bits & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ src++; ++ j -= 8; ++ } ++ if (j != 0) { ++ u32 bits = (u32) * src; ++ while (j > 1) { ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ bits <<= 1; ++ j--; ++ } ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst); ++ } ++ dst1 += p->fix.line_length; ++ s += spitch; ++ } ++} ++ + void cfb_imageblit(struct fb_info *p, const struct fb_image *image) + { + u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; +@@ -294,11 +426,21 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) + bgcolor = image->bg_color; + } + +- if (32 % bpp == 0 && !start_index && !pitch_index && +- ((width & (32/bpp-1)) == 0) && +- bpp >= 8 && bpp <= 32) +- fast_imageblit(image, p, dst1, fgcolor, bgcolor); +- else ++ if (!start_index && !pitch_index) { ++ if (bpp == 32) ++ fast_imageblit32(image, p, dst1, fgcolor, ++ bgcolor); ++ else if (bpp == 16 && (width & 1) == 0) ++ fast_imageblit16(image, p, dst1, fgcolor, ++ bgcolor); ++ else if (bpp == 8 && (width & 3) == 0) ++ fast_imageblit(image, p, dst1, fgcolor, ++ bgcolor); ++ else ++ slow_imageblit(image, p, dst1, fgcolor, ++ bgcolor, ++ start_index, pitch_index); ++ } else + slow_imageblit(image, p, dst1, fgcolor, bgcolor, + start_index, pitch_index); + } else + +From b78abfc78e582f82fda5e69816eaa97b1097c853 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 26 Mar 2013 17:26:38 +0000 +Subject: [PATCH 31/77] Allow mac address to be set in smsc95xx + +Signed-off-by: popcornmix +--- + drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 26423ad..e29a323 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -59,6 +59,7 @@ + #define SUSPEND_SUSPEND3 (0x08) + #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ + SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) ++#define MAC_ADDR_LEN (6) + + struct smsc95xx_priv { + u32 mac_cr; +@@ -74,6 +75,10 @@ static bool turbo_mode = true; + module_param(turbo_mode, bool, 0644); + MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); + ++static char *macaddr = ":"; ++module_param(macaddr, charp, 0); ++MODULE_PARM_DESC(macaddr, "MAC address"); ++ + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + u32 *data, int in_pm) + { +@@ -763,8 +768,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); + } + ++/* Check the macaddr module parameter for a MAC address */ ++static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) ++{ ++ int i, j, got_num, num; ++ u8 mtbl[MAC_ADDR_LEN]; ++ ++ if (macaddr[0] == ':') ++ return 0; ++ ++ i = 0; ++ j = 0; ++ num = 0; ++ got_num = 0; ++ while (j < MAC_ADDR_LEN) { ++ if (macaddr[i] && macaddr[i] != ':') { ++ got_num++; ++ if ('0' <= macaddr[i] && macaddr[i] <= '9') ++ num = num * 16 + macaddr[i] - '0'; ++ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') ++ num = num * 16 + 10 + macaddr[i] - 'A'; ++ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') ++ num = num * 16 + 10 + macaddr[i] - 'a'; ++ else ++ break; ++ i++; ++ } else if (got_num == 2) { ++ mtbl[j++] = (u8) num; ++ num = 0; ++ got_num = 0; ++ i++; ++ } else { ++ break; ++ } ++ } ++ ++ if (j == MAC_ADDR_LEN) { ++ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " ++ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], ++ mtbl[3], mtbl[4], mtbl[5]); ++ for (i = 0; i < MAC_ADDR_LEN; i++) ++ dev_mac[i] = mtbl[i]; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ + static void smsc95xx_init_mac_address(struct usbnet *dev) + { ++ /* Check module parameters */ ++ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) ++ return; ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { + +From 468a5ebe451a5e3bc693fdbd67173f2fadb7d217 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 May 2013 11:46:50 +0100 +Subject: [PATCH 32/77] 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 +See: https://github.com/raspberrypi/linux/pull/457 + +Add bitbanging pullups, use them for w1-gpio + +Allows parasite power to work, uses module option pullup=1 + +bcm2708: Ensure 1-wire pullup is disabled by default, and expose as module parameter + +Signed-off-by: Alex J Lennon + +w1-gpio: Add gpiopin module parameter and correctly free up gpio pull-up pin, if set + +Signed-off-by: Alex J Lennon + +w1-gpio: Sort out the pullup/parasitic power tangle +--- + arch/arm/mach-bcm2708/bcm2708.c | 29 +++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 29 +++++++++++++++++ + drivers/w1/masters/w1-gpio.c | 69 +++++++++++++++++++++++++++++++++++++---- + drivers/w1/w1.h | 6 ++++ + drivers/w1/w1_int.c | 14 +++++++++ + drivers/w1/w1_io.c | 18 +++++++++-- + include/linux/w1-gpio.h | 1 + + 7 files changed, 157 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index efb3544..c7b4b61 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -77,12 +78,19 @@ + */ + #define DMA_MASK_BITS_COMMON 32 + ++// use GPIO 4 for the one-wire GPIO pin, if enabled ++#define W1_GPIO 4 ++// ensure one-wire GPIO pullup is disabled by default ++#define W1_PULLUP -1 ++ + /* command line parameters */ + static unsigned boardrev, serial; + static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static unsigned w1_gpio_pin = W1_GPIO; ++static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + + static unsigned use_dt = 0; +@@ -303,6 +311,20 @@ static struct platform_device bcm2708_dmaengine_device = { + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), + }; + ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++static struct w1_gpio_platform_data w1_gpio_pdata = { ++ .pin = W1_GPIO, ++ .ext_pullup_enable_pin = W1_PULLUP, ++ .is_open_drain = 0, ++}; ++ ++static struct platform_device w1_device = { ++ .name = "w1-gpio", ++ .id = -1, ++ .dev.platform_data = &w1_gpio_pdata, ++}; ++#endif ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -729,6 +751,11 @@ void __init bcm2708_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ w1_gpio_pdata.pin = w1_gpio_pin; ++ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; ++ bcm_register_device_dt(&w1_device); ++#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +@@ -942,5 +969,7 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(w1_gpio_pin, uint, 0644); ++module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 8017c50..03e208b 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -79,12 +80,19 @@ + */ + #define DMA_MASK_BITS_COMMON 32 + ++// use GPIO 4 for the one-wire GPIO pin, if enabled ++#define W1_GPIO 4 ++// ensure one-wire GPIO pullup is disabled by default ++#define W1_PULLUP -1 ++ + /* command line parameters */ + static unsigned boardrev, serial; + static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static unsigned w1_gpio_pin = W1_GPIO; ++static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + + static unsigned use_dt = 0; +@@ -313,6 +321,20 @@ static struct platform_device bcm2708_dmaengine_device = { + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), + }; + ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++static struct w1_gpio_platform_data w1_gpio_pdata = { ++ .pin = W1_GPIO, ++ .ext_pullup_enable_pin = W1_PULLUP, ++ .is_open_drain = 0, ++}; ++ ++static struct platform_device w1_device = { ++ .name = "w1-gpio", ++ .id = -1, ++ .dev.platform_data = &w1_gpio_pdata, ++}; ++#endif ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -749,6 +771,11 @@ void __init bcm2709_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ w1_gpio_pdata.pin = w1_gpio_pin; ++ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; ++ bcm_register_device_dt(&w1_device); ++#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +@@ -1110,5 +1137,7 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(w1_gpio_pin, uint, 0644); ++module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c +index 8f7848c6..2240f32 100644 +--- a/drivers/w1/masters/w1-gpio.c ++++ b/drivers/w1/masters/w1-gpio.c +@@ -23,6 +23,19 @@ + #include "../w1.h" + #include "../w1_int.h" + ++static int w1_gpio_pullup = 0; ++static int w1_gpio_pullup_orig = 0; ++module_param_named(pullup, w1_gpio_pullup, int, 0); ++MODULE_PARM_DESC(pullup, "Enable parasitic power (power on data) mode"); ++static int w1_gpio_pullup_pin = -1; ++static int w1_gpio_pullup_pin_orig = -1; ++module_param_named(extpullup, w1_gpio_pullup_pin, int, 0); ++MODULE_PARM_DESC(extpullup, "GPIO external pullup pin number"); ++static int w1_gpio_pin = -1; ++static int w1_gpio_pin_orig = -1; ++module_param_named(gpiopin, w1_gpio_pin, int, 0); ++MODULE_PARM_DESC(gpiopin, "GPIO pin number"); ++ + static u8 w1_gpio_set_pullup(void *data, int delay) + { + struct w1_gpio_platform_data *pdata = data; +@@ -67,6 +80,16 @@ static u8 w1_gpio_read_bit(void *data) + return gpio_get_value(pdata->pin) ? 1 : 0; + } + ++static void w1_gpio_bitbang_pullup(void *data, u8 on) ++{ ++ struct w1_gpio_platform_data *pdata = data; ++ ++ if (on) ++ gpio_direction_output(pdata->pin, 1); ++ else ++ gpio_direction_input(pdata->pin); ++} ++ + #if defined(CONFIG_OF) + static const struct of_device_id w1_gpio_dt_ids[] = { + { .compatible = "w1-gpio" }, +@@ -80,6 +103,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; + int gpio; ++ u32 value; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) +@@ -88,6 +112,9 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + if (of_get_property(np, "linux,open-drain", NULL)) + pdata->is_open_drain = 1; + ++ if (of_property_read_u32(np, "rpi,parasitic-power", &value) == 0) ++ pdata->parasitic_power = (value != 0); ++ + gpio = of_get_gpio(np, 0); + if (gpio < 0) { + if (gpio != -EPROBE_DEFER) +@@ -103,7 +130,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + if (gpio == -EPROBE_DEFER) + return gpio; + /* ignore other errors as the pullup gpio is optional */ +- pdata->ext_pullup_enable_pin = gpio; ++ pdata->ext_pullup_enable_pin = (gpio >= 0) ? gpio : -1; + + pdev->dev.platform_data = pdata; + +@@ -113,13 +140,15 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + static int w1_gpio_probe(struct platform_device *pdev) + { + struct w1_bus_master *master; +- struct w1_gpio_platform_data *pdata; ++ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; + int err; + +- if (of_have_populated_dt()) { +- err = w1_gpio_probe_dt(pdev); +- if (err < 0) +- return err; ++ if(pdata == NULL) { ++ if (of_have_populated_dt()) { ++ err = w1_gpio_probe_dt(pdev); ++ if (err < 0) ++ return err; ++ } + } + + pdata = dev_get_platdata(&pdev->dev); +@@ -136,6 +165,22 @@ static int w1_gpio_probe(struct platform_device *pdev) + return -ENOMEM; + } + ++ w1_gpio_pin_orig = pdata->pin; ++ w1_gpio_pullup_pin_orig = pdata->ext_pullup_enable_pin; ++ w1_gpio_pullup_orig = pdata->parasitic_power; ++ ++ if(gpio_is_valid(w1_gpio_pin)) { ++ pdata->pin = w1_gpio_pin; ++ pdata->ext_pullup_enable_pin = -1; ++ pdata->parasitic_power = -1; ++ } ++ pdata->parasitic_power |= w1_gpio_pullup; ++ if(gpio_is_valid(w1_gpio_pullup_pin)) { ++ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin; ++ } ++ ++ dev_info(&pdev->dev, "gpio pin %d, external pullup pin %d, parasitic power %d\n", pdata->pin, pdata->ext_pullup_enable_pin, pdata->parasitic_power); ++ + err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); + if (err) { + dev_err(&pdev->dev, "gpio_request (pin) failed\n"); +@@ -165,6 +210,14 @@ static int w1_gpio_probe(struct platform_device *pdev) + master->set_pullup = w1_gpio_set_pullup; + } + ++ if (pdata->parasitic_power) { ++ if (pdata->is_open_drain) ++ printk(KERN_ERR "w1-gpio 'pullup'(parasitic power) " ++ "option doesn't work with open drain GPIO\n"); ++ else ++ master->bitbang_pullup = w1_gpio_bitbang_pullup; ++ } ++ + err = w1_add_master_device(master); + if (err) { + dev_err(&pdev->dev, "w1_add_master device failed\n"); +@@ -195,6 +248,10 @@ static int w1_gpio_remove(struct platform_device *pdev) + + w1_remove_master_device(master); + ++ pdata->pin = w1_gpio_pin_orig; ++ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin_orig; ++ pdata->parasitic_power = w1_gpio_pullup_orig; ++ + return 0; + } + +diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h +index 56a49ba..881d728 100644 +--- a/drivers/w1/w1.h ++++ b/drivers/w1/w1.h +@@ -171,6 +171,12 @@ struct w1_bus_master + + u8 (*set_pullup)(void *, int); + ++ /** ++ * Turns the pullup on/off in bitbanging mode, takes an on/off argument. ++ * @return -1=Error, 0=completed ++ */ ++ void (*bitbang_pullup) (void *, u8); ++ + void (*search)(void *, struct w1_master *, + u8, w1_slave_found_callback); + }; +diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c +index 47249a3..a4b4a8d 100644 +--- a/drivers/w1/w1_int.c ++++ b/drivers/w1/w1_int.c +@@ -123,6 +123,20 @@ int w1_add_master_device(struct w1_bus_master *master) + return(-EINVAL); + } + ++ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup ++ * and takes care of timing itself */ ++ if (!master->write_byte && !master->touch_bit && master->set_pullup) { ++ printk(KERN_ERR "w1_add_master_device: set_pullup requires " ++ "write_byte or touch_bit, disabling\n"); ++ master->set_pullup = NULL; ++ } ++ ++ if (master->set_pullup && master->bitbang_pullup) { ++ printk(KERN_ERR "w1_add_master_device: set_pullup should not " ++ "be set when bitbang_pullup is used, disabling\n"); ++ master->set_pullup = NULL; ++ } ++ + /* Lock until the device is added (or not) to w1_masters. */ + mutex_lock(&w1_mlock); + /* Search for the first available id (starting at 1). */ +diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c +index 2820924..fd0550f 100644 +--- a/drivers/w1/w1_io.c ++++ b/drivers/w1/w1_io.c +@@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) + static void w1_post_write(struct w1_master *dev) + { + if (dev->pullup_duration) { +- if (dev->enable_pullup && dev->bus_master->set_pullup) +- dev->bus_master->set_pullup(dev->bus_master->data, 0); +- else ++ if (dev->enable_pullup) { ++ if (dev->bus_master->set_pullup) { ++ dev->bus_master->set_pullup(dev-> ++ bus_master->data, ++ 0); ++ } else if (dev->bus_master->bitbang_pullup) { ++ dev->bus_master-> ++ bitbang_pullup(dev->bus_master->data, 1); ++ msleep(dev->pullup_duration); ++ dev->bus_master-> ++ bitbang_pullup(dev->bus_master->data, 0); ++ } ++ } else { + msleep(dev->pullup_duration); ++ } ++ + dev->pullup_duration = 0; + } + } +diff --git a/include/linux/w1-gpio.h b/include/linux/w1-gpio.h +index d58594a..feae942 100644 +--- a/include/linux/w1-gpio.h ++++ b/include/linux/w1-gpio.h +@@ -18,6 +18,7 @@ + struct w1_gpio_platform_data { + unsigned int pin; + unsigned int is_open_drain:1; ++ unsigned int parasitic_power:1; + void (*enable_external_pullup)(int enable); + unsigned int ext_pullup_enable_pin; + unsigned int pullup_duration; + +From 00d8013737c9e736f70e04e07b761517559e495e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 18 Dec 2013 22:16:19 +0000 +Subject: [PATCH 34/77] config: Enable CONFIG_MEMCG, but leave it disabled (due + to memory cost). Enable with cgroup_enable=memory. + +--- + kernel/cgroup.c | 23 +++++++++++++++++++++++ + mm/memcontrol.c | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 469dd54..c9684da 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -5395,6 +5395,29 @@ static int __init cgroup_disable(char *str) + } + __setup("cgroup_disable=", cgroup_disable); + ++static int __init cgroup_enable(char *str) ++{ ++ struct cgroup_subsys *ss; ++ char *token; ++ int i; ++ ++ while ((token = strsep(&str, ",")) != NULL) { ++ if (!*token) ++ continue; ++ ++ for_each_subsys(ss, i) { ++ if (!strcmp(token, ss->name)) { ++ ss->disabled = 0; ++ printk(KERN_INFO "Enabling %s control group" ++ " subsystem\n", ss->name); ++ break; ++ } ++ } ++ } ++ return 1; ++} ++__setup("cgroup_enable=", cgroup_enable); ++ + static int __init cgroup_set_legacy_files_on_dfl(char *str) + { + printk("cgroup: using legacy files on the default hierarchy\n"); +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index a04225d..a2ef8af 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5388,6 +5388,7 @@ struct cgroup_subsys memory_cgrp_subsys = { + .dfl_cftypes = memory_files, + .legacy_cftypes = mem_cgroup_legacy_files, + .early_init = 0, ++ .disabled = 1, + }; + + /** + +From 5e192d7296061c5d70da39b3fbd1eeedef467923 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:33:38 +0100 +Subject: [PATCH 35/77] ASoC: Add support for BCM2708 + +This driver adds support for digital audio (I2S) +for the BCM2708 SoC that is used by the +Raspberry Pi. External audio codecs can be +connected to the Raspberry Pi via P5 header. + +It relies on cyclic DMA engine support for BCM2708. + +Signed-off-by: Florian Meier + +ASoC: BCM2708: Add 24 bit support + +This adds 24 bit support to the I2S driver of the BCM2708. +Besides enabling the 24 bit flags, it includes two bug fixes: + +MMAP is not supported. Claiming this leads to strange issues +when the format of driver and file do not match. + +The datasheet states that the width extension bit should be set +for widths greater than 24, but greater or equal would be correct. +This follows from the definition of the width field. + +Signed-off-by: Florian Meier + +bcm2708-i2s: Update bclk_ratio to more correct values + +Move GPIO setup to hw_params. + +This is used to stop the I2S driver from breaking +the GPIO setup for other uses of the PCM interface + +Configure GPIOs for I2S based on revision/card settings + +With RPi model B+, assignment of the I2S GPIO pins has changed. +This patch uses the board revision to auto-detect the GPIOs used +for I2S. It also allows sound card drivers to set the GPIOs that +should be used. This is especially important with the Compute +Module. + +bcm2708-i2s: Avoid leak from iomap when accessing gpio + +bcm2708: Eliminate i2s debugfs directory error + +Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') +to avoid the name clash when registering debugfs entries. +--- + sound/soc/bcm/Kconfig | 11 + + sound/soc/bcm/Makefile | 4 + + sound/soc/bcm/bcm2708-i2s.c | 1009 +++++++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/bcm2708-i2s.h | 35 ++ + 4 files changed, 1059 insertions(+) + create mode 100644 sound/soc/bcm/bcm2708-i2s.c + create mode 100644 sound/soc/bcm/bcm2708-i2s.h + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 6a834e1..8642296 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -7,3 +7,14 @@ config SND_BCM2835_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2835 I2S interface. You will also need + to select the audio interfaces to support below. ++ ++config SND_BCM2708_SOC_I2S ++ tristate "SoC Audio support for the Broadcom BCM2708 I2S module" ++ depends on MACH_BCM2708 || MACH_BCM2709 ++ select REGMAP_MMIO ++ select SND_SOC_DMAENGINE_PCM ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ help ++ Say Y or M if you want to add support for codecs attached to ++ the BCM2708 I2S interface. You will also need ++ to select the audio interfaces to support below. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index bc816b7..f8bbe1f 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o + + obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + ++# BCM2708 Platform Support ++snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o ++ ++obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o +diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c +new file mode 100644 +index 0000000..a3b65dc +--- /dev/null ++++ b/sound/soc/bcm/bcm2708-i2s.c +@@ -0,0 +1,1009 @@ ++/* ++ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * Based on ++ * Raspberry Pi PCM I2S ALSA Driver ++ * Copyright (c) by Phil Poole 2013 ++ * ++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor ++ * Vladimir Barinov, ++ * Copyright (C) 2007 MontaVista Software, Inc., ++ * ++ * OMAP ALSA SoC DAI driver using McBSP port ++ * Copyright (C) 2008 Nokia Corporation ++ * Contact: Jarkko Nikula ++ * Peter Ujfalusi ++ * ++ * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver ++ * Author: Timur Tabi ++ * Copyright 2007-2010 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include "bcm2708-i2s.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* Clock registers */ ++#define BCM2708_CLK_PCMCTL_REG 0x00 ++#define BCM2708_CLK_PCMDIV_REG 0x04 ++ ++/* Clock register settings */ ++#define BCM2708_CLK_PASSWD (0x5a000000) ++#define BCM2708_CLK_PASSWD_MASK (0xff000000) ++#define BCM2708_CLK_MASH(v) ((v) << 9) ++#define BCM2708_CLK_FLIP BIT(8) ++#define BCM2708_CLK_BUSY BIT(7) ++#define BCM2708_CLK_KILL BIT(5) ++#define BCM2708_CLK_ENAB BIT(4) ++#define BCM2708_CLK_SRC(v) (v) ++ ++#define BCM2708_CLK_SHIFT (12) ++#define BCM2708_CLK_DIVI(v) ((v) << BCM2708_CLK_SHIFT) ++#define BCM2708_CLK_DIVF(v) (v) ++#define BCM2708_CLK_DIVF_MASK (0xFFF) ++ ++enum { ++ BCM2708_CLK_MASH_0 = 0, ++ BCM2708_CLK_MASH_1, ++ BCM2708_CLK_MASH_2, ++ BCM2708_CLK_MASH_3, ++}; ++ ++enum { ++ BCM2708_CLK_SRC_GND = 0, ++ BCM2708_CLK_SRC_OSC, ++ BCM2708_CLK_SRC_DBG0, ++ BCM2708_CLK_SRC_DBG1, ++ BCM2708_CLK_SRC_PLLA, ++ BCM2708_CLK_SRC_PLLC, ++ BCM2708_CLK_SRC_PLLD, ++ BCM2708_CLK_SRC_HDMI, ++}; ++ ++/* Most clocks are not useable (freq = 0) */ ++static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = { ++ [BCM2708_CLK_SRC_GND] = 0, ++ [BCM2708_CLK_SRC_OSC] = 19200000, ++ [BCM2708_CLK_SRC_DBG0] = 0, ++ [BCM2708_CLK_SRC_DBG1] = 0, ++ [BCM2708_CLK_SRC_PLLA] = 0, ++ [BCM2708_CLK_SRC_PLLC] = 0, ++ [BCM2708_CLK_SRC_PLLD] = 500000000, ++ [BCM2708_CLK_SRC_HDMI] = 0, ++}; ++ ++/* I2S registers */ ++#define BCM2708_I2S_CS_A_REG 0x00 ++#define BCM2708_I2S_FIFO_A_REG 0x04 ++#define BCM2708_I2S_MODE_A_REG 0x08 ++#define BCM2708_I2S_RXC_A_REG 0x0c ++#define BCM2708_I2S_TXC_A_REG 0x10 ++#define BCM2708_I2S_DREQ_A_REG 0x14 ++#define BCM2708_I2S_INTEN_A_REG 0x18 ++#define BCM2708_I2S_INTSTC_A_REG 0x1c ++#define BCM2708_I2S_GRAY_REG 0x20 ++ ++/* I2S register settings */ ++#define BCM2708_I2S_STBY BIT(25) ++#define BCM2708_I2S_SYNC BIT(24) ++#define BCM2708_I2S_RXSEX BIT(23) ++#define BCM2708_I2S_RXF BIT(22) ++#define BCM2708_I2S_TXE BIT(21) ++#define BCM2708_I2S_RXD BIT(20) ++#define BCM2708_I2S_TXD BIT(19) ++#define BCM2708_I2S_RXR BIT(18) ++#define BCM2708_I2S_TXW BIT(17) ++#define BCM2708_I2S_CS_RXERR BIT(16) ++#define BCM2708_I2S_CS_TXERR BIT(15) ++#define BCM2708_I2S_RXSYNC BIT(14) ++#define BCM2708_I2S_TXSYNC BIT(13) ++#define BCM2708_I2S_DMAEN BIT(9) ++#define BCM2708_I2S_RXTHR(v) ((v) << 7) ++#define BCM2708_I2S_TXTHR(v) ((v) << 5) ++#define BCM2708_I2S_RXCLR BIT(4) ++#define BCM2708_I2S_TXCLR BIT(3) ++#define BCM2708_I2S_TXON BIT(2) ++#define BCM2708_I2S_RXON BIT(1) ++#define BCM2708_I2S_EN (1) ++ ++#define BCM2708_I2S_CLKDIS BIT(28) ++#define BCM2708_I2S_PDMN BIT(27) ++#define BCM2708_I2S_PDME BIT(26) ++#define BCM2708_I2S_FRXP BIT(25) ++#define BCM2708_I2S_FTXP BIT(24) ++#define BCM2708_I2S_CLKM BIT(23) ++#define BCM2708_I2S_CLKI BIT(22) ++#define BCM2708_I2S_FSM BIT(21) ++#define BCM2708_I2S_FSI BIT(20) ++#define BCM2708_I2S_FLEN(v) ((v) << 10) ++#define BCM2708_I2S_FSLEN(v) (v) ++ ++#define BCM2708_I2S_CHWEX BIT(15) ++#define BCM2708_I2S_CHEN BIT(14) ++#define BCM2708_I2S_CHPOS(v) ((v) << 4) ++#define BCM2708_I2S_CHWID(v) (v) ++#define BCM2708_I2S_CH1(v) ((v) << 16) ++#define BCM2708_I2S_CH2(v) (v) ++ ++#define BCM2708_I2S_TX_PANIC(v) ((v) << 24) ++#define BCM2708_I2S_RX_PANIC(v) ((v) << 16) ++#define BCM2708_I2S_TX(v) ((v) << 8) ++#define BCM2708_I2S_RX(v) (v) ++ ++#define BCM2708_I2S_INT_RXERR BIT(3) ++#define BCM2708_I2S_INT_TXERR BIT(2) ++#define BCM2708_I2S_INT_RXR BIT(1) ++#define BCM2708_I2S_INT_TXW BIT(0) ++ ++/* I2S DMA interface */ ++#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004 ++#define BCM2708_DMA_DREQ_PCM_TX 2 ++#define BCM2708_DMA_DREQ_PCM_RX 3 ++ ++/* I2S pin configuration */ ++static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO; ++ ++/* General device struct */ ++struct bcm2708_i2s_dev { ++ struct device *dev; ++ struct snd_dmaengine_dai_dma_data dma_data[2]; ++ unsigned int fmt; ++ unsigned int bclk_ratio; ++ ++ struct regmap *i2s_regmap; ++ struct regmap *clk_regmap; ++}; ++ ++void bcm2708_i2s_set_gpio(int gpio) { ++ bcm2708_i2s_gpio=gpio; ++} ++EXPORT_SYMBOL(bcm2708_i2s_set_gpio); ++ ++ ++static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev) ++{ ++ /* Start the clock if in master mode */ ++ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; ++ ++ switch (master) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void bcm2708_i2s_stop_clock(struct bcm2708_i2s_dev *dev) ++{ ++ uint32_t clkreg; ++ int timeout = 1000; ++ ++ /* Stop clock */ ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD); ++ ++ /* Wait for the BUSY flag going down */ ++ while (--timeout) { ++ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); ++ if (!(clkreg & BCM2708_CLK_BUSY)) ++ break; ++ } ++ ++ if (!timeout) { ++ /* KILL the clock */ ++ dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD_MASK, ++ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD); ++ } ++} ++ ++static void bcm2708_i2s_clear_fifos(struct bcm2708_i2s_dev *dev, ++ bool tx, bool rx) ++{ ++ int timeout = 1000; ++ uint32_t syncval; ++ uint32_t csreg; ++ uint32_t i2s_active_state; ++ uint32_t clkreg; ++ uint32_t clk_active_state; ++ uint32_t off; ++ uint32_t clr; ++ ++ off = tx ? BCM2708_I2S_TXON : 0; ++ off |= rx ? BCM2708_I2S_RXON : 0; ++ ++ clr = tx ? BCM2708_I2S_TXCLR : 0; ++ clr |= rx ? BCM2708_I2S_RXCLR : 0; ++ ++ /* Backup the current state */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ i2s_active_state = csreg & (BCM2708_I2S_RXON | BCM2708_I2S_TXON); ++ ++ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); ++ clk_active_state = clkreg & BCM2708_CLK_ENAB; ++ ++ /* Start clock if not running */ ++ if (!clk_active_state) { ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); ++ } ++ ++ /* Stop I2S module */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, off, 0); ++ ++ /* ++ * Clear the FIFOs ++ * Requires at least 2 PCM clock cycles to take effect ++ */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, clr, clr); ++ ++ /* Wait for 2 PCM clock cycles */ ++ ++ /* ++ * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back ++ * FIXME: This does not seem to work for slave mode! ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &syncval); ++ syncval &= BCM2708_I2S_SYNC; ++ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_SYNC, ~syncval); ++ ++ /* Wait for the SYNC flag changing it's state */ ++ while (--timeout) { ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ if ((csreg & BCM2708_I2S_SYNC) != syncval) ++ break; ++ } ++ ++ if (!timeout) ++ dev_err(dev->dev, "I2S SYNC error!\n"); ++ ++ /* Stop clock if it was not running before */ ++ if (!clk_active_state) ++ bcm2708_i2s_stop_clock(dev); ++ ++ /* Restore I2S state */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_RXON | BCM2708_I2S_TXON, i2s_active_state); ++} ++ ++static int bcm2708_i2s_set_dai_fmt(struct snd_soc_dai *dai, ++ unsigned int fmt) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ dev->fmt = fmt; ++ return 0; ++} ++ ++static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, ++ unsigned int ratio) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ dev->bclk_ratio = ratio; ++ return 0; ++} ++ ++ ++static int bcm2708_i2s_set_function(unsigned offset, int function) ++{ ++ #define GPIOFSEL(x) (0x00+(x)*4) ++ void __iomem *gpio = __io_address(GPIO_BASE); ++ unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2; ++ unsigned gpiodir; ++ unsigned gpio_bank = offset / 10; ++ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; ++ ++ if (offset >= BCM2708_NR_GPIOS) ++ return -EINVAL; ++ ++ gpiodir = readl(gpio + GPIOFSEL(gpio_bank)); ++ gpiodir &= ~(7 << gpio_field_offset); ++ gpiodir |= alt << gpio_field_offset; ++ writel(gpiodir, gpio + GPIOFSEL(gpio_bank)); ++ return 0; ++} ++ ++static void bcm2708_i2s_setup_gpio(void) ++{ ++ /* ++ * This is the common way to handle the GPIO pins for ++ * the Raspberry Pi. ++ * TODO Better way would be to handle ++ * this in the device tree! ++ */ ++ int pin,pinconfig,startpin,alt; ++ ++ /* SPI is on different GPIOs on different boards */ ++ /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */ ++ if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) { ++ if ((system_rev & 0xffffff) >= 0x10) { ++ /* Model B+ */ ++ pinconfig=BCM2708_I2S_GPIO_PIN18; ++ } else { ++ /* original */ ++ pinconfig=BCM2708_I2S_GPIO_PIN28; ++ } ++ } else { ++ pinconfig=bcm2708_i2s_gpio; ++ } ++ ++ if (pinconfig==BCM2708_I2S_GPIO_PIN18) { ++ startpin=18; ++ alt=BCM2708_I2S_GPIO_PIN18_ALT; ++ } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) { ++ startpin=28; ++ alt=BCM2708_I2S_GPIO_PIN28_ALT; ++ } else { ++ printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig); ++ return; ++ } ++ ++ /* configure I2S pins to correct ALT mode */ ++ for (pin = startpin; pin <= startpin+3; pin++) { ++ bcm2708_i2s_set_function(pin, alt); ++ } ++} ++ ++static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ unsigned int sampling_rate = params_rate(params); ++ unsigned int data_length, data_delay, bclk_ratio; ++ unsigned int ch1pos, ch2pos, mode, format; ++ unsigned int mash = BCM2708_CLK_MASH_1; ++ unsigned int divi, divf, target_frequency; ++ int clk_src = -1; ++ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; ++ bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS ++ || master == SND_SOC_DAIFMT_CBS_CFM); ++ ++ bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS ++ || master == SND_SOC_DAIFMT_CBM_CFS); ++ uint32_t csreg; ++ ++ /* ++ * If a stream is already enabled, ++ * the registers are already set properly. ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ ++ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON)) ++ return 0; ++ ++ ++ bcm2708_i2s_setup_gpio(); ++ ++ /* ++ * Adjust the data length according to the format. ++ * We prefill the half frame length with an integer ++ * divider of 2400 as explained at the clock settings. ++ * Maybe it is overwritten there, if the Integer mode ++ * does not apply. ++ */ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ data_length = 16; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ data_length = 24; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ data_length = 32; ++ bclk_ratio = 100; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* If bclk_ratio already set, use that one. */ ++ if (dev->bclk_ratio) ++ bclk_ratio = dev->bclk_ratio; ++ ++ /* ++ * Clock Settings ++ * ++ * The target frequency of the bit clock is ++ * sampling rate * frame length ++ * ++ * Integer mode: ++ * Sampling rates that are multiples of 8000 kHz ++ * can be driven by the oscillator of 19.2 MHz ++ * with an integer divider as long as the frame length ++ * is an integer divider of 19200000/8000=2400 as set up above. ++ * This is no longer possible if the sampling rate ++ * is too high (e.g. 192 kHz), because the oscillator is too slow. ++ * ++ * MASH mode: ++ * For all other sampling rates, it is not possible to ++ * have an integer divider. Approximate the clock ++ * with the MASH module that induces a slight frequency ++ * variance. To minimize that it is best to have the fastest ++ * clock here. That is PLLD with 500 MHz. ++ */ ++ target_frequency = sampling_rate * bclk_ratio; ++ clk_src = BCM2708_CLK_SRC_OSC; ++ mash = BCM2708_CLK_MASH_0; ++ ++ if (bcm2708_clk_freq[clk_src] % target_frequency == 0 ++ && bit_master && frame_master) { ++ divi = bcm2708_clk_freq[clk_src] / target_frequency; ++ divf = 0; ++ } else { ++ uint64_t dividend; ++ ++ if (!dev->bclk_ratio) { ++ /* ++ * Overwrite bclk_ratio, because the ++ * above trick is not needed or can ++ * not be used. ++ */ ++ bclk_ratio = 2 * data_length; ++ } ++ ++ target_frequency = sampling_rate * bclk_ratio; ++ ++ clk_src = BCM2708_CLK_SRC_PLLD; ++ mash = BCM2708_CLK_MASH_1; ++ ++ dividend = bcm2708_clk_freq[clk_src]; ++ dividend <<= BCM2708_CLK_SHIFT; ++ do_div(dividend, target_frequency); ++ divi = dividend >> BCM2708_CLK_SHIFT; ++ divf = dividend & BCM2708_CLK_DIVF_MASK; ++ } ++ ++ /* Clock should only be set up here if CPU is clock master */ ++ if (((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS) || ++ ((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFM)) { ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMDIV_REG, BCM2708_CLK_PASSWD ++ | BCM2708_CLK_DIVI(divi) ++ | BCM2708_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, BCM2708_CLK_PASSWD ++ | BCM2708_CLK_MASH(mash) ++ | BCM2708_CLK_SRC(clk_src)); ++ } ++ ++ /* Setup the frame format */ ++ format = BCM2708_I2S_CHEN; ++ ++ if (data_length >= 24) ++ format |= BCM2708_I2S_CHWEX; ++ ++ format |= BCM2708_I2S_CHWID((data_length-8)&0xf); ++ ++ switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ data_delay = 1; ++ break; ++ default: ++ /* ++ * TODO ++ * Others are possible but are not implemented at the moment. ++ */ ++ dev_err(dev->dev, "%s:bad format\n", __func__); ++ return -EINVAL; ++ } ++ ++ ch1pos = data_delay; ++ ch2pos = bclk_ratio / 2 + data_delay; ++ ++ switch (params_channels(params)) { ++ case 2: ++ format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format); ++ format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos)); ++ format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * Set format for both streams. ++ * We cannot set another frame length ++ * (and therefore word length) anyway, ++ * so the format will be the same. ++ */ ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_RXC_A_REG, format); ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_TXC_A_REG, format); ++ ++ /* Setup the I2S mode */ ++ mode = 0; ++ ++ if (data_length <= 16) { ++ /* ++ * Use frame packed mode (2 channels per 32 bit word) ++ * We cannot set another frame length in the second stream ++ * (and therefore word length) anyway, ++ * so the format will be the same. ++ */ ++ mode |= BCM2708_I2S_FTXP | BCM2708_I2S_FRXP; ++ } ++ ++ mode |= BCM2708_I2S_FLEN(bclk_ratio - 1); ++ mode |= BCM2708_I2S_FSLEN(bclk_ratio / 2); ++ ++ /* Master or slave? */ ++ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ /* CPU is master */ ++ break; ++ case SND_SOC_DAIFMT_CBM_CFS: ++ /* ++ * CODEC is bit clock master ++ * CPU is frame master ++ */ ++ mode |= BCM2708_I2S_CLKM; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFM: ++ /* ++ * CODEC is frame master ++ * CPU is bit clock master ++ */ ++ mode |= BCM2708_I2S_FSM; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ /* CODEC is master */ ++ mode |= BCM2708_I2S_CLKM; ++ mode |= BCM2708_I2S_FSM; ++ break; ++ default: ++ dev_err(dev->dev, "%s:bad master\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* ++ * Invert clocks? ++ * ++ * The BCM approach seems to be inverted to the classical I2S approach. ++ */ ++ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ /* None. Therefore, both for BCM */ ++ mode |= BCM2708_I2S_CLKI; ++ mode |= BCM2708_I2S_FSI; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ /* Both. Therefore, none for BCM */ ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ /* ++ * Invert only frame sync. Therefore, ++ * invert only bit clock for BCM ++ */ ++ mode |= BCM2708_I2S_CLKI; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ /* ++ * Invert only bit clock. Therefore, ++ * invert only frame sync for BCM ++ */ ++ mode |= BCM2708_I2S_FSI; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_MODE_A_REG, mode); ++ ++ /* Setup the DMA parameters */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_RXTHR(1) ++ | BCM2708_I2S_TXTHR(1) ++ | BCM2708_I2S_DMAEN, 0xffffffff); ++ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_DREQ_A_REG, ++ BCM2708_I2S_TX_PANIC(0x10) ++ | BCM2708_I2S_RX_PANIC(0x30) ++ | BCM2708_I2S_TX(0x30) ++ | BCM2708_I2S_RX(0x20), 0xffffffff); ++ ++ /* Clear FIFOs */ ++ bcm2708_i2s_clear_fifos(dev, true, true); ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ uint32_t cs_reg; ++ ++ bcm2708_i2s_start_clock(dev); ++ ++ /* ++ * Clear both FIFOs if the one that should be started ++ * is not empty at the moment. This should only happen ++ * after overrun. Otherwise, hw_params would have cleared ++ * the FIFO. ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &cs_reg); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ++ && !(cs_reg & BCM2708_I2S_TXE)) ++ bcm2708_i2s_clear_fifos(dev, true, false); ++ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE ++ && (cs_reg & BCM2708_I2S_RXD)) ++ bcm2708_i2s_clear_fifos(dev, false, true); ++ ++ return 0; ++} ++ ++static void bcm2708_i2s_stop(struct bcm2708_i2s_dev *dev, ++ struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ uint32_t mask; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ mask = BCM2708_I2S_RXON; ++ else ++ mask = BCM2708_I2S_TXON; ++ ++ regmap_update_bits(dev->i2s_regmap, ++ BCM2708_I2S_CS_A_REG, mask, 0); ++ ++ /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ ++ if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) ++ bcm2708_i2s_stop_clock(dev); ++} ++ ++static int bcm2708_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ uint32_t mask; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ bcm2708_i2s_start_clock(dev); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ mask = BCM2708_I2S_RXON; ++ else ++ mask = BCM2708_I2S_TXON; ++ ++ regmap_update_bits(dev->i2s_regmap, ++ BCM2708_I2S_CS_A_REG, mask, mask); ++ break; ++ ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ bcm2708_i2s_stop(dev, substream, dai); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ if (dai->active) ++ return 0; ++ ++ /* Should this still be running stop it */ ++ bcm2708_i2s_stop_clock(dev); ++ ++ /* Enable PCM block */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_EN, BCM2708_I2S_EN); ++ ++ /* ++ * Disable STBY. ++ * Requires at least 4 PCM clock cycles to take effect. ++ */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_STBY, BCM2708_I2S_STBY); ++ ++ return 0; ++} ++ ++static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ bcm2708_i2s_stop(dev, substream, dai); ++ ++ /* If both streams are stopped, disable module and clock */ ++ if (dai->active) ++ return; ++ ++ /* Disable the module */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_EN, 0); ++ ++ /* ++ * Stopping clock is necessary, because stop does ++ * not stop the clock when SND_SOC_DAIFMT_CONT ++ */ ++ bcm2708_i2s_stop_clock(dev); ++} ++ ++static const struct snd_soc_dai_ops bcm2708_i2s_dai_ops = { ++ .startup = bcm2708_i2s_startup, ++ .shutdown = bcm2708_i2s_shutdown, ++ .prepare = bcm2708_i2s_prepare, ++ .trigger = bcm2708_i2s_trigger, ++ .hw_params = bcm2708_i2s_hw_params, ++ .set_fmt = bcm2708_i2s_set_dai_fmt, ++ .set_bclk_ratio = bcm2708_i2s_set_dai_bclk_ratio ++}; ++ ++static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; ++ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; ++ ++ return 0; ++} ++ ++static struct snd_soc_dai_driver bcm2708_i2s_dai = { ++ .name = "bcm2708-i2s", ++ .probe = bcm2708_i2s_dai_probe, ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE ++ | SNDRV_PCM_FMTBIT_S24_LE ++ | SNDRV_PCM_FMTBIT_S32_LE ++ }, ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE ++ | SNDRV_PCM_FMTBIT_S24_LE ++ | SNDRV_PCM_FMTBIT_S32_LE ++ }, ++ .ops = &bcm2708_i2s_dai_ops, ++ .symmetric_rates = 1 ++}; ++ ++static bool bcm2708_i2s_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_I2S_CS_A_REG: ++ case BCM2708_I2S_FIFO_A_REG: ++ case BCM2708_I2S_INTSTC_A_REG: ++ case BCM2708_I2S_GRAY_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static bool bcm2708_i2s_precious_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_I2S_FIFO_A_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static bool bcm2708_clk_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_CLK_PCMCTL_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static const struct regmap_config bcm2708_regmap_config[] = { ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2708_I2S_GRAY_REG, ++ .precious_reg = bcm2708_i2s_precious_reg, ++ .volatile_reg = bcm2708_i2s_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ .name = "i2s", ++ }, ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2708_CLK_PCMDIV_REG, ++ .volatile_reg = bcm2708_clk_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ .name = "clk", ++ }, ++}; ++ ++static const struct snd_soc_component_driver bcm2708_i2s_component = { ++ .name = "bcm2708-i2s-comp", ++}; ++ ++static const struct snd_pcm_hardware bcm2708_pcm_hardware = { ++ .info = SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_JOINT_DUPLEX, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ .period_bytes_min = 32, ++ .period_bytes_max = 64 * PAGE_SIZE, ++ .periods_min = 2, ++ .periods_max = 255, ++ .buffer_bytes_max = 128 * PAGE_SIZE, ++}; ++ ++static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &bcm2708_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ ++ ++static int bcm2708_i2s_probe(struct platform_device *pdev) ++{ ++ struct bcm2708_i2s_dev *dev; ++ int i; ++ int ret; ++ struct regmap *regmap[2]; ++ struct resource *mem[2]; ++ ++ /* Request both ioareas */ ++ for (i = 0; i <= 1; i++) { ++ void __iomem *base; ++ ++ mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); ++ base = devm_ioremap_resource(&pdev->dev, mem[i]); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, ++ &bcm2708_regmap_config[i]); ++ if (IS_ERR(regmap[i])) { ++ dev_err(&pdev->dev, "I2S probe: regmap init failed\n"); ++ return PTR_ERR(regmap[i]); ++ } ++ } ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), ++ GFP_KERNEL); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ dev->i2s_regmap = regmap[0]; ++ dev->clk_regmap = regmap[1]; ++ ++ /* Set the DMA address */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = ++ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; ++ ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = ++ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; ++ ++ /* Set the DREQ */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id = ++ BCM2708_DMA_DREQ_PCM_TX; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id = ++ BCM2708_DMA_DREQ_PCM_RX; ++ ++ /* Set the bus width */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = ++ DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = ++ DMA_SLAVE_BUSWIDTH_4_BYTES; ++ ++ /* Set burst */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; ++ ++ /* BCLK ratio - use default */ ++ dev->bclk_ratio = 0; ++ ++ /* Store the pdev */ ++ dev->dev = &pdev->dev; ++ dev_set_drvdata(&pdev->dev, dev); ++ ++ ret = snd_soc_register_component(&pdev->dev, ++ &bcm2708_i2s_component, &bcm2708_i2s_dai, 1); ++ ++ if (ret) { ++ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); ++ ret = -ENOMEM; ++ return ret; ++ } ++ ++ ret = snd_dmaengine_pcm_register(&pdev->dev, ++ &bcm2708_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ if (ret) { ++ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); ++ snd_soc_unregister_component(&pdev->dev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_remove(struct platform_device *pdev) ++{ ++ snd_dmaengine_pcm_unregister(&pdev->dev); ++ snd_soc_unregister_component(&pdev->dev); ++ return 0; ++} ++ ++static const struct of_device_id bcm2708_i2s_of_match[] = { ++ { .compatible = "brcm,bcm2708-i2s", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_i2s_of_match); ++ ++static struct platform_driver bcm2708_i2s_driver = { ++ .probe = bcm2708_i2s_probe, ++ .remove = bcm2708_i2s_remove, ++ .driver = { ++ .name = "bcm2708-i2s", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2708_i2s_of_match, ++ }, ++}; ++ ++module_platform_driver(bcm2708_i2s_driver); ++ ++MODULE_ALIAS("platform:bcm2708-i2s"); ++MODULE_DESCRIPTION("BCM2708 I2S interface"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/bcm/bcm2708-i2s.h b/sound/soc/bcm/bcm2708-i2s.h +new file mode 100644 +index 0000000..6fdcbc1 +--- /dev/null ++++ b/sound/soc/bcm/bcm2708-i2s.h +@@ -0,0 +1,35 @@ ++/* ++ * I2S configuration for sound cards. ++ * ++ * Copyright (c) 2014 Daniel Matuschek ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef BCM2708_I2S_H ++#define BCM2708_I2S_H ++ ++/* I2S pin assignment */ ++#define BCM2708_I2S_GPIO_AUTO 0 ++#define BCM2708_I2S_GPIO_PIN18 1 ++#define BCM2708_I2S_GPIO_PIN28 2 ++ ++/* Alt mode to enable I2S */ ++#define BCM2708_I2S_GPIO_PIN18_ALT 0 ++#define BCM2708_I2S_GPIO_PIN28_ALT 2 ++ ++extern void bcm2708_i2s_set_gpio(int gpio); ++ ++#endif + +From 355253cae3f2e9200926bfeb8d21646600d0768e Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:59:51 +0100 +Subject: [PATCH 36/77] ASoC: Add support for PCM5102A codec + +Some definitions to support the PCM5102A codec +by Texas Instruments. + +Signed-off-by: Florian Meier +--- + sound/soc/codecs/Kconfig | 4 +++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/pcm5102a.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+) + create mode 100644 sound/soc/codecs/pcm5102a.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 061c465..a3d70f9 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -83,6 +83,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM512x_I2C if I2C + select SND_SOC_PCM512x_SPI if SPI_MASTER + select SND_SOC_RT286 if I2C ++ select SND_SOC_PCM5102A if I2C + select SND_SOC_RT5631 if I2C + select SND_SOC_RT5640 if I2C + select SND_SOC_RT5645 if I2C +@@ -511,6 +512,9 @@ config SND_SOC_RT286 + tristate + depends on I2C + ++config SND_SOC_PCM5102A ++ tristate ++ + config SND_SOC_RT5631 + tristate "Realtek ALC5631/RT5631 CODEC" + depends on I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index abe2d7e..a0fda52 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -78,6 +78,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o + snd-soc-pcm512x-spi-objs := pcm512x-spi.o + snd-soc-rl6231-objs := rl6231.o + snd-soc-rt286-objs := rt286.o ++snd-soc-pcm5102a-objs := pcm5102a.o + snd-soc-rt5631-objs := rt5631.o + snd-soc-rt5640-objs := rt5640.o + snd-soc-rt5645-objs := rt5645.o +@@ -263,6 +264,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o ++obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o + obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o + obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o +diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c +new file mode 100644 +index 0000000..126f1e9 +--- /dev/null ++++ b/sound/soc/codecs/pcm5102a.c +@@ -0,0 +1,63 @@ ++/* ++ * Driver for the PCM5102A codec ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver pcm5102a_dai = { ++ .name = "pcm5102a-hifi", ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; ++ ++static int pcm5102a_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, ++ &pcm5102a_dai, 1); ++} ++ ++static int pcm5102a_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver pcm5102a_codec_driver = { ++ .probe = pcm5102a_probe, ++ .remove = pcm5102a_remove, ++ .driver = { ++ .name = "pcm5102a-codec", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(pcm5102a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From 49e137bd21361ad8f4439f35956ceab424013411 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:04:54 +0100 +Subject: [PATCH 37/77] BCM2708: Add I2S support to board file + +Adds the required initializations for I2S +to the board file of mach-bcm2708. + +Signed-off-by: Florian Meier + +bcm2708-i2s: Enable MMAP support via a DT property and overlay + +The i2s driver used to claim to support MMAP, but that feature was disabled +when some problems were found. Add the ability to enable this feature +through Device Tree, using the i2s-mmap overlay. + +See: #1004 +--- + arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ + sound/soc/bcm/bcm2708-i2s.c | 7 ++++++- + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index c7b4b61..dc57983 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -616,6 +616,28 @@ static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++static struct resource bcm2708_i2s_resources[] = { ++ { ++ .start = I2S_BASE, ++ .end = I2S_BASE + 0x20, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = PCM_CLOCK_BASE, ++ .end = PCM_CLOCK_BASE + 0x02, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device bcm2708_i2s_device = { ++ .name = "bcm2708-i2s", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), ++ .resource = bcm2708_i2s_resources, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -780,6 +802,10 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2835_thermal_device); + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++ bcm_register_device_dt(&bcm2708_i2s_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c +index a3b65dc..a515992 100644 +--- a/sound/soc/bcm/bcm2708-i2s.c ++++ b/sound/soc/bcm/bcm2708-i2s.c +@@ -874,7 +874,7 @@ static const struct snd_soc_component_driver bcm2708_i2s_component = { + .name = "bcm2708-i2s-comp", + }; + +-static const struct snd_pcm_hardware bcm2708_pcm_hardware = { ++static struct snd_pcm_hardware bcm2708_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX, + .formats = SNDRV_PCM_FMTBIT_S16_LE | +@@ -902,6 +902,11 @@ static int bcm2708_i2s_probe(struct platform_device *pdev) + struct regmap *regmap[2]; + struct resource *mem[2]; + ++ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) ++ bcm2708_pcm_hardware.info |= ++ SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID; ++ + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { + void __iomem *base; + +From 5786483930fcb7863012d8bb81d1f73a67b258da Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:19:08 +0100 +Subject: [PATCH 38/77] ASoC: Add support for HifiBerry DAC + +This adds a machine driver for the HifiBerry DAC. +It is a sound card that can +be stacked onto the Raspberry Pi. + +Signed-off-by: Florian Meier +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 5 +++ + sound/soc/bcm/hifiberry_dac.c | 100 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 112 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8642296..a4a3e86 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -18,3 +18,10 @@ config SND_BCM2708_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2708 I2S interface. You will also need + to select the audio interfaces to support below. ++ ++config SND_BCM2708_SOC_HIFIBERRY_DAC ++ tristate "Support for HifiBerry DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5102A ++ help ++ Say Y or M if you want to add support for HifiBerry DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index f8bbe1f..be90a49cb 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,3 +7,8 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o + + obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o ++ ++# BCM2708 Machine Support ++snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++ ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c +new file mode 100644 +index 0000000..4b70b45 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -0,0 +1,100 @@ ++/* ++ * ASoC Driver for HifiBerry DAC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_hifiberry_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dac_ops = { ++ .hw_params = snd_rpi_hifiberry_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { ++{ ++ .name = "HifiBerry DAC", ++ .stream_name = "HifiBerry DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm5102a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm5102a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dac_ops, ++ .init = snd_rpi_hifiberry_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dac = { ++ .name = "snd_rpi_hifiberry_dac", ++ .dai_link = snd_rpi_hifiberry_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), ++}; ++ ++static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_dac_driver = { ++ .driver = { ++ .name = "snd-hifiberry-dac", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_dac_probe, ++ .remove = snd_rpi_hifiberry_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); ++MODULE_LICENSE("GPL v2"); + +From 47d7a2a48fd4b2da2f9400de4307febe755b2ef2 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:21:34 +0100 +Subject: [PATCH 39/77] BCM2708: Add HifiBerry DAC to board file + +This adds the initalization of the HifiBerry DAC +to the mach-bcm2708 board file. + +Signed-off-by: Florian Meier +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index dc57983..ef7c48d 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -638,6 +638,20 @@ static struct platform_device bcm2708_i2s_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++static struct platform_device snd_hifiberry_dac_device = { ++ .name = "snd-hifiberry-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm5102a_codec_device = { ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -806,6 +820,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&bcm2708_i2s_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_dac_device); ++ bcm_register_device_dt(&snd_pcm5102a_codec_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + +From 403dc5c76505dd5813174532b2f032e52cbe06b8 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 6 Dec 2013 20:50:28 +0100 +Subject: [PATCH 40/77] ASoC: BCM2708: Add support for RPi-DAC + +This adds a machine driver for the RPi-DAC. + +Signed-off-by: Florian Meier +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-dac.c | 97 +++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/Kconfig | 4 ++ + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/pcm1794a.c | 62 ++++++++++++++++++++++++++ + 7 files changed, 193 insertions(+) + create mode 100644 sound/soc/bcm/rpi-dac.c + create mode 100644 sound/soc/codecs/pcm1794a.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index ef7c48d..be27073 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++static struct platform_device snd_rpi_dac_device = { ++ .name = "snd-rpi-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm1794a_codec_device = { ++ .name = "pcm1794a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -825,6 +839,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_dac_device); ++ bcm_register_device_dt(&snd_pcm1794a_codec_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a4a3e86..cb7c0c2 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -25,3 +25,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + select SND_SOC_PCM5102A + help + Say Y or M if you want to add support for HifiBerry DAC. ++ ++config SND_BCM2708_SOC_RPI_DAC ++ tristate "Support for RPi-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM1794A ++ help ++ Say Y or M if you want to add support for RPi-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index be90a49cb..ccc9809 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,5 +10,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-rpi-dac-objs := rpi-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c +new file mode 100644 +index 0000000..6d6e0ba +--- /dev/null ++++ b/sound/soc/bcm/rpi-dac.c +@@ -0,0 +1,97 @@ ++/* ++ * ASoC Driver for RPi-DAC. ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_rpi_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_rpi_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_rpi_dac_ops = { ++ .hw_params = snd_rpi_rpi_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = { ++{ ++ .name = "RPi-DAC", ++ .stream_name = "RPi-DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm1794a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm1794a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_rpi_dac_ops, ++ .init = snd_rpi_rpi_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_rpi_dac = { ++ .name = "snd_rpi_rpi_dac", ++ .dai_link = snd_rpi_rpi_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_rpi_dac_dai), ++}; ++ ++static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_rpi_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_rpi_dac); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_rpi_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_rpi_dac); ++} ++ ++static struct platform_driver snd_rpi_rpi_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-dac", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_rpi_dac_probe, ++ .remove = snd_rpi_rpi_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_rpi_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index a3d70f9..dc3df1a 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -84,6 +84,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM512x_SPI if SPI_MASTER + select SND_SOC_RT286 if I2C + select SND_SOC_PCM5102A if I2C ++ select SND_SOC_PCM1794A if I2C + select SND_SOC_RT5631 if I2C + select SND_SOC_RT5640 if I2C + select SND_SOC_RT5645 if I2C +@@ -512,6 +513,9 @@ config SND_SOC_RT286 + tristate + depends on I2C + ++config SND_SOC_PCM1794A ++ tristate ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index a0fda52..c1f6ba6 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -78,6 +78,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o + snd-soc-pcm512x-spi-objs := pcm512x-spi.o + snd-soc-rl6231-objs := rl6231.o + snd-soc-rt286-objs := rt286.o ++snd-soc-pcm1794a-objs := pcm1794a.o + snd-soc-pcm5102a-objs := pcm5102a.o + snd-soc-rt5631-objs := rt5631.o + snd-soc-rt5640-objs := rt5640.o +@@ -264,6 +265,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o ++obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o + obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o + obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o +diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c +new file mode 100644 +index 0000000..b4eaa44 +--- /dev/null ++++ b/sound/soc/codecs/pcm1794a.c +@@ -0,0 +1,62 @@ ++/* ++ * Driver for the PCM1794A codec ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver pcm1794a_dai = { ++ .name = "pcm1794a-hifi", ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_pcm1794a; ++ ++static int pcm1794a_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm1794a, ++ &pcm1794a_dai, 1); ++} ++ ++static int pcm1794a_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver pcm1794a_codec_driver = { ++ .probe = pcm1794a_probe, ++ .remove = pcm1794a_remove, ++ .driver = { ++ .name = "pcm1794a-codec", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(pcm1794a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From 0418e9bd3eab8e21b5d69ed0b7899dd5a80263f1 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:41:23 +0100 +Subject: [PATCH 41/77] 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 + additional mclk_div divider, it is now possible to control the behaviour. + This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It + should allow lower jitter and better signal quality. The behavior has to be + controlled by the sound card driver, because some sample frequency share the + same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only + difference is the MCLK divider. + +This also added support for 32bit data. + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 1e403f6..d4efa85 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, + blen = 0x1; + break; + case 24: ++ case 32: + blen = 0x2; + break; + default: +@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { + }; + + #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ +- SNDRV_PCM_FMTBIT_S24_LE) ++ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + +From 82c2f5a297701240bf5a77611d2d93c041497246 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:42:08 +0100 +Subject: [PATCH 42/77] ASoC: BCM:Add support for HiFiBerry Digi. Driver is + based on the patched WM8804 driver. + +Signed-off-by: Daniel Matuschek + +Add a parameter to turn off SPDIF output if no audio is playing + +This patch adds the paramater auto_shutdown_output to the kernel module. +Default behaviour of the module is the same, but when auto_shutdown_output +is set to 1, the SPDIF oputput will shutdown if no stream is playing. + +bugfix for 32kHz sample rate, was missing + +HiFiBerry Digi: set SPDIF status bits for sample rate + +The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. +While this is optional, some DACs and receivers do not accept this signal. This patch +adds the sample rate bits in the SPDIF status block. +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_digi.c | 201 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 210 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_digi.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index cb7c0c2..2e26e12 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + help + Say Y or M if you want to add support for HifiBerry DAC. + ++config SND_BCM2708_SOC_HIFIBERRY_DIGI ++ tristate "Support for HifiBerry Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index ccc9809..826df7d 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,7 +10,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +new file mode 100644 +index 0000000..92e9e46 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -0,0 +1,201 @@ ++/* ++ * ASoC Driver for HifiBerry Digi ++ * ++ * Author: Daniel Matuschek ++ * based on the HifiBerry DAC driver by Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8804.h" ++ ++static short int auto_shutdown_output = 0; ++module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++ ++static int samplerate=44100; ++ ++static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_digi_startup(struct snd_pcm_substream *substream) { ++ /* turn on digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { ++ /* turn off output */ ++ if (auto_shutdown_output) { ++ /* turn off output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ int sysclk = 27000000; /* This is fixed on this board */ ++ ++ long mclk_freq=0; ++ int mclk_div=1; ++ int sampling_freq=1; ++ ++ int ret; ++ ++ samplerate = params_rate(params); ++ ++ if (samplerate<=96000) { ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq=0x03; ++ break; ++ case 44100: ++ sampling_freq=0x00; ++ break; ++ case 48000: ++ sampling_freq=0x02; ++ break; ++ case 88200: ++ sampling_freq=0x08; ++ break; ++ case 96000: ++ sampling_freq=0x0a; ++ break; ++ case 176400: ++ sampling_freq=0x0c; ++ break; ++ case 192000: ++ sampling_freq=0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { ++ .hw_params = snd_rpi_hifiberry_digi_hw_params, ++ .startup = snd_rpi_hifiberry_digi_startup, ++ .shutdown = snd_rpi_hifiberry_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { ++{ ++ .name = "HifiBerry Digi", ++ .stream_name = "HifiBerry Digi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_hifiberry_digi_ops, ++ .init = snd_rpi_hifiberry_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_digi = { ++ .name = "snd_rpi_hifiberry_digi", ++ .dai_link = snd_rpi_hifiberry_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), ++}; ++ ++static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_digi.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_digi_driver = { ++ .driver = { ++ .name = "snd-hifiberry-digi", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_digi_probe, ++ .remove = snd_rpi_hifiberry_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); ++MODULE_LICENSE("GPL v2"); + +From df14e52cd5e411324c58e28ec158f503d4905dbb Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:26:08 +0100 +Subject: [PATCH 43/77] BCM2708: Added support for HiFiBerry Digi board Board + initalization by I2C + +Signed-off-by: Daniel Matuschek +--- + arch/arm/mach-bcm2708/bcm2708.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index be27073..2a33663 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,21 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++static struct platform_device snd_hifiberry_digi_device = { ++ .name = "snd-hifiberry-digi", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8804", 0x3b) ++ }, ++}; ++ ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", +@@ -839,6 +854,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_digi_device); ++ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); + +From d8de9644604c68b7148b023608d70d8ac3bf466f Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:36:35 +0100 +Subject: [PATCH 44/77] ASoC: wm8804: Set idle_bias_off to false Idle bias has + been change to remove warning on driver startup + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index d4efa85..f3f26a2 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -544,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { + }; + + static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { +- .idle_bias_off = true, ++ .idle_bias_off = false, + + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + +From 40f01186460630fa704c88adbefbc347e5e402e4 Mon Sep 17 00:00:00 2001 +From: Gordon Garrity +Date: Sat, 8 Mar 2014 16:56:57 +0000 +Subject: [PATCH 45/77] Add IQaudIO Sound Card support for Raspberry Pi + +Set a limit of 0dB on Digital Volume Control + +The main volume control in the PCM512x DAC has a range up to ++24dB. This is dangerously loud and can potentially cause massive +clipping in the output stages. Therefore this sets a sensible +limit of 0dB for this control. +--- + arch/arm/mach-bcm2708/bcm2708.c | 21 ++++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio-dac.c | 117 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 147 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio-dac.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 2a33663..957504e 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -681,6 +681,22 @@ static struct platform_device snd_pcm1794a_codec_device = { + }; + #endif + ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++static struct platform_device snd_rpi_iqaudio_dac_device = { ++ .name = "snd-rpi-iqaudio-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++// Use the actual device name rather than generic driver name ++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4c) ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -864,6 +880,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm1794a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 2e26e12..f6f8ec1 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -39,3 +39,10 @@ config SND_BCM2708_SOC_RPI_DAC + select SND_SOC_PCM1794A + help + Say Y or M if you want to add support for RPi-DAC. ++ ++config SND_BCM2708_SOC_IQAUDIO_DAC ++ tristate "Support for IQaudIO-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ help ++ Say Y or M if you want to add support for IQaudIO-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 826df7d..d597fb0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,7 +12,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +new file mode 100644 +index 0000000..aff7377 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -0,0 +1,117 @@ ++/* ++ * ASoC Driver for IQaudIO DAC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ ret = snd_soc_limit_volume(codec, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; ++// NOT USED struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { ++ .hw_params = snd_rpi_iqaudio_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { ++{ ++ .name = "IQaudIO DAC", ++ .stream_name = "IQaudIO DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_iqaudio_dac_ops, ++ .init = snd_rpi_iqaudio_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_dac = { ++ .name = "IQaudIODAC", ++ .dai_link = snd_rpi_iqaudio_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), ++}; ++ ++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); ++} ++ ++static const struct of_device_id iqaudio_of_match[] = { ++ { .compatible = "iqaudio,iqaudio-dac", }, ++ {}, ++}; ++ ++static struct platform_driver snd_rpi_iqaudio_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-iqaudio-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = iqaudio_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_dac_probe, ++ .remove = snd_rpi_iqaudio_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); ++MODULE_LICENSE("GPL v2"); + +From 5d1014e6dfa91f7f4b07851eefaa0a8bc544fda8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 18 Jun 2014 13:42:01 +0100 +Subject: [PATCH 46/77] vmstat: Workaround for issue where dirty page count + goes negative + +See: +https://github.com/raspberrypi/linux/issues/617 +http://www.spinics.net/lists/linux-mm/msg72236.html +--- + include/linux/vmstat.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h +index 82e7db7..f87d16d 100644 +--- a/include/linux/vmstat.h ++++ b/include/linux/vmstat.h +@@ -241,7 +241,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) + static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) + { + atomic_long_dec(&zone->vm_stat[item]); ++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&zone->vm_stat[item]) < 0)) ++ atomic_long_set(&zone->vm_stat[item], 0); + atomic_long_dec(&vm_stat[item]); ++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&vm_stat[item]) < 0)) ++ atomic_long_set(&vm_stat[item], 0); + } + + static inline void __inc_zone_page_state(struct page *page, + +From 462ac627ee409f190f5519727c80942afafd0d6d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 14 Jul 2014 22:02:09 +0100 +Subject: [PATCH 47/77] hid: Reduce default mouse polling interval to 60Hz + +Reduces overhead when using X +--- + drivers/hid/usbhid/hid-core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index bfbe1be..a738b25 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -49,7 +49,7 @@ + * Module parameters. + */ + +-static unsigned int hid_mousepoll_interval; ++static unsigned int hid_mousepoll_interval = ~0; + module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); + MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); + +@@ -1090,8 +1090,12 @@ static int usbhid_start(struct hid_device *hid) + } + + /* Change the polling interval of mice. */ +- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) +- interval = hid_mousepoll_interval; ++ if (hid->collection->usage == HID_GD_MOUSE) { ++ if (hid_mousepoll_interval == ~0 && interval < 16) ++ interval = 16; ++ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) ++ interval = hid_mousepoll_interval; ++ } + + ret = -ENOMEM; + if (usb_endpoint_dir_in(endpoint)) { + +From 6a68d9854eed6f1c5741aff8466cb5877deecd54 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 10:06:56 +0200 +Subject: [PATCH 48/77] 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. +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_dacplus.c | 119 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 147 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dacplus.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 957504e..90459b8 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++static struct platform_device snd_rpi_hifiberry_dacplus_device = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4d) ++ }, ++}; ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + static struct platform_device snd_hifiberry_digi_device = { + .name = "snd-hifiberry-digi", +@@ -870,6 +884,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + bcm_register_device_dt(&snd_hifiberry_digi_device); + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index f6f8ec1..8b45ac5 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + help + Say Y or M if you want to add support for HifiBerry DAC. + ++config SND_BCM2708_SOC_HIFIBERRY_DACPLUS ++ tristate "Support for HifiBerry DAC+" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x ++ help ++ Say Y or M if you want to add support for HifiBerry DAC+. ++ + config SND_BCM2708_SOC_HIFIBERRY_DIGI + tristate "Support for HifiBerry Digi" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index d597fb0..c02e3a2 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +new file mode 100644 +index 0000000..c63387b +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -0,0 +1,119 @@ ++/* ++ * ASoC Driver for HiFiBerry DAC+ ++ * ++ * Author: Daniel Matuschek ++ * Copyright 2014 ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/pcm512x.h" ++ ++static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++static int snd_rpi_hifiberry_dacplus_startup(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_dacplus_shutdown(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { ++ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, ++ .startup = snd_rpi_hifiberry_dacplus_startup, ++ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { ++{ ++ .name = "HiFiBerry DAC+", ++ .stream_name = "HiFiBerry DAC+ HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dacplus_ops, ++ .init = snd_rpi_hifiberry_dacplus_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dacplus = { ++ .name = "snd_rpi_hifiberry_dacplus", ++ .dai_link = snd_rpi_hifiberry_dacplus_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), ++}; ++ ++static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { ++ .driver = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_dacplus_probe, ++ .remove = snd_rpi_hifiberry_dacplus_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dacplus_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); ++MODULE_LICENSE("GPL v2"); + +From 1ca3777a5f3e17847136937e1bab1717281c73ca Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 11:09:58 +0200 +Subject: [PATCH 49/77] 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. + +TAS5713: return error if initialisation fails + +Existing TAS5713 driver logs errors during initialisation, but does not return +an error code. Therefore even if initialisation fails, the driver will still be +loaded, but won't work. This patch fixes this. I2C communication error will now +reported correctly by a non-zero return code. + +HiFiBerry Amp: fix device-tree problems + +Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 +++ + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_amp.c | 127 ++++++++++++++ + sound/soc/codecs/Kconfig | 4 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/tas5713.h | 210 +++++++++++++++++++++++ + 8 files changed, 740 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_amp.c + create mode 100644 sound/soc/codecs/tas5713.c + create mode 100644 sound/soc/codecs/tas5713.h + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 90459b8..785cf1a 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -681,6 +681,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { + + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++static struct platform_device snd_hifiberry_amp_device = { ++ .name = "snd-hifiberry-amp", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("tas5713", 0x1b) ++ }, ++}; ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", +@@ -894,6 +908,11 @@ void __init bcm2708_init(void) + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_amp_device); ++ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8b45ac5..bdcf12f 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. + ++config SND_BCM2708_SOC_HIFIBERRY_AMP ++ tristate "Support for the HifiBerry Amp" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_TAS5713 ++ help ++ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index c02e3a2..17ea2b0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o ++snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +new file mode 100644 +index 0000000..5903915 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_amp.c +@@ -0,0 +1,127 @@ ++/* ++ * ASoC Driver for HifiBerry AMP ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ // ToDo: init of the dsp-registers. ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params ) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { ++ .hw_params = snd_rpi_hifiberry_amp_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { ++ { ++ .name = "HifiBerry AMP", ++ .stream_name = "HifiBerry AMP HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tas5713-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tas5713.1-001b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_amp_ops, ++ .init = snd_rpi_hifiberry_amp_init, ++ }, ++}; ++ ++ ++static struct snd_soc_card snd_rpi_hifiberry_amp = { ++ .name = "snd_rpi_hifiberry_amp", ++ .dai_link = snd_rpi_hifiberry_amp_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), ++}; ++ ++static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-amp", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); ++ ++ ++static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_amp.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); ++ ++ if (ret != 0) { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); ++} ++ ++ ++static struct platform_driver snd_rpi_hifiberry_amp_driver = { ++ .driver = { ++ .name = "snd-hifiberry-amp", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_amp_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_amp_probe, ++ .remove = snd_rpi_hifiberry_amp_remove, ++}; ++ ++ ++module_platform_driver(snd_rpi_hifiberry_amp_driver); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index dc3df1a..8a9f07c 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -109,6 +109,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER ++ select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4 if I2C +@@ -623,6 +624,9 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C + ++config SND_SOC_TAS5713 ++ tristate ++ + config SND_SOC_TLV320AIC23 + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index c1f6ba6..8ebf7f1 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -109,6 +109,7 @@ snd-soc-sta529-objs := sta529.o + snd-soc-stac9766-objs := stac9766.o + snd-soc-tas5086-objs := tas5086.o + snd-soc-tfa9879-objs := tfa9879.o ++snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -293,6 +294,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o + obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o + obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o ++obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +new file mode 100644 +index 0000000..9b27138 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.c +@@ -0,0 +1,369 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "tas5713.h" ++ ++ ++static struct i2c_client *i2c; ++ ++struct tas5713_priv { ++ struct regmap *regmap; ++ int mclk_div; ++ struct snd_soc_codec *codec; ++}; ++ ++static struct tas5713_priv *priv_data; ++ ++ ++ ++ ++/* ++ * _ _ ___ _ ___ _ _ ++ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ ++ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< ++ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ ++ * ++ */ ++ ++static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); ++ ++ ++static const struct snd_kcontrol_new tas5713_snd_controls[] = { ++ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), ++ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) ++}; ++ ++ ++ ++ ++/* ++ * __ __ _ _ ___ _ ++ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ ++ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| ++ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ u16 blen = 0x00; ++ ++ struct snd_soc_codec *codec; ++ codec = dai->codec; ++ priv_data->codec = dai->codec; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ blen = 0x03; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ blen = 0x1; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ blen = 0x04; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ blen = 0x05; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported word length: %u\n", ++ params_format(params)); ++ return -EINVAL; ++ } ++ ++ // set word length ++ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); ++ ++ return 0; ++} ++ ++ ++static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ unsigned int val = 0; ++ ++ struct tas5713_priv *tas5713; ++ struct snd_soc_codec *codec = dai->codec; ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ if (mute) { ++ val = TAS5713_SOFT_MUTE_ALL; ++ } ++ ++ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); ++} ++ ++ ++static const struct snd_soc_dai_ops tas5713_dai_ops = { ++ .hw_params = tas5713_hw_params, ++ .mute_stream = tas5713_mute_stream, ++}; ++ ++ ++static struct snd_soc_dai_driver tas5713_dai = { ++ .name = "tas5713-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), ++ }, ++ .ops = &tas5713_dai_ops, ++}; ++ ++ ++ ++ ++/* ++ * ___ _ ___ _ ++ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ ++ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| ++ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_remove(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ return 0; ++} ++ ++ ++static int tas5713_probe(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ int i, ret; ++ ++ i2c = container_of(codec->dev, struct i2c_client, dev); ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Trim oscillator ++ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); ++ if (ret < 0) return ret; ++ msleep(1000); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Clock mode: 44/48kHz, MCLK=64xfs ++ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); ++ if (ret < 0) return ret; ++ ++ // I2S 24bit ++ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); ++ if (ret < 0) return ret; ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); ++ if (ret < 0) return ret; ++ ++ // Set volume to 0db ++ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); ++ if (ret < 0) return ret; ++ ++ // Now start programming the default initialization sequence ++ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { ++ ret = i2c_master_send(i2c, ++ tas5713_init_sequence[i].data, ++ tas5713_init_sequence[i].size); ++ if (ret < 0) { ++ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); ++ } ++ } ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { ++ .probe = tas5713_probe, ++ .remove = tas5713_remove, ++ .controls = tas5713_snd_controls, ++ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++}; ++ ++ ++ ++ ++/* ++ * ___ ___ ___ ___ _ ++ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ ++ * | | / / (__ | |) | '_| \ V / -_) '_| ++ * |___/___\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static const struct reg_default tas5713_reg_defaults[] = { ++ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB ++ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB ++ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB ++ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB ++}; ++ ++ ++static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case TAS5713_DEVICE_ID: ++ case TAS5713_ERROR_STATUS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++ ++static const struct of_device_id tas5713_of_match[] = { ++ { .compatible = "ti,tas5713", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, tas5713_of_match); ++ ++ ++static struct regmap_config tas5713_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .max_register = TAS5713_MAX_REGISTER, ++ .volatile_reg = tas5713_reg_volatile, ++ ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = tas5713_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), ++}; ++ ++ ++static int tas5713_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ int ret; ++ ++ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); ++ if (!priv_data) ++ return -ENOMEM; ++ ++ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); ++ if (IS_ERR(priv_data->regmap)) { ++ ret = PTR_ERR(priv_data->regmap); ++ return ret; ++ } ++ ++ i2c_set_clientdata(i2c, priv_data); ++ ++ ret = snd_soc_register_codec(&i2c->dev, ++ &soc_codec_dev_tas5713, &tas5713_dai, 1); ++ ++ return ret; ++} ++ ++ ++static int tas5713_i2c_remove(struct i2c_client *i2c) ++{ ++ snd_soc_unregister_codec(&i2c->dev); ++ i2c_set_clientdata(i2c, NULL); ++ ++ kfree(priv_data); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id tas5713_i2c_id[] = { ++ { "tas5713", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); ++ ++ ++static struct i2c_driver tas5713_i2c_driver = { ++ .driver = { ++ .name = "tas5713", ++ .owner = THIS_MODULE, ++ .of_match_table = tas5713_of_match, ++ }, ++ .probe = tas5713_i2c_probe, ++ .remove = tas5713_i2c_remove, ++ .id_table = tas5713_i2c_id ++}; ++ ++ ++static int __init tas5713_modinit(void) ++{ ++ int ret = 0; ++ ++ ret = i2c_add_driver(&tas5713_i2c_driver); ++ if (ret) { ++ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", ++ ret); ++ } ++ ++ return ret; ++} ++module_init(tas5713_modinit); ++ ++ ++static void __exit tas5713_exit(void) ++{ ++ i2c_del_driver(&tas5713_i2c_driver); ++} ++module_exit(tas5713_exit); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for TAS5713"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +new file mode 100644 +index 0000000..8f019e0 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.h +@@ -0,0 +1,210 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#ifndef _TAS5713_H ++#define _TAS5713_H ++ ++ ++// TAS5713 I2C-bus register addresses ++ ++#define TAS5713_CLOCK_CTRL 0x00 ++#define TAS5713_DEVICE_ID 0x01 ++#define TAS5713_ERROR_STATUS 0x02 ++#define TAS5713_SYSTEM_CTRL1 0x03 ++#define TAS5713_SERIAL_DATA_INTERFACE 0x04 ++#define TAS5713_SYSTEM_CTRL2 0x05 ++#define TAS5713_SOFT_MUTE 0x06 ++#define TAS5713_VOL_MASTER 0x07 ++#define TAS5713_VOL_CH1 0x08 ++#define TAS5713_VOL_CH2 0x09 ++#define TAS5713_VOL_HEADPHONE 0x0A ++#define TAS5713_VOL_CONFIG 0x0E ++#define TAS5713_MODULATION_LIMIT 0x10 ++#define TAS5713_IC_DLY_CH1 0x11 ++#define TAS5713_IC_DLY_CH2 0x12 ++#define TAS5713_IC_DLY_CH3 0x13 ++#define TAS5713_IC_DLY_CH4 0x14 ++ ++#define TAS5713_START_STOP_PERIOD 0x1A ++#define TAS5713_OSC_TRIM 0x1B ++#define TAS5713_BKND_ERR 0x1C ++ ++#define TAS5713_INPUT_MUX 0x20 ++#define TAS5713_SRC_SELECT_CH4 0x21 ++#define TAS5713_PWM_MUX 0x25 ++ ++#define TAS5713_CH1_BQ0 0x29 ++#define TAS5713_CH1_BQ1 0x2A ++#define TAS5713_CH1_BQ2 0x2B ++#define TAS5713_CH1_BQ3 0x2C ++#define TAS5713_CH1_BQ4 0x2D ++#define TAS5713_CH1_BQ5 0x2E ++#define TAS5713_CH1_BQ6 0x2F ++#define TAS5713_CH1_BQ7 0x58 ++#define TAS5713_CH1_BQ8 0x59 ++ ++#define TAS5713_CH2_BQ0 0x30 ++#define TAS5713_CH2_BQ1 0x31 ++#define TAS5713_CH2_BQ2 0x32 ++#define TAS5713_CH2_BQ3 0x33 ++#define TAS5713_CH2_BQ4 0x34 ++#define TAS5713_CH2_BQ5 0x35 ++#define TAS5713_CH2_BQ6 0x36 ++#define TAS5713_CH2_BQ7 0x5C ++#define TAS5713_CH2_BQ8 0x5D ++ ++#define TAS5713_CH4_BQ0 0x5A ++#define TAS5713_CH4_BQ1 0x5B ++#define TAS5713_CH3_BQ0 0x5E ++#define TAS5713_CH3_BQ1 0x5F ++ ++#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B ++#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C ++#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E ++#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F ++#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 ++#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 ++#define TAS5713_DRC_CTRL 0x46 ++ ++#define TAS5713_BANK_SW_CTRL 0x50 ++#define TAS5713_CH1_OUTPUT_MIXER 0x51 ++#define TAS5713_CH2_OUTPUT_MIXER 0x52 ++#define TAS5713_CH1_INPUT_MIXER 0x53 ++#define TAS5713_CH2_INPUT_MIXER 0x54 ++#define TAS5713_OUTPUT_POST_SCALE 0x56 ++#define TAS5713_OUTPUT_PRESCALE 0x57 ++ ++#define TAS5713_IDF_POST_SCALE 0x62 ++ ++#define TAS5713_CH1_INLINE_MIXER 0x70 ++#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 ++#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 ++#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 ++#define TAS5713_CH2_INLINE_MIXER 0x74 ++#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 ++#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 ++#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 ++ ++#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 ++#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 ++ ++#define TAS5713_REGISTER_COUNT 0x46 ++#define TAS5713_MAX_REGISTER 0xF9 ++ ++ ++// Bitmasks for registers ++#define TAS5713_SOFT_MUTE_ALL 0x07 ++ ++ ++ ++struct tas5713_init_command { ++ const int size; ++ const char *const data; ++}; ++ ++static const struct tas5713_init_command tas5713_init_sequence[] = { ++ ++ // Trim oscillator ++ { .size = 2, .data = "\x1B\x00" }, ++ // System control register 1 (0x03): block DC ++ { .size = 2, .data = "\x03\x80" }, ++ // Mute everything ++ { .size = 2, .data = "\x05\x40" }, ++ // Modulation limit register (0x10): 97.7% ++ { .size = 2, .data = "\x10\x02" }, ++ // Interchannel delay registers ++ // (0x11, 0x12, 0x13, and 0x14): BD mode ++ { .size = 2, .data = "\x11\xB8" }, ++ { .size = 2, .data = "\x12\x60" }, ++ { .size = 2, .data = "\x13\xA0" }, ++ { .size = 2, .data = "\x14\x48" }, ++ // PWM shutdown group register (0x19): no shutdown ++ { .size = 2, .data = "\x19\x00" }, ++ // Input multiplexer register (0x20): BD mode ++ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, ++ // PWM output mux register (0x25) ++ // Channel 1 --> OUTA, channel 1 neg --> OUTB ++ // Channel 2 --> OUTC, channel 2 neg --> OUTD ++ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, ++ // DRC control (0x46): DRC off ++ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, ++ // BKND_ERR register (0x1C): 299ms reset period ++ { .size = 2, .data = "\x1C\x07" }, ++ // Mute channel 3 ++ { .size = 2, .data = "\x0A\xFF" }, ++ // Volume configuration register (0x0E): volume slew 512 steps ++ { .size = 2, .data = "\x0E\x90" }, ++ // Clock control register (0x00): 44/48kHz, MCLK=64xfs ++ { .size = 2, .data = "\x00\x60" }, ++ // Bank switch and eq control (0x50): no bank switching ++ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, ++ // Volume registers (0x07, 0x08, 0x09, 0x0A) ++ { .size = 2, .data = "\x07\x20" }, ++ { .size = 2, .data = "\x08\x30" }, ++ { .size = 2, .data = "\x09\x30" }, ++ { .size = 2, .data = "\x0A\xFF" }, ++ // 0x72, 0x73, 0x76, 0x77 input mixer: ++ // no intermix between channels ++ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, ++ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: ++ // no inline DRC inmix ++ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, ++ // 0x56, 0x57 Output scale ++ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, ++ // 0x3B, 0x3c ++ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ // 0x51, 0x52: output mixer ++ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ // PEQ defaults ++ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++}; ++ ++ ++#endif /* _TAS5713_H */ + +From 06c9b132b1340b495048f8814be13fe71b5cd77e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Apr 2015 19:14:18 +0100 +Subject: [PATCH 50/77] bcm2708: Allow option card devices to be configured via + DT + +If the kernel is built with Device Tree support, and if a DT blob +is provided for the kernel at boot time, then the platform devices +for option cards are not created. This avoids both the need to +blacklist unwanted devices, and the need to update the board +support code with each new device. +--- + sound/soc/bcm/bcm2835-i2s.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 03fa1cb..c816526 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -861,6 +861,7 @@ static const struct of_device_id bcm2835_i2s_of_match[] = { + { .compatible = "brcm,bcm2835-i2s", }, + {}, + }; ++MODULE_DEVICE_TABLE(of, bcm2835_i2s_of_match); + + static struct platform_driver bcm2835_i2s_driver = { + .probe = bcm2835_i2s_probe, + +From a9fff3c9005e6658977bd5e7df92114e70e1f813 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 13 Apr 2015 18:45:39 +0100 +Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards + +--- + arch/arm/mach-bcm2709/bcm2709.c | 143 ++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/hifiberry_dac.c | 22 ++++++ + sound/soc/bcm/hifiberry_dacplus.c | 22 ++++++ + sound/soc/bcm/hifiberry_digi.c | 22 ++++++ + sound/soc/bcm/iqaudio-dac.c | 16 +++++ + sound/soc/codecs/pcm5102a.c | 7 ++ + 6 files changed, 232 insertions(+) + +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 03e208b..2ae79d9 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -636,6 +636,115 @@ static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++static struct resource bcm2708_i2s_resources[] = { ++ { ++ .start = I2S_BASE, ++ .end = I2S_BASE + 0x20, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = PCM_CLOCK_BASE, ++ .end = PCM_CLOCK_BASE + 0x02, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device bcm2708_i2s_device = { ++ .name = "bcm2708-i2s", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), ++ .resource = bcm2708_i2s_resources, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++static struct platform_device snd_hifiberry_dac_device = { ++ .name = "snd-hifiberry-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm5102a_codec_device = { ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++static struct platform_device snd_rpi_hifiberry_dacplus_device = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4d) ++ }, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++static struct platform_device snd_hifiberry_digi_device = { ++ .name = "snd-hifiberry-digi", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8804", 0x3b) ++ }, ++}; ++ ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++static struct platform_device snd_hifiberry_amp_device = { ++ .name = "snd-hifiberry-amp", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("tas5713", 0x1b) ++ }, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++static struct platform_device snd_rpi_dac_device = { ++ .name = "snd-rpi-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm1794a_codec_device = { ++ .name = "pcm1794a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++static struct platform_device snd_rpi_iqaudio_dac_device = { ++ .name = "snd-rpi-iqaudio-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++// Use the actual device name rather than generic driver name ++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4c) ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -800,6 +909,40 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2835_thermal_device); + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++ bcm_register_device_dt(&bcm2708_i2s_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_dac_device); ++ bcm_register_device_dt(&snd_pcm5102a_codec_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_digi_device); ++ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_amp_device); ++ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_dac_device); ++ bcm_register_device_dt(&snd_pcm1794a_codec_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c +index 4b70b45..3ab0f47 100644 +--- a/sound/soc/bcm/hifiberry_dac.c ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -72,6 +72,21 @@ static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +@@ -84,10 +99,17 @@ static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); + } + ++static const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_dac_driver = { + .driver = { + .name = "snd-hifiberry-dac", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dac_of_match, + }, + .probe = snd_rpi_hifiberry_dac_probe, + .remove = snd_rpi_hifiberry_dac_remove, +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +index c63387b..11e4f39 100644 +--- a/sound/soc/bcm/hifiberry_dacplus.c ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -90,6 +90,21 @@ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dacplus_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); + if (ret) + dev_err(&pdev->dev, +@@ -103,10 +118,17 @@ static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); + } + ++static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dacplus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { + .driver = { + .name = "snd-rpi-hifiberry-dacplus", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, + }, + .probe = snd_rpi_hifiberry_dacplus_probe, + .remove = snd_rpi_hifiberry_dacplus_remove, +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +index 92e9e46..80732b8 100644 +--- a/sound/soc/bcm/hifiberry_digi.c ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -173,6 +173,21 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_digi.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +@@ -185,10 +200,17 @@ static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); + } + ++static const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_digi_driver = { + .driver = { + .name = "snd-hifiberry-digi", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_digi_of_match, + }, + .probe = snd_rpi_hifiberry_digi_probe, + .remove = snd_rpi_hifiberry_digi_remove, +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +index aff7377..a38e874 100644 +--- a/sound/soc/bcm/iqaudio-dac.c ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -82,6 +82,21 @@ static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); + if (ret) + dev_err(&pdev->dev, +@@ -99,6 +114,7 @@ static const struct of_device_id iqaudio_of_match[] = { + { .compatible = "iqaudio,iqaudio-dac", }, + {}, + }; ++MODULE_DEVICE_TABLE(of, iqaudio_of_match); + + static struct platform_driver snd_rpi_iqaudio_dac_driver = { + .driver = { +diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c +index 126f1e9..7c6598e 100644 +--- a/sound/soc/codecs/pcm5102a.c ++++ b/sound/soc/codecs/pcm5102a.c +@@ -47,12 +47,19 @@ static int pcm5102a_remove(struct platform_device *pdev) + return 0; + } + ++static const struct of_device_id pcm5102a_of_match[] = { ++ { .compatible = "ti,pcm5102a", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcm5102a_of_match); ++ + static struct platform_driver pcm5102a_codec_driver = { + .probe = pcm5102a_probe, + .remove = pcm5102a_remove, + .driver = { + .name = "pcm5102a-codec", + .owner = THIS_MODULE, ++ .of_match_table = pcm5102a_of_match, + }, + }; + + +From 9518bd237c4fb516a0ec78f7ec81e5784f8425e0 Mon Sep 17 00:00:00 2001 +From: Timo Kokkonen +Date: Wed, 29 Oct 2014 23:30:30 -0700 +Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used + from pps-gpio module (LinuxPPS). Enable PPS modules in default config for + RPi. + +--- + arch/arm/mach-bcm2708/bcm2708.c | 27 +++++++++++++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 785cf1a..e42f5a5 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -92,6 +93,7 @@ static unsigned reboot_part = 0; + static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; ++static int pps_gpio_pin = -1; + + static unsigned use_dt = 0; + +@@ -325,6 +327,19 @@ static struct platform_device w1_device = { + }; + #endif + ++static struct pps_gpio_platform_data pps_gpio_info = { ++ .assert_falling_edge = false, ++ .capture_clear = false, ++ .gpio_pin = -1, ++ .gpio_label = "PPS", ++}; ++ ++static struct platform_device pps_gpio_device = { ++ .name = "pps-gpio", ++ .id = PLATFORM_DEVID_NONE, ++ .dev.platform_data = &pps_gpio_info, ++}; ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -860,6 +875,16 @@ void __init bcm2708_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++ ++#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) ++ if (!use_dt && (pps_gpio_pin >= 0)) { ++ pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); ++ pps_gpio_info.gpio_pin = pps_gpio_pin; ++ pps_gpio_device.id = pps_gpio_pin; ++ bcm_register_device(&pps_gpio_device); ++ } ++#endif ++ + #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; +@@ -1116,3 +1141,5 @@ module_param(w1_gpio_pin, uint, 0644); + module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); ++module_param(pps_gpio_pin, int, 0644); ++MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 2ae79d9..95223ff 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -94,6 +95,7 @@ static unsigned reboot_part = 0; + static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; ++static int pps_gpio_pin = -1; + + static unsigned use_dt = 0; + +@@ -335,6 +337,19 @@ static struct platform_device w1_device = { + }; + #endif + ++static struct pps_gpio_platform_data pps_gpio_info = { ++ .assert_falling_edge = false, ++ .capture_clear = false, ++ .gpio_pin = -1, ++ .gpio_label = "PPS", ++}; ++ ++static struct platform_device pps_gpio_device = { ++ .name = "pps-gpio", ++ .id = PLATFORM_DEVID_NONE, ++ .dev.platform_data = &pps_gpio_info, ++}; ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -880,6 +895,16 @@ void __init bcm2709_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++ ++#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) ++ if (!use_dt && (pps_gpio_pin >= 0)) { ++ pr_info("bcm2709: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); ++ pps_gpio_info.gpio_pin = pps_gpio_pin; ++ pps_gpio_device.id = pps_gpio_pin; ++ bcm_register_device(&pps_gpio_device); ++ } ++#endif ++ + #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; +@@ -1284,3 +1309,5 @@ module_param(w1_gpio_pin, uint, 0644); + module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); ++module_param(pps_gpio_pin, int, 0644); ++MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); + +From 6831eded602a01774036cb24d3195dbbd51f9135 Mon Sep 17 00:00:00 2001 +From: Ryan Coe +Date: Sat, 31 Jan 2015 18:25:49 -0700 +Subject: [PATCH 53/77] Update ds1307 driver for device-tree support + +Signed-off-by: Ryan Coe +--- + drivers/rtc/rtc-ds1307.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 4ffabb3..c6789a7 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1242,6 +1242,14 @@ static int ds1307_remove(struct i2c_client *client) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id ds1307_of_match[] = { ++ { .compatible = "maxim,ds1307" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ds1307_of_match); ++#endif ++ + static struct i2c_driver ds1307_driver = { + .driver = { + .name = "rtc-ds1307", + +From 47ca2482bc03a888435d35139cd2f5989354ee1b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 6 Feb 2015 13:50:57 +0000 +Subject: [PATCH 54/77] BCM270x_DT: Add pwr_led, and the required "input" + trigger + +The "input" trigger makes the associated GPIO an input. This is to support +the Raspberry Pi PWR LED, which is driven by external hardware in normal use. + +N.B. pwr_led is not available on Model A or B boards. +--- + drivers/leds/trigger/Kconfig | 7 ++++ + drivers/leds/trigger/Makefile | 1 + + drivers/leds/trigger/ledtrig-input.c | 65 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 73 insertions(+) + create mode 100644 drivers/leds/trigger/ledtrig-input.c + diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..640756b 100644 --- a/drivers/leds/trigger/Kconfig @@ -124668,10 +127463,10 @@ index 0000000..2ca2b98 +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); -From be825a324f0b4e90f3fc396b0ed17442c5cb771d Mon Sep 17 00:00:00 2001 +From 38c278bba1388423ba1508d0712babb717685530 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Jun 2014 17:19:27 +0100 -Subject: [PATCH 072/216] bcm2709: Simplify and strip down IRQ handler +Subject: [PATCH 55/77] bcm2709: Simplify and strip down IRQ handler --- arch/arm/include/asm/entry-macro-multi.S | 2 + @@ -124890,737 +127685,10 @@ index d08591b..08d184c 100644 +1: get_irqnr_and_base r0, r2, r6, lr + .endm -From 219ae1b83de018ba2a3e3d909c0cbfce14579c14 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Tue, 3 Feb 2015 07:15:19 +0100 -Subject: [PATCH 073/216] HiFiBerry Amp: fix device-tree problems - -Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. ---- - sound/soc/bcm/hifiberry_amp.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -index 1e87ee06..5903915 100644 ---- a/sound/soc/bcm/hifiberry_amp.c -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -65,6 +65,12 @@ static struct snd_soc_card snd_rpi_hifiberry_amp = { - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), - }; - -+static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-amp", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -+ - - static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) - { -@@ -72,6 +78,20 @@ static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) - - snd_rpi_hifiberry_amp.dev = &pdev->dev; - -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); - - if (ret != 0) { -@@ -92,6 +112,7 @@ static struct platform_driver snd_rpi_hifiberry_amp_driver = { - .driver = { - .name = "snd-hifiberry-amp", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_amp_of_match, - }, - .probe = snd_rpi_hifiberry_amp_probe, - .remove = snd_rpi_hifiberry_amp_remove, - -From 81042a79740e7b0c61fcbfa97e76c3d97c40b630 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 3 Feb 2015 11:41:38 +0000 -Subject: [PATCH 074/216] BCM270x_DT: Add i2c0_baudrate and i2c1_baudrate - parameters - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 3 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index b409c2c..7f84473 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -103,6 +103,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 1ecd1a1..a39562f 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -97,6 +97,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 46f4908..75c222f 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -103,6 +103,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - -From 4ff8b4c54db8215c8daa7a1d70c623b642143f16 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 4 Feb 2015 10:02:24 +0000 -Subject: [PATCH 075/216] pinctrl-bcm2835: bcm2835_gpio_direction_output must - set the value - ---- - drivers/pinctrl/pinctrl-bcm2835.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index 9d1149e..d9c727b 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -355,7 +355,14 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) - static int bcm2835_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) - { -- return pinctrl_gpio_direction_output(chip->base + offset); -+ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev); -+ int ret; -+ -+ ret = pinctrl_gpio_direction_output(chip->base + offset); -+ if (ret >= 0) -+ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset); -+ -+ return ret; - } - - static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) - -From 1184251f953b0cd578ee44fa36d67f7f9091e6a5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 4 Feb 2015 12:59:36 +0000 -Subject: [PATCH 076/216] w1-gpio: Sort out the pullup/parasitic power tangle - ---- - arch/arm/boot/dts/w1-gpio-overlay.dts | 4 +++- - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 6 +++-- - drivers/w1/masters/w1-gpio.c | 36 ++++++++++++++++++---------- - include/linux/w1-gpio.h | 1 + - 4 files changed, 32 insertions(+), 15 deletions(-) - -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -index b2c5ee2..29a3b48 100644 ---- a/arch/arm/boot/dts/w1-gpio-overlay.dts -+++ b/arch/arm/boot/dts/w1-gpio-overlay.dts -@@ -1,4 +1,4 @@ --// Definitions for lirc-rpi module -+// Definitions for w1-gpio module (without external pullup) - /dts-v1/; - /plugin/; - -@@ -14,6 +14,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&w1_pins>; - gpios = <&gpio 4 0>; -+ rpi,parasitic-power = <0>; - status = "okay"; - }; - }; -@@ -33,5 +34,6 @@ - __overrides__ { - gpiopin = <&w1>,"gpios:4", - <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; - }; - }; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -index b3e97c2..66a98f6 100644 ---- a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -+++ b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -@@ -1,4 +1,4 @@ --// Definitions for lirc-rpi module -+// Definitions for w1-gpio module (with external pullup) - /dts-v1/; - /plugin/; - -@@ -14,6 +14,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&w1_pins>; - gpios = <&gpio 4 0>, <&gpio 5 1>; -+ rpi,parasitic-power = <0>; - status = "okay"; - }; - }; -@@ -33,7 +34,8 @@ - __overrides__ { - gpiopin = <&w1>,"gpios:4", - <&w1_pins>,"brcm,pins:0"; -- pullup = <&w1>,"gpios:16", -+ extpullup = <&w1>,"gpios:16", - <&w1_pins>,"brcm,pins:4"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; - }; - }; -diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c -index 3ad15cc..e34d418 100644 ---- a/drivers/w1/masters/w1-gpio.c -+++ b/drivers/w1/masters/w1-gpio.c -@@ -23,10 +23,14 @@ - #include "../w1.h" - #include "../w1_int.h" - --static int w1_gpio_pullup = -1; --static int w1_gpio_pullup_orig = -1; -+static int w1_gpio_pullup = 0; -+static int w1_gpio_pullup_orig = 0; - module_param_named(pullup, w1_gpio_pullup, int, 0); --MODULE_PARM_DESC(pullup, "GPIO pin pullup number"); -+MODULE_PARM_DESC(pullup, "Enable parasitic power (power on data) mode"); -+static int w1_gpio_pullup_pin = -1; -+static int w1_gpio_pullup_pin_orig = -1; -+module_param_named(extpullup, w1_gpio_pullup_pin, int, 0); -+MODULE_PARM_DESC(extpullup, "GPIO external pullup pin number"); - static int w1_gpio_pin = -1; - static int w1_gpio_pin_orig = -1; - module_param_named(gpiopin, w1_gpio_pin, int, 0); -@@ -99,6 +103,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; - int gpio; -+ u32 value; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) -@@ -107,6 +112,9 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - if (of_get_property(np, "linux,open-drain", NULL)) - pdata->is_open_drain = 1; - -+ if (of_property_read_u32(np, "rpi,parasitic-power", &value) == 0) -+ pdata->parasitic_power = (value != 0); -+ - gpio = of_get_gpio(np, 0); - if (gpio < 0) { - if (gpio != -EPROBE_DEFER) -@@ -122,7 +130,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - if (gpio == -EPROBE_DEFER) - return gpio; - /* ignore other errors as the pullup gpio is optional */ -- pdata->ext_pullup_enable_pin = gpio; -+ pdata->ext_pullup_enable_pin = (gpio >= 0) ? gpio : -1; - - pdev->dev.platform_data = pdata; - -@@ -158,17 +166,20 @@ static int w1_gpio_probe(struct platform_device *pdev) - } - - w1_gpio_pin_orig = pdata->pin; -- w1_gpio_pullup_orig = pdata->ext_pullup_enable_pin; -+ w1_gpio_pullup_pin_orig = pdata->ext_pullup_enable_pin; -+ w1_gpio_pullup_orig = pdata->parasitic_power; - - if(gpio_is_valid(w1_gpio_pin)) { - pdata->pin = w1_gpio_pin; - pdata->ext_pullup_enable_pin = -1; -+ pdata->parasitic_power = -1; - } -- if(gpio_is_valid(w1_gpio_pullup)) { -- pdata->ext_pullup_enable_pin = w1_gpio_pullup; -+ pdata->parasitic_power |= w1_gpio_pullup; -+ if(gpio_is_valid(w1_gpio_pullup_pin)) { -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin; - } - -- dev_info(&pdev->dev, "gpio pin %d, gpio pullup pin %d\n", pdata->pin, pdata->ext_pullup_enable_pin); -+ dev_info(&pdev->dev, "gpio pin %d, external pullup pin %d, parasitic power %d\n", pdata->pin, pdata->ext_pullup_enable_pin, pdata->parasitic_power); - - err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); - if (err) { -@@ -199,10 +210,10 @@ static int w1_gpio_probe(struct platform_device *pdev) - master->set_pullup = w1_gpio_set_pullup; - } - -- if (gpio_is_valid(w1_gpio_pullup)) { -+ if (pdata->parasitic_power) { - if (pdata->is_open_drain) -- printk(KERN_ERR "w1-gpio 'pullup' option " -- "doesn't work with open drain GPIO\n"); -+ printk(KERN_ERR "w1-gpio 'pullup'(parasitic power) " -+ "option doesn't work with open drain GPIO\n"); - else - master->bitbang_pullup = w1_gpio_bitbang_pullup; - } -@@ -238,7 +249,8 @@ static int w1_gpio_remove(struct platform_device *pdev) - w1_remove_master_device(master); - - pdata->pin = w1_gpio_pin_orig; -- pdata->ext_pullup_enable_pin = w1_gpio_pullup_orig; -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin_orig; -+ pdata->parasitic_power = w1_gpio_pullup_orig; - - return 0; - } -diff --git a/include/linux/w1-gpio.h b/include/linux/w1-gpio.h -index d58594a..feae942 100644 ---- a/include/linux/w1-gpio.h -+++ b/include/linux/w1-gpio.h -@@ -18,6 +18,7 @@ - struct w1_gpio_platform_data { - unsigned int pin; - unsigned int is_open_drain:1; -+ unsigned int parasitic_power:1; - void (*enable_external_pullup)(int enable); - unsigned int ext_pullup_enable_pin; - unsigned int pullup_duration; - -From a0d0e3ba49f5daa0ece5234cdf688fb490ee15a7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 5 Feb 2015 16:01:44 +0000 -Subject: [PATCH 077/216] i2c_bcm2708: Fix clock reference counting - ---- - drivers/i2c/busses/i2c-bcm2708.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 526129b..fda59ba 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -337,11 +337,17 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - return PTR_ERR(clk); - } - -+ err = clk_prepare_enable(clk); -+ if (err) { -+ dev_err(&pdev->dev, "could not enable clk: %d\n", err); -+ goto out_clk_put; -+ } -+ - bcm2708_i2c_init_pinmode(pdev->id); - - bi = kzalloc(sizeof(*bi), GFP_KERNEL); - if (!bi) -- goto out_clk_put; -+ goto out_clk_disable; - - platform_set_drvdata(pdev, bi); - -@@ -412,6 +418,8 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - iounmap(bi->base); - out_free_bi: - kfree(bi); -+out_clk_disable: -+ clk_disable_unprepare(clk); - out_clk_put: - clk_put(clk); - return err; -@@ -426,7 +434,7 @@ static int bcm2708_i2c_remove(struct platform_device *pdev) - i2c_del_adapter(&bi->adapter); - free_irq(bi->irq, bi); - iounmap(bi->base); -- clk_disable(bi->clk); -+ clk_disable_unprepare(bi->clk); - clk_put(bi->clk); - kfree(bi); - - -From dffb6179317e46f3f2d60c62b6b4c6c1008990ef Mon Sep 17 00:00:00 2001 -From: Byron Bradley -Date: Fri, 6 Feb 2015 14:19:41 +0000 -Subject: [PATCH 078/216] Add device-tree overlay for pcf2127 - -Signed-off-by: Byron Bradley ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pcf2127-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/pcf2127-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 7755a84..6cb743a 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -20,6 +20,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -new file mode 100644 -index 0000000..01fc81d ---- /dev/null -+++ b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF2127 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From 6547e99ab9f5be7bc839f36becfc18e6dd879d0d Mon Sep 17 00:00:00 2001 -From: android -Date: Mon, 25 Aug 2014 13:18:21 +0100 -Subject: [PATCH 079/216] BCM2708_VCIO : Add automatic creation of device node - ---- - arch/arm/mach-bcm2708/vcio.c | 12 +++++++++++- - arch/arm/mach-bcm2709/vcio.c | 12 +++++++++++- - 2 files changed, 22 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 5e43e85..700bff4 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -61,7 +61,7 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de -- -+static struct class *vcio_class = NULL; - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -421,6 +421,13 @@ static int bcm_vcio_probe(struct platform_device *pdev) - "Failed registering the character device %d\n", ret); - return ret; - } -+ vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ return ret ; -+ } -+ device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); - } - return ret; - } -@@ -462,6 +469,9 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -+ device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -index 5e43e85..700bff4 100644 ---- a/arch/arm/mach-bcm2709/vcio.c -+++ b/arch/arm/mach-bcm2709/vcio.c -@@ -61,7 +61,7 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de -- -+static struct class *vcio_class = NULL; - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -421,6 +421,13 @@ static int bcm_vcio_probe(struct platform_device *pdev) - "Failed registering the character device %d\n", ret); - return ret; - } -+ vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ return ret ; -+ } -+ device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); - } - return ret; - } -@@ -462,6 +469,9 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -+ device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - - -From 05b37dedc10f2da009b868c101623c742eda1c3f Mon Sep 17 00:00:00 2001 -From: jeanleflambeur -Date: Sun, 1 Feb 2015 12:35:38 +0100 -Subject: [PATCH 080/216] Fix grabbing lock from atomic context in i2c driver - -2 main changes: -- check for timeouts in the bcm2708_bsc_setup function as indicated by this comment: - /* poll for transfer start bit (should only take 1-20 polls) */ - This implies that the setup function can now fail so account for this everywhere it's called -- Removed the clk_get_rate call from inside the setup function as it locks a mutex and that's not ok since we call it from under a spin lock. - -removed dead code and update comment - -fixed typo in comment ---- - drivers/i2c/busses/i2c-bcm2708.c | 90 +++++++++++++++++++++++++++++----------- - 1 file changed, 65 insertions(+), 25 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index fda59ba..81e9374 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -68,6 +68,7 @@ - #define BSC_S_TA 0x00000001 - - #define I2C_TIMEOUT_MS 150 -+#define I2C_WAIT_LOOP_COUNT 40 - - #define DRV_NAME "bcm2708_i2c" - -@@ -86,6 +87,7 @@ struct bcm2708_i2c { - void __iomem *base; - int irq; - struct clk *clk; -+ u32 cdiv; - - struct completion done; - -@@ -109,10 +111,10 @@ static void bcm2708_i2c_init_pinmode(int id) - int pin; - u32 *gpio = ioremap(GPIO_BASE, SZ_16K); - -- BUG_ON(id != 0 && id != 1); -+ BUG_ON(id != 0 && id != 1); - /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ - for (pin = id*2+0; pin <= id*2+1; pin++) { --printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); -+ printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); - INP_GPIO(pin); /* set mode to GPIO input first */ - SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ - } -@@ -151,16 +153,16 @@ static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) - bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); - } - --static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) -+static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi) - { -- unsigned long bus_hz; - u32 cdiv, s; - u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; -+ int wait_loops = I2C_WAIT_LOOP_COUNT; - -- bus_hz = clk_get_rate(bi->clk); -- cdiv = bus_hz / baudrate; -- if (cdiv > 0xffff) -- cdiv = 0xffff; -+ /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked. -+ * Use the value that we cached in the probe. -+ */ -+ cdiv = bi->cdiv; - - if (bi->msg->flags & I2C_M_RD) - c |= BSC_C_INTR | BSC_C_READ; -@@ -177,17 +179,25 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) - - Both messages to same slave address - - Write message can fit inside FIFO (16 bytes or less) */ - if ( (bi->nmsgs > 1) && -- !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -- (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { -+ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -+ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { - /* Fill FIFO with entire write message (16 byte FIFO) */ -- while (bi->pos < bi->msg->len) -+ while (bi->pos < bi->msg->len) { - bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+ } - /* Start write transfer (no interrupts, don't clear FIFO) */ - bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); -+ - /* poll for transfer start bit (should only take 1-20 polls) */ - do { - s = bcm2708_rd(bi, BSC_S); -- } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE))); -+ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0); -+ -+ /* did we time out or some error occured? */ -+ if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) { -+ return -1; -+ } -+ - /* Send next read message before the write transfer finishes. */ - bi->nmsgs--; - bi->msg++; -@@ -197,6 +207,8 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) - } - } - bcm2708_wr(bi, BSC_C, c); -+ -+ return 0; - } - - static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) -@@ -204,13 +216,15 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - struct bcm2708_i2c *bi = dev_id; - bool handled = true; - u32 s; -+ int ret; - - spin_lock(&bi->lock); - - /* we may see camera interrupts on the "other" I2C channel -- Just return if we've not sent anything */ -- if (!bi->nmsgs || !bi->msg ) -+ Just return if we've not sent anything */ -+ if (!bi->nmsgs || !bi->msg) { - goto early_exit; -+ } - - s = bcm2708_rd(bi, BSC_S); - -@@ -218,13 +232,16 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - bcm2708_bsc_reset(bi); - bi->error = true; - -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; - /* wake up our bh */ - complete(&bi->done); - } else if (s & BSC_S_DONE) { - bi->nmsgs--; - -- if (bi->msg->flags & I2C_M_RD) -+ if (bi->msg->flags & I2C_M_RD) { - bcm2708_bsc_fifo_drain(bi); -+ } - - bcm2708_bsc_reset(bi); - -@@ -232,8 +249,19 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - /* advance to next message */ - bi->msg++; - bi->pos = 0; -- bcm2708_bsc_setup(bi); -+ ret = bcm2708_bsc_setup(bi); -+ if (ret < 0) { -+ bcm2708_bsc_reset(bi); -+ bi->error = true; -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; -+ /* wake up our bh */ -+ complete(&bi->done); -+ goto early_exit; -+ } - } else { -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; - /* wake up our bh */ - complete(&bi->done); - } -@@ -266,22 +294,33 @@ static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, - bi->nmsgs = num; - bi->error = false; - -- bcm2708_bsc_setup(bi); -+ ret = bcm2708_bsc_setup(bi); - -- /* unlockig _after_ the setup to avoid races with the interrupt routine */ - spin_unlock_irqrestore(&bi->lock, flags); - -- ret = wait_for_completion_timeout(&bi->done, -- msecs_to_jiffies(I2C_TIMEOUT_MS)); -+ /* check the result of the setup */ -+ if (ret < 0) -+ { -+ dev_err(&adap->dev, "transfer setup timed out\n"); -+ goto error_timeout; -+ } -+ -+ ret = wait_for_completion_timeout(&bi->done, msecs_to_jiffies(I2C_TIMEOUT_MS)); - if (ret == 0) { - dev_err(&adap->dev, "transfer timed out\n"); -- spin_lock_irqsave(&bi->lock, flags); -- bcm2708_bsc_reset(bi); -- spin_unlock_irqrestore(&bi->lock, flags); -- return -ETIMEDOUT; -+ goto error_timeout; - } - -- return bi->error ? -EIO : num; -+ ret = bi->error ? -EIO : num; -+ return ret; -+ -+error_timeout: -+ spin_lock_irqsave(&bi->lock, flags); -+ bcm2708_bsc_reset(bi); -+ bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */ -+ bi->nmsgs = 0; -+ spin_unlock_irqrestore(&bi->lock, flags); -+ return -ETIMEDOUT; - } - - static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) -@@ -406,6 +445,7 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - cdiv = 0xffff; - baudrate = bus_hz / cdiv; - } -+ bi->cdiv = cdiv; - - dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", - pdev->id, (unsigned long)regs->start, irq, baudrate); - -From 2e3d8378c9031150eda4fd030b14d6c4ea762786 Mon Sep 17 00:00:00 2001 +From a69146643bae1215ab2860b9646f0f380bd3c50f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Feb 2015 11:17:53 +0000 -Subject: [PATCH 081/216] Fix LED "input" trigger implementation for 3.19 +Subject: [PATCH 56/77] Fix LED "input" trigger implementation for 3.19 --- drivers/leds/leds-gpio.c | 10 +++++++++- @@ -125629,7 +127697,7 @@ Subject: [PATCH 081/216] Fix LED "input" trigger implementation for 3.19 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index d26af0a..9e49c72 100644 +index 15eb3f8..3cfbd6a 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -41,6 +41,13 @@ static void gpio_led_work(struct work_struct *work) @@ -125693,13 +127761,13 @@ index 2ca2b98..07d1219 100644 static struct led_trigger input_led_trigger = { diff --git a/include/linux/leds.h b/include/linux/leds.h -index f70f84f..f3fcaa1 100644 +index 9a2b000..60accc5 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -48,6 +48,9 @@ struct led_classdev { +@@ -47,6 +47,9 @@ struct led_classdev { + #define SET_BRIGHTNESS_ASYNC (1 << 21) #define SET_BRIGHTNESS_SYNC (1 << 22) #define LED_DEV_CAP_FLASH (1 << 23) - #define LED_DEV_CAP_SYNC_STROBE (1 << 24) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT (1 << 30) +#define SET_GPIO_OUTPUT (1 << 31) @@ -125707,65 +127775,67 @@ index f70f84f..f3fcaa1 100644 /* Set LED brightness level */ /* Must not sleep, use a workqueue if needed */ -From 9bdca5da4acd1e4893a10183c0202b2b1293b9cd Mon Sep 17 00:00:00 2001 -From: Rainer Herbers -Date: Sun, 15 Feb 2015 13:44:14 +0100 -Subject: [PATCH 082/216] Create bmp085_i2c-sensor-overlay.dts and update - Makefile +From d8f6c527b14c125e58173e8bd0e7c6c59bab4919 Mon Sep 17 00:00:00 2001 +From: notro +Date: Thu, 10 Jul 2014 13:59:47 +0200 +Subject: [PATCH 57/77] pinctrl-bcm2835: Set base to 0 give expected gpio + numbering + +Signed-off-by: Noralf Tronnes +--- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 8d908e3..7a1900d 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -382,7 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = { + .get = bcm2835_gpio_get, + .set = bcm2835_gpio_set, + .to_irq = bcm2835_gpio_to_irq, +- .base = -1, ++ .base = 0, + .ngpio = BCM2835_NUM_GPIOS, + .can_sleep = false, + }; + +From bf8c97c74733237b219a22da649cb6cb7029615d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 4 Feb 2015 10:02:24 +0000 +Subject: [PATCH 58/77] pinctrl-bcm2835: bcm2835_gpio_direction_output must set + the value --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts | 23 +++++++++++++++++++++++ - 2 files changed, 24 insertions(+) - create mode 100644 arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 6cb743a..7946143 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 7a1900d..62f85aa 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -355,7 +355,14 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) + static int bcm2835_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) + { +- return pinctrl_gpio_direction_output(chip->base + offset); ++ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev); ++ int ret; ++ ++ ret = pinctrl_gpio_direction_output(chip->base + offset); ++ if (ret >= 0) ++ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset); ++ ++ return ret; + } -+dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -diff --git a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -new file mode 100644 -index 0000000..b830bf2 ---- /dev/null -+++ b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -@@ -0,0 +1,23 @@ -+// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; + static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -From 92765161f74e60edf1eb2c752f2cd3ea9d531d14 Mon Sep 17 00:00:00 2001 +From 1262602778ac5adbe798e7ace41b22262a578fcf Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 083/216] pinctrl-bcm2835: Fix interrupt handling for GPIOs - 28-31 and 46-53 +Subject: [PATCH 59/77] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 + and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has four interrupt lines - one each for the three IRQ groups and one common. Rather @@ -125781,13 +127851,13 @@ This bug has only just been observed because GPIOs above 27 can only be accessed on an old Raspberry Pi with the optional P5 header fitted, where the pins are often used for I2S instead. --- - drivers/pinctrl/pinctrl-bcm2835.c | 51 ++++++++++++++++++++++++++++++--------- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 51 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index d9c727b..ae68710 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 62f85aa..c7cf266 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 @@ -125842,9 +127912,9 @@ index d9c727b..ae68710 100644 events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; -@@ -420,7 +420,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) - if (type & IRQ_TYPE_LEVEL_MASK) - bcm2835_gpio_set_bit(pc, GPEDS0, gpio); +@@ -412,7 +412,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) + + generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } - return events ? IRQ_HANDLED : IRQ_NONE; + @@ -125874,7 +127944,7 @@ index d9c727b..ae68710 100644 } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, -@@ -992,8 +1015,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1000,8 +1023,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; @@ -125883,7 +127953,7 @@ index d9c727b..ae68710 100644 /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); -@@ -1008,10 +1029,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1016,10 +1037,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); @@ -125901,7 +127971,7 @@ index d9c727b..ae68710 100644 len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); -@@ -1069,6 +1095,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { +@@ -1077,6 +1103,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { .remove = bcm2835_pinctrl_remove, .driver = { .name = MODULE_NAME, @@ -125910,11 +127980,11 @@ index d9c727b..ae68710 100644 }, }; -From d1f5e57c873c1acf3be524693888af970a08f4fb Mon Sep 17 00:00:00 2001 +From fd7e740e1c83bd550444192a8beff54ea5291c50 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 084/216] pinctrl-bcm2835: Only request the interrupts listed - in the DTB +Subject: [PATCH 60/77] pinctrl-bcm2835: Only request the interrupts listed in + the DTB Although the GPIO controller can generate three interrupts (four counting the common one), the device tree files currently only specify two. In the @@ -125923,14 +127993,14 @@ registering 0), which has the effect of making it impossible to generate interrupts for GPIOs 46-53 which, since they share pins with the SD card interface, is unlikely to be a problem. --- - drivers/pinctrl/pinctrl-bcm2835.c | 2 ++ + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index ae68710..87b7a4a 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -1036,6 +1036,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index c7cf266..986779a 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -1044,6 +1044,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int len; char *name; pc->irq[i] = irq_of_parse_and_map(np, i); @@ -125940,1282 +128010,16 @@ index ae68710..87b7a4a 100644 pc->irq_data[i].irqgroup = i; -From a10a9f8313c8fff626c82bf63608f3f00188c5db Mon Sep 17 00:00:00 2001 -From: Dave Martin -Date: Fri, 27 Feb 2015 15:51:37 +0000 -Subject: [PATCH 085/216] serial/amba-pl011: Activate TX IRQ passively - -The current PL011 driver transmits a dummy character when the UART -is opened, to assert the TX IRQ for the first time -(see pl011_startup()). The UART is put in loopback mode temporarily, -so the receiver presumably shouldn't see anything. - -However... - -At least some platforms containing a PL011 send characters down the -wire even when loopback mode is enabled. This means that a -spurious NUL character may be seen at the receiver when the PL011 is -opened through the TTY layer. - -The current code also temporarily sets the baud rate to maximum and -the character width to the minimum, to that the dummy TX completes -as quickly as possible. If this is seen by the receiver it will -result in a framing error and can knock the receiver out of sync -- -turning subsequent output into garbage until synchronisation -is reestablished. (Particularly problematic during boot with systemd.) - -To avoid spurious transmissions, this patch removes assumptions about -whether the TX IRQ will fire until at least one TX IRQ has been seen. - -Instead, the UART will unmask the TX IRQ and then slow-start via -polling and timer-based soft IRQs initially. If the TTY layer writes -enough data to fill the FIFO to the interrupt threshold in one go, -the TX IRQ should assert, at which point the driver changes to -fully interrupt-driven TX. - -In this way, the TX IRQ is activated as a side-effect instead of -being done deliberately. - -This should also mean that the driver works on the SBSA Generic -UART[1] (a cut-down PL011) without invasive changes. The Generic -UART lacks some features needed for the dummy TX approach to work -(FIFO disabling and loopback). - -[1] Server Base System Architecture (ARM-DEN-0029-v2.3) - http://infocenter.arm.com/ - (click-thru required :/) - -Signed-off-by: Dave Martin ---- - drivers/tty/serial/amba-pl011.c | 165 ++++++++++++++++++++++++++++------------ - 1 file changed, 115 insertions(+), 50 deletions(-) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 16ca535..c243729 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include - - #define UART_NR 14 - -@@ -156,7 +157,9 @@ struct uart_amba_port { - unsigned int lcrh_tx; /* vendor-specific */ - unsigned int lcrh_rx; /* vendor-specific */ - unsigned int old_cr; /* state during shutdown */ -+ struct delayed_work tx_softirq_work; - bool autorts; -+ unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */ - char type[12]; - #ifdef CONFIG_DMA_ENGINE - /* DMA stuff */ -@@ -440,8 +443,9 @@ static void pl011_dma_remove(struct uart_amba_port *uap) - dma_release_channel(uap->dmarx.chan); - } - --/* Forward declare this for the refill routine */ -+/* Forward declare these for the refill routine */ - static int pl011_dma_tx_refill(struct uart_amba_port *uap); -+static void pl011_start_tx_pio(struct uart_amba_port *uap); - - /* - * The current DMA TX buffer has been sent. -@@ -479,14 +483,13 @@ static void pl011_dma_tx_callback(void *data) - return; - } - -- if (pl011_dma_tx_refill(uap) <= 0) { -+ if (pl011_dma_tx_refill(uap) <= 0) - /* - * We didn't queue a DMA buffer for some reason, but we - * have data pending to be sent. Re-enable the TX IRQ. - */ -- uap->im |= UART011_TXIM; -- writew(uap->im, uap->port.membase + UART011_IMSC); -- } -+ pl011_start_tx_pio(uap); -+ - spin_unlock_irqrestore(&uap->port.lock, flags); - } - -@@ -664,12 +667,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) - if (!uap->dmatx.queued) { - if (pl011_dma_tx_refill(uap) > 0) { - uap->im &= ~UART011_TXIM; -- ret = true; -- } else { -- uap->im |= UART011_TXIM; -+ writew(uap->im, uap->port.membase + -+ UART011_IMSC); -+ } else - ret = false; -- } -- writew(uap->im, uap->port.membase + UART011_IMSC); - } else if (!(uap->dmacr & UART011_TXDMAE)) { - uap->dmacr |= UART011_TXDMAE; - writew(uap->dmacr, -@@ -1208,15 +1209,24 @@ static void pl011_stop_tx(struct uart_port *port) - pl011_dma_tx_stop(uap); - } - -+static bool pl011_tx_chars(struct uart_amba_port *uap); -+ -+/* Start TX with programmed I/O only (no DMA) */ -+static void pl011_start_tx_pio(struct uart_amba_port *uap) -+{ -+ uap->im |= UART011_TXIM; -+ writew(uap->im, uap->port.membase + UART011_IMSC); -+ if (!uap->tx_irq_seen) -+ pl011_tx_chars(uap); -+} -+ - static void pl011_start_tx(struct uart_port *port) - { - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); - -- if (!pl011_dma_tx_start(uap)) { -- uap->im |= UART011_TXIM; -- writew(uap->im, uap->port.membase + UART011_IMSC); -- } -+ if (!pl011_dma_tx_start(uap)) -+ pl011_start_tx_pio(uap); - } - - static void pl011_stop_rx(struct uart_port *port) -@@ -1274,40 +1284,87 @@ __acquires(&uap->port.lock) - spin_lock(&uap->port.lock); - } - --static void pl011_tx_chars(struct uart_amba_port *uap) -+/* -+ * Transmit a character -+ * There must be at least one free entry in the TX FIFO to accept the char. -+ * -+ * Returns true if the FIFO might have space in it afterwards; -+ * returns false if the FIFO definitely became full. -+ */ -+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c) -+{ -+ writew(c, uap->port.membase + UART01x_DR); -+ uap->port.icount.tx++; -+ -+ if (likely(uap->tx_irq_seen > 1)) -+ return true; -+ -+ return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF); -+} -+ -+static bool pl011_tx_chars(struct uart_amba_port *uap) - { - struct circ_buf *xmit = &uap->port.state->xmit; - int count; - -+ if (unlikely(uap->tx_irq_seen < 2)) -+ /* -+ * Initial FIFO fill level unknown: we must check TXFF -+ * after each write, so just try to fill up the FIFO. -+ */ -+ count = uap->fifosize; -+ else /* tx_irq_seen >= 2 */ -+ /* -+ * FIFO initially at least half-empty, so we can simply -+ * write half the FIFO without polling TXFF. -+ -+ * Note: the *first* TX IRQ can still race with -+ * pl011_start_tx_pio(), which can result in the FIFO -+ * being fuller than expected in that case. -+ */ -+ count = uap->fifosize >> 1; -+ -+ /* -+ * If the FIFO is full we're guaranteed a TX IRQ at some later point, -+ * and can't transmit immediately in any case: -+ */ -+ if (unlikely(uap->tx_irq_seen < 2 && -+ readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)) -+ return false; -+ - if (uap->port.x_char) { -- writew(uap->port.x_char, uap->port.membase + UART01x_DR); -- uap->port.icount.tx++; -+ pl011_tx_char(uap, uap->port.x_char); - uap->port.x_char = 0; -- return; -+ --count; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl011_stop_tx(&uap->port); -- return; -+ goto done; - } - - /* If we are using DMA mode, try to send some characters. */ - if (pl011_dma_tx_irq(uap)) -- return; -+ goto done; - -- count = uap->fifosize >> 1; -- do { -- writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); -+ while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) { - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -- uap->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; -- } while (--count > 0); -+ } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uap->port); - -- if (uart_circ_empty(xmit)) -+ if (uart_circ_empty(xmit)) { - pl011_stop_tx(&uap->port); -+ goto done; -+ } -+ -+ if (unlikely(!uap->tx_irq_seen)) -+ schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout); -+ -+done: -+ return false; - } - - static void pl011_modem_status(struct uart_amba_port *uap) -@@ -1334,6 +1391,28 @@ static void pl011_modem_status(struct uart_amba_port *uap) - wake_up_interruptible(&uap->port.state->port.delta_msr_wait); - } - -+static void pl011_tx_softirq(struct work_struct *work) -+{ -+ struct delayed_work *dwork = to_delayed_work(work); -+ struct uart_amba_port *uap = -+ container_of(dwork, struct uart_amba_port, tx_softirq_work); -+ -+ spin_lock(&uap->port.lock); -+ while (pl011_tx_chars(uap)) ; -+ spin_unlock(&uap->port.lock); -+} -+ -+static void pl011_tx_irq_seen(struct uart_amba_port *uap) -+{ -+ if (likely(uap->tx_irq_seen > 1)) -+ return; -+ -+ uap->tx_irq_seen++; -+ if (uap->tx_irq_seen < 2) -+ /* first TX IRQ */ -+ cancel_delayed_work(&uap->tx_softirq_work); -+} -+ - static irqreturn_t pl011_int(int irq, void *dev_id) - { - struct uart_amba_port *uap = dev_id; -@@ -1372,8 +1451,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id) - if (status & (UART011_DSRMIS|UART011_DCDMIS| - UART011_CTSMIS|UART011_RIMIS)) - pl011_modem_status(uap); -- if (status & UART011_TXIS) -+ if (status & UART011_TXIS) { -+ pl011_tx_irq_seen(uap); - pl011_tx_chars(uap); -+ } - - if (pass_counter-- == 0) - break; -@@ -1577,7 +1658,7 @@ static int pl011_startup(struct uart_port *port) - { - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); -- unsigned int cr, lcr_h, fbrd, ibrd; -+ unsigned int cr; - int retval; - - retval = pl011_hwinit(port); -@@ -1595,29 +1676,10 @@ static int pl011_startup(struct uart_port *port) - - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); - -- /* -- * Provoke TX FIFO interrupt into asserting. Taking care to preserve -- * baud rate and data format specified by FBRD, IBRD and LCRH as the -- * UART may already be in use as a console. -- */ -- spin_lock_irq(&uap->port.lock); -- -- fbrd = readw(uap->port.membase + UART011_FBRD); -- ibrd = readw(uap->port.membase + UART011_IBRD); -- lcr_h = readw(uap->port.membase + uap->lcrh_rx); -- -- cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; -- writew(cr, uap->port.membase + UART011_CR); -- writew(0, uap->port.membase + UART011_FBRD); -- writew(1, uap->port.membase + UART011_IBRD); -- pl011_write_lcr_h(uap, 0); -- writew(0, uap->port.membase + UART01x_DR); -- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) -- barrier(); -+ /* Assume that TX IRQ doesn't work until we see one: */ -+ uap->tx_irq_seen = 0; - -- writew(fbrd, uap->port.membase + UART011_FBRD); -- writew(ibrd, uap->port.membase + UART011_IBRD); -- pl011_write_lcr_h(uap, lcr_h); -+ spin_lock_irq(&uap->port.lock); - - /* restore RTS and DTR */ - cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); -@@ -1672,6 +1734,8 @@ static void pl011_shutdown(struct uart_port *port) - container_of(port, struct uart_amba_port, port); - unsigned int cr; - -+ cancel_delayed_work_sync(&uap->tx_softirq_work); -+ - /* - * disable all interrupts - */ -@@ -2218,6 +2282,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) - uap->port.ops = &amba_pl011_pops; - uap->port.flags = UPF_BOOT_AUTOCONF; - uap->port.line = i; -+ INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq); - pl011_dma_probe(&dev->dev, uap); - - /* Ensure interrupts from this UART are masked and cleared */ - -From 75d9fae636d84117aa46cf0c2dcc556d02d67aca Mon Sep 17 00:00:00 2001 -From: Dave Martin -Date: Wed, 1 Apr 2015 14:08:31 +0100 -Subject: [PATCH 086/216] serial/amba-pl011: Refactor and simplify TX FIFO - handling - -Commit 734745c serial/amba-pl011: Activate TX IRQ passively -adds some complexity and overhead in the form of a softirq -mechanism for transmitting in the absence of interrupts. - -This patch simplifies the code flow to reduce the reliance on -subtle behaviour and avoid fragility under future maintenance. - -To this end, the TX softirq mechanism is removed and instead -pl011_start_tx() will now simply stuff the FIFO until full -(guaranteeing future TX IRQs), or until there are no more chars -to write (in which case we don't care whether an IRQ happens). - -Signed-off-by: Dave Martin -Signed-off-by: Jakub Kicinski ---- - drivers/tty/serial/amba-pl011.c | 119 +++++++++------------------------------- - 1 file changed, 26 insertions(+), 93 deletions(-) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index c243729..e32f4d7 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -58,7 +58,6 @@ - #include - #include - #include --#include - - #define UART_NR 14 - -@@ -157,9 +156,7 @@ struct uart_amba_port { - unsigned int lcrh_tx; /* vendor-specific */ - unsigned int lcrh_rx; /* vendor-specific */ - unsigned int old_cr; /* state during shutdown */ -- struct delayed_work tx_softirq_work; - bool autorts; -- unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */ - char type[12]; - #ifdef CONFIG_DMA_ENGINE - /* DMA stuff */ -@@ -1209,15 +1206,14 @@ static void pl011_stop_tx(struct uart_port *port) - pl011_dma_tx_stop(uap); - } - --static bool pl011_tx_chars(struct uart_amba_port *uap); -+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); - - /* Start TX with programmed I/O only (no DMA) */ - static void pl011_start_tx_pio(struct uart_amba_port *uap) - { - uap->im |= UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); -- if (!uap->tx_irq_seen) -- pl011_tx_chars(uap); -+ pl011_tx_chars(uap, false); - } - - static void pl011_start_tx(struct uart_port *port) -@@ -1284,87 +1280,54 @@ __acquires(&uap->port.lock) - spin_lock(&uap->port.lock); - } - --/* -- * Transmit a character -- * There must be at least one free entry in the TX FIFO to accept the char. -- * -- * Returns true if the FIFO might have space in it afterwards; -- * returns false if the FIFO definitely became full. -- */ --static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c) -+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, -+ bool from_irq) - { -+ if (unlikely(!from_irq) && -+ readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) -+ return false; /* unable to transmit character */ -+ - writew(c, uap->port.membase + UART01x_DR); - uap->port.icount.tx++; - -- if (likely(uap->tx_irq_seen > 1)) -- return true; -- -- return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF); -+ return true; - } - --static bool pl011_tx_chars(struct uart_amba_port *uap) -+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) - { - struct circ_buf *xmit = &uap->port.state->xmit; -- int count; -- -- if (unlikely(uap->tx_irq_seen < 2)) -- /* -- * Initial FIFO fill level unknown: we must check TXFF -- * after each write, so just try to fill up the FIFO. -- */ -- count = uap->fifosize; -- else /* tx_irq_seen >= 2 */ -- /* -- * FIFO initially at least half-empty, so we can simply -- * write half the FIFO without polling TXFF. -- -- * Note: the *first* TX IRQ can still race with -- * pl011_start_tx_pio(), which can result in the FIFO -- * being fuller than expected in that case. -- */ -- count = uap->fifosize >> 1; -- -- /* -- * If the FIFO is full we're guaranteed a TX IRQ at some later point, -- * and can't transmit immediately in any case: -- */ -- if (unlikely(uap->tx_irq_seen < 2 && -- readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)) -- return false; -+ int count = uap->fifosize >> 1; - - if (uap->port.x_char) { -- pl011_tx_char(uap, uap->port.x_char); -+ if (!pl011_tx_char(uap, uap->port.x_char, from_irq)) -+ return; - uap->port.x_char = 0; - --count; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl011_stop_tx(&uap->port); -- goto done; -+ return; - } - - /* If we are using DMA mode, try to send some characters. */ - if (pl011_dma_tx_irq(uap)) -- goto done; -+ return; - -- while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) { -- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -- if (uart_circ_empty(xmit)) -+ do { -+ if (likely(from_irq) && count-- == 0) - break; -- } -+ -+ if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq)) -+ break; -+ -+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -+ } while (!uart_circ_empty(xmit)); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uap->port); - -- if (uart_circ_empty(xmit)) { -+ if (uart_circ_empty(xmit)) - pl011_stop_tx(&uap->port); -- goto done; -- } -- -- if (unlikely(!uap->tx_irq_seen)) -- schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout); -- --done: -- return false; - } - - static void pl011_modem_status(struct uart_amba_port *uap) -@@ -1391,28 +1354,6 @@ static void pl011_modem_status(struct uart_amba_port *uap) - wake_up_interruptible(&uap->port.state->port.delta_msr_wait); - } - --static void pl011_tx_softirq(struct work_struct *work) --{ -- struct delayed_work *dwork = to_delayed_work(work); -- struct uart_amba_port *uap = -- container_of(dwork, struct uart_amba_port, tx_softirq_work); -- -- spin_lock(&uap->port.lock); -- while (pl011_tx_chars(uap)) ; -- spin_unlock(&uap->port.lock); --} -- --static void pl011_tx_irq_seen(struct uart_amba_port *uap) --{ -- if (likely(uap->tx_irq_seen > 1)) -- return; -- -- uap->tx_irq_seen++; -- if (uap->tx_irq_seen < 2) -- /* first TX IRQ */ -- cancel_delayed_work(&uap->tx_softirq_work); --} -- - static irqreturn_t pl011_int(int irq, void *dev_id) - { - struct uart_amba_port *uap = dev_id; -@@ -1451,10 +1392,8 @@ static irqreturn_t pl011_int(int irq, void *dev_id) - if (status & (UART011_DSRMIS|UART011_DCDMIS| - UART011_CTSMIS|UART011_RIMIS)) - pl011_modem_status(uap); -- if (status & UART011_TXIS) { -- pl011_tx_irq_seen(uap); -- pl011_tx_chars(uap); -- } -+ if (status & UART011_TXIS) -+ pl011_tx_chars(uap, true); - - if (pass_counter-- == 0) - break; -@@ -1676,9 +1615,6 @@ static int pl011_startup(struct uart_port *port) - - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); - -- /* Assume that TX IRQ doesn't work until we see one: */ -- uap->tx_irq_seen = 0; -- - spin_lock_irq(&uap->port.lock); - - /* restore RTS and DTR */ -@@ -1734,8 +1670,6 @@ static void pl011_shutdown(struct uart_port *port) - container_of(port, struct uart_amba_port, port); - unsigned int cr; - -- cancel_delayed_work_sync(&uap->tx_softirq_work); -- - /* - * disable all interrupts - */ -@@ -2282,7 +2216,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) - uap->port.ops = &amba_pl011_pops; - uap->port.flags = UPF_BOOT_AUTOCONF; - uap->port.line = i; -- INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq); - pl011_dma_probe(&dev->dev, uap); - - /* Ensure interrupts from this UART are masked and cleared */ - -From 29cd864c0ec9d9d593e569ee5d4fcb463d36cb35 Mon Sep 17 00:00:00 2001 -From: Jon Burgess -Date: Tue, 17 Feb 2015 13:22:17 +0000 -Subject: [PATCH 087/216] Create generic i2c-rtc overlay for supporting ds1307, - ds3231, pcf2127 and pcf8523. - -Signed-off-by: Jon Burgess ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/i2c-rtc-overlay.dts | 43 +++++++++++++++++++++++++++++++++++ - 2 files changed, 44 insertions(+) - create mode 100644 arch/arm/boot/dts/i2c-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 7946143..6753fcb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -14,6 +14,7 @@ endif - - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -diff --git a/arch/arm/boot/dts/i2c-rtc-overlay.dts b/arch/arm/boot/dts/i2c-rtc-overlay.dts -new file mode 100644 -index 0000000..5d5abb1 ---- /dev/null -+++ b/arch/arm/boot/dts/i2c-rtc-overlay.dts -@@ -0,0 +1,43 @@ -+// Definitions for several I2C based Real Time Clocks -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ ds3231: ds3231@68 { -+ compatible = "maxim,ds3231"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf2127: pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ pcf8523: pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ __overrides__ { -+ ds1307 = <&ds1307>,"status"; -+ ds3231 = <&ds3231>,"status"; -+ pcf2127 = <&pcf2127>,"status"; -+ pcf8523 = <&pcf8523>,"status"; -+ }; -+}; - -From 600d5e0e89ecc723b7ffb29209b058d0275502e2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:24:05 +0100 -Subject: [PATCH 088/216] dts: overlay: add support for rpi-display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for rpi-display by Watterott. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-display-overlay.dts | 81 +++++++++++++++++++++++++++++++ - 2 files changed, 82 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-display-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 6753fcb..de47748 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -25,6 +25,7 @@ dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -new file mode 100644 -index 0000000..0578810 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-display-overlay.dts -@@ -0,0 +1,81 @@ -+/* -+ * Device Tree overlay for rpi-display by Watterott -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ rpi_display_pins: rpi_display_pins { -+ brcm,pins = <18 23 24 25>; -+ brcm,function = <1 1 1 0>; /* out out out in */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rpidisplay: rpi-display@0{ -+ compatible = "ilitek,ili9341"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rpi_display_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ reset-gpios = <&gpio 23 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ rpidisplay_ts: rpi-display-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <25 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 25 0>; -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&rpidisplay>,"spi-max-frequency:0"; -+ rotate = <&rpidisplay>,"rotate:0"; -+ fps = <&rpidisplay>,"fps:0"; -+ debug = <&rpidisplay>,"debug:0"; -+ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From 525949ace298ff41d93fc2025ac768654e745642 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:36:27 +0100 -Subject: [PATCH 089/216] dts: overlay: add support for HY28A display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for HY28A display by HAOYU Electronics. -Default values are set to match Texy's display shield. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hy28a-overlay.dts | 87 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 88 insertions(+) - create mode 100644 arch/arm/boot/dts/hy28a-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index de47748..8d7e535 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hy28a-overlay.dts b/arch/arm/boot/dts/hy28a-overlay.dts -new file mode 100644 -index 0000000..3cd3083 ---- /dev/null -+++ b/arch/arm/boot/dts/hy28a-overlay.dts -@@ -0,0 +1,87 @@ -+/* -+ * Device Tree overlay for HY28A display -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28a_pins: hy28a_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28a: hy28a@0{ -+ compatible = "ilitek,ili9320"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28a_pins>; -+ -+ spi-max-frequency = <32000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ hy28a_ts: hy28a-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28a>,"spi-max-frequency:0"; -+ rotate = <&hy28a>,"rotate:0"; -+ fps = <&hy28a>,"fps:0"; -+ debug = <&hy28a>,"debug:0"; -+ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28a>,"reset-gpios:4", -+ <&hy28a_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28a>,"led-gpios:4", -+ <&hy28a_pins>, "brcm,pins:2"; -+ }; -+}; - -From 131c6ba7b078b8536755c8cae2e31c09053b5804 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:38:00 +0100 -Subject: [PATCH 090/216] dts: overlay: add support for HY28B display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for HY28B display by HAOYU Electronics. -Default values are set to match Texy's display shield. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hy28b-overlay.dts | 142 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 143 insertions(+) - create mode 100644 arch/arm/boot/dts/hy28b-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 8d7e535..ec26431b1 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -20,6 +20,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hy28b-overlay.dts b/arch/arm/boot/dts/hy28b-overlay.dts -new file mode 100644 -index 0000000..f774c4a ---- /dev/null -+++ b/arch/arm/boot/dts/hy28b-overlay.dts -@@ -0,0 +1,142 @@ -+/* -+ * Device Tree overlay for HY28b display shield by Texy -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28b_pins: hy28b_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28b: hy28b@0{ -+ compatible = "ilitek,ili9325"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28b_pins>; -+ -+ spi-max-frequency = <48000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ -+ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -+ -+ init = <0x10000e7 0x0010 -+ 0x1000000 0x0001 -+ 0x1000001 0x0100 -+ 0x1000002 0x0700 -+ 0x1000003 0x1030 -+ 0x1000004 0x0000 -+ 0x1000008 0x0207 -+ 0x1000009 0x0000 -+ 0x100000a 0x0000 -+ 0x100000c 0x0001 -+ 0x100000d 0x0000 -+ 0x100000f 0x0000 -+ 0x1000010 0x0000 -+ 0x1000011 0x0007 -+ 0x1000012 0x0000 -+ 0x1000013 0x0000 -+ 0x2000032 -+ 0x1000010 0x1590 -+ 0x1000011 0x0227 -+ 0x2000032 -+ 0x1000012 0x009c -+ 0x2000032 -+ 0x1000013 0x1900 -+ 0x1000029 0x0023 -+ 0x100002b 0x000e -+ 0x2000032 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000032 -+ 0x1000050 0x0000 -+ 0x1000051 0x00ef -+ 0x1000052 0x0000 -+ 0x1000053 0x013f -+ 0x1000060 0xa700 -+ 0x1000061 0x0001 -+ 0x100006a 0x0000 -+ 0x1000080 0x0000 -+ 0x1000081 0x0000 -+ 0x1000082 0x0000 -+ 0x1000083 0x0000 -+ 0x1000084 0x0000 -+ 0x1000085 0x0000 -+ 0x1000090 0x0010 -+ 0x1000092 0x0000 -+ 0x1000093 0x0003 -+ 0x1000095 0x0110 -+ 0x1000097 0x0000 -+ 0x1000098 0x0000 -+ 0x1000007 0x0133 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000064>; -+ debug = <0>; -+ }; -+ -+ hy28b_ts: hy28b-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28b>,"spi-max-frequency:0"; -+ rotate = <&hy28b>,"rotate:0"; -+ fps = <&hy28b>,"fps:0"; -+ debug = <&hy28b>,"debug:0"; -+ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28b>,"reset-gpios:4", -+ <&hy28b_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28b>,"led-gpios:4", -+ <&hy28b_pins>, "brcm,pins:2"; -+ }; -+}; - -From 33ce6c6c093580873f0f54b8633f44479d31786b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:38:47 +0100 -Subject: [PATCH 091/216] dts: overlay: add support for PiScreen display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for PiScreen display by OzzMaker.com - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/piscreen-overlay.dts | 94 ++++++++++++++++++++++++++++++++++ - 2 files changed, 95 insertions(+) - create mode 100644 arch/arm/boot/dts/piscreen-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ec26431b1..107448d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -26,6 +26,7 @@ dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -new file mode 100644 -index 0000000..8cd6a95 ---- /dev/null -+++ b/arch/arm/boot/dts/piscreen-overlay.dts -@@ -0,0 +1,94 @@ -+/* -+ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ piscreen_pins: piscreen_pins { -+ brcm,pins = <17 25 24 22>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ piscreen: piscreen@0{ -+ compatible = "ilitek,ili9486"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&piscreen_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ regwidth = <16>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 22 1>; -+ debug = <0>; -+ -+ init = <0x10000b0 0x00 -+ 0x1000011 -+ 0x20000ff -+ 0x100003a 0x55 -+ 0x1000036 0x28 -+ 0x10000c2 0x44 -+ 0x10000c5 0x00 0x00 0x00 0x00 -+ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -+ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x1000011 -+ 0x1000029>; -+ }; -+ -+ piscreen-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&piscreen>,"spi-max-frequency:0"; -+ rotate = <&piscreen>,"rotate:0"; -+ fps = <&piscreen>,"fps:0"; -+ debug = <&piscreen>,"debug:0"; -+ }; -+}; - -From 5ef8657c77133ceed5a8ddf80fed6d3002ac9dca Mon Sep 17 00:00:00 2001 +From c24fbfc7a5bc3c7cb35f51d0a40ad25b98a8a422 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 092/216] enc28j60: Add device tree compatible string and an +Subject: [PATCH 61/77] enc28j60: Add device tree compatible string and an overlay --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/enc28j60-overlay.dts | 29 +++++++++++++++++++++++++++++ drivers/net/ethernet/microchip/enc28j60.c | 11 +++++++++++ - 3 files changed, 41 insertions(+) - create mode 100755 arch/arm/boot/dts/enc28j60-overlay.dts + 1 file changed, 11 insertions(+) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 107448d..81afe85 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -14,6 +14,7 @@ endif - - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -diff --git a/arch/arm/boot/dts/enc28j60-overlay.dts b/arch/arm/boot/dts/enc28j60-overlay.dts -new file mode 100755 -index 0000000..aa9b645 ---- /dev/null -+++ b/arch/arm/boot/dts/enc28j60-overlay.dts -@@ -0,0 +1,29 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index b1b5f66..c6b6e1a 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c @@ -127243,1131 +128047,10 @@ index b1b5f66..c6b6e1a 100644 .probe = enc28j60_probe, .remove = enc28j60_remove, -From 04e8bf899200ef72d464ce9ee362d4377fbd7d87 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 27 Feb 2015 18:17:25 +0100 -Subject: [PATCH 093/216] dts: overlay: add support for Adafruit PiTFT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add DT overlay for the Adafruit PiTFT 2.8" resistive touch screen - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pitft28-resistive-overlay.dts | 115 ++++++++++++++++++++++++ - 2 files changed, 116 insertions(+) - create mode 100644 arch/arm/boot/dts/pitft28-resistive-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 81afe85..07c6eeb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -28,6 +28,7 @@ dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -new file mode 100644 -index 0000000..d506eae ---- /dev/null -+++ b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -@@ -0,0 +1,115 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "ilitek,ili9340"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; - -From 917597bfd056d8d37b02a21e7ea4e56023a3e630 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 2 Mar 2015 09:37:02 +0000 -Subject: [PATCH 094/216] enable compiling spi-bcm2835 and add overlay to allow - us to load the driver - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/spi-bcm2835-overlay.dts | 18 ++++++++++++++++++ - 2 files changed, 19 insertions(+) - create mode 100644 arch/arm/boot/dts/spi-bcm2835-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 07c6eeb..e83179f 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -33,6 +33,7 @@ dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -new file mode 100644 -index 0000000..fc1e39b ---- /dev/null -+++ b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2835-spi"; -+ }; -+ }; -+}; - -From 58f834d50fb0e6eb0f1a8c48bdb3551866addc62 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:39:30 +0100 -Subject: [PATCH 095/216] dts: overlay: add support for MZ61581 display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for MZ61581 display by Tontec. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/mz61581-overlay.dts | 109 ++++++++++++++++++++++++++++++++++ - 2 files changed, 110 insertions(+) - create mode 100644 arch/arm/boot/dts/mz61581-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e83179f..f99eccf 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -25,6 +25,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -diff --git a/arch/arm/boot/dts/mz61581-overlay.dts b/arch/arm/boot/dts/mz61581-overlay.dts -new file mode 100644 -index 0000000..c06fe12 ---- /dev/null -+++ b/arch/arm/boot/dts/mz61581-overlay.dts -@@ -0,0 +1,109 @@ -+/* -+ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ mz61581_pins: mz61581_pins { -+ brcm,pins = <4 15 18 25>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mz61581: mz61581@0{ -+ compatible = "samsung,s6d02a1"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mz61581_pins>; -+ -+ spi-max-frequency = <128000000>; -+ spi-cpol; -+ spi-cpha; -+ -+ width = <320>; -+ height = <480>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ -+ reset-gpios = <&gpio 15 0>; -+ dc-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 0>; -+ -+ init = <0x10000b0 00 -+ 0x1000011 -+ 0x20000ff -+ 0x10000b3 0x02 0x00 0x00 0x00 -+ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -+ 0x10000c1 0x08 0x16 0x08 0x08 -+ 0x10000c4 0x11 0x07 0x03 0x03 -+ 0x10000c6 0x00 -+ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -+ 0x1000035 0x00 -+ 0x1000036 0xa0 -+ 0x100003a 0x55 -+ 0x1000044 0x00 0x01 -+ 0x10000d0 0x07 0x07 0x1d 0x03 -+ 0x10000d1 0x03 0x30 0x10 -+ 0x10000d2 0x03 0x14 0x04 -+ 0x1000029 -+ 0x100002c>; -+ -+ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -+ debug = <3>; -+ }; -+ -+ mz61581_ts: mz61581_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <4 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 4 0>; -+ -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&mz61581>, "spi-max-frequency:0"; -+ rotate = <&mz61581>, "rotate:0"; -+ fps = <&mz61581>, "fps:0"; -+ debug = <&mz61581>, "debug:0"; -+ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From 080c66dfc13694a3c6123d6732d6255361e49733 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:40:07 +0100 -Subject: [PATCH 096/216] dts: overlay: piscreen: set speed to 24MHz -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some of the displays can't handle the 32MHz speed. -Lower the default speed to 24MHz. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/piscreen-overlay.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -index 8cd6a95..b7fd7ea 100644 ---- a/arch/arm/boot/dts/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/piscreen-overlay.dts -@@ -47,7 +47,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&piscreen_pins>; - -- spi-max-frequency = <32000000>; -+ spi-max-frequency = <24000000>; - rotate = <270>; - bgr; - fps = <30>; - -From c34aef0866b8605b64dd7b7c1bf4c1db77933089 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:40:43 +0100 -Subject: [PATCH 097/216] dts: overlay: rpi-display: pullup irq gpio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -An early version of rpi-display needs the touch controller irq -to be pulled up. This is the version with 9-bit SPI as default. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/rpi-display-overlay.dts | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -index 0578810..a8fa974 100644 ---- a/arch/arm/boot/dts/rpi-display-overlay.dts -+++ b/arch/arm/boot/dts/rpi-display-overlay.dts -@@ -30,6 +30,7 @@ - rpi_display_pins: rpi_display_pins { - brcm,pins = <18 23 24 25>; - brcm,function = <1 1 1 0>; /* out out out in */ -+ brcm,pull = <0 0 0 2>; /* - - - up */ - }; - }; - }; - -From 7268b2f16833d36f6568add569f15325b398497b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 14:48:30 +0100 -Subject: [PATCH 098/216] BCM270x_DT: add bcm2835-dma entry -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree entry for bcm2835-dma. -The entry doesn't contain any resources since they are handled -by the arch/arm/mach-bcm270x/dma.c driver. -In non-DT mode, don't add the device in the board file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708.dtsi | 5 +++++ - arch/arm/boot/dts/bcm2709.dtsi | 5 +++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 4 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 0713a1ed..846f148 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -17,6 +17,11 @@ - #size-cells = <1>; - ranges = <0x7e000000 0x20000000 0x01000000>; - -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ - intc: interrupt-controller { - compatible = "brcm,bcm2708-armctrl-ic"; - reg = <0x7e00b200 0x200>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 34d2226..d468363 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -17,6 +17,11 @@ - #size-cells = <1>; - ranges = <0x7e000000 0x3f000000 0x01000000>; - -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ - intc: interrupt-controller { - compatible = "brcm,bcm2708-armctrl-ic"; - reg = <0x7e00b200 0x200>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c8aea5b..6a08e95 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -857,7 +857,7 @@ void __init bcm2708_init(void) - bcm2708_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); -- bcm_register_device(&bcm2708_dmaengine_device); -+ bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 259d552..3c1c1dc 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -879,7 +879,7 @@ void __init bcm2709_init(void) - bcm2709_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); -- bcm_register_device(&bcm2708_dmaengine_device); -+ bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - -From ccc2b25ac7ffe4252a482901541a1894c86bb4c3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 14:50:19 +0100 -Subject: [PATCH 099/216] bcm270x: add mmc-bcm2835 clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add clock for the mmc-bcm2835.0 device. -Will be used in non-DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6a08e95..b5f22e2 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -233,6 +233,7 @@ void __init bcm2708_init_clocks(void) - bcm2708_register_clkdev(clk, "dev:f1"); - - clk = bcm2708_clk_register("sdhost_clk", 250000000); -+ bcm2708_register_clkdev(clk, "mmc-bcm2835.0"); - bcm2708_register_clkdev(clk, "bcm2708_spi.0"); - bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); - bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 3c1c1dc..e10667d 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -243,6 +243,7 @@ void __init bcm2709_init_clocks(void) - bcm2709_register_clkdev(clk, "dev:f1"); - - clk = bcm2709_clk_register("sdhost_clk", 250000000); -+ bcm2709_register_clkdev(clk, "mmc-bcm2835.0"); - bcm2709_register_clkdev(clk, "bcm2708_spi.0"); - bcm2709_register_clkdev(clk, "bcm2708_i2c.0"); - bcm2709_register_clkdev(clk, "bcm2708_i2c.1"); - -From 7520bcefca288277ace88e3df254045eee89c189 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 15:12:35 +0100 -Subject: [PATCH 100/216] BCM270x_DT: add bcm2835-mmc entry -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree entry for bcm2835-mmc. -In non-DT mode, don't add the device in the board file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 +++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 +++++ - arch/arm/boot/dts/bcm2708.dtsi | 19 +++++++++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 +++++ - arch/arm/boot/dts/bcm2709.dtsi | 19 +++++++++++++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 7 files changed, 55 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 7f84473..f25563a 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index a39562f..17b4b8c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 846f148..42edda5 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -41,6 +41,17 @@ - #interrupt-cells = <2>; - }; - -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -96,6 +107,14 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ - clk_i2c: i2c { - compatible = "fixed-clock"; - reg = <1>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 75c222f..c73249b 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index d468363..bd6605d 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -41,6 +41,17 @@ - #interrupt-cells = <2>; - }; - -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -97,6 +108,14 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ - clk_i2c: i2c { - compatible = "fixed-clock"; - reg = <1>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index b5f22e2..16ba248 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -885,7 +885,7 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 -- bcm_register_device(&bcm2835_emmc_device); -+ bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2708_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index e10667d..dcad008 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -909,7 +909,7 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 -- bcm_register_device(&bcm2835_emmc_device); -+ bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2709_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - -From 7504524f3f951bf8c40c5decf231ea6538d1380b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 27 Mar 2015 11:45:44 +0000 -Subject: [PATCH 101/216] BCM270x_DT: Refactor bcm2708.dtsi and bcm2709.dtsi - -Extract the common elements, creating bcm2708_common.dtsi ---- - arch/arm/boot/dts/bcm2708.dtsi | 118 +-------------------------------- - arch/arm/boot/dts/bcm2708_common.dtsi | 120 ++++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 118 +-------------------------------- - 3 files changed, 124 insertions(+), 232 deletions(-) - create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 42edda5..0d47427 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -1,133 +1,19 @@ --/include/ "skeleton.dtsi" -+/include/ "bcm2708_common.dtsi" - - / { - compatible = "brcm,bcm2708"; - model = "BCM2708"; - -- interrupt-parent = <&intc>; -- - chosen { - /* No padding required - the boot loader can do that. */ - bootargs = ""; - }; - -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -+ soc { - ranges = <0x7e000000 0x20000000 0x01000000>; - -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- #dma-cells = <1>; -- }; -- -- intc: interrupt-controller { -- compatible = "brcm,bcm2708-armctrl-ic"; -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- gpio: gpio { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&clk_mmc>; -- dmas = <&dma 11>, -- <&dma 11>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2708-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -- -- //dmas = <&dma 2>, -- // <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&clk_spi>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- - arm-pmu { - compatible = "arm,arm1176-pmu"; - }; - }; -- -- clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_mmc: clock@0 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "mmc"; -- clock-frequency = <250000000>; -- }; -- -- clk_i2c: i2c { -- compatible = "fixed-clock"; -- reg = <1>; -- #clock-cells = <0>; -- clock-frequency = <250000000>; -- }; -- -- clk_spi: clock@2 { -- compatible = "fixed-clock"; -- reg = <2>; -- #clock-cells = <0>; -- clock-output-names = "spi"; -- clock-frequency = <250000000>; -- }; -- }; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -new file mode 100644 -index 0000000..ff70c58 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,120 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&intc>; -+ -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index bd6605d..5e0b935 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -1,137 +1,23 @@ --/include/ "skeleton.dtsi" -+/include/ "bcm2708_common.dtsi" - - / { - compatible = "brcm,bcm2709"; - model = "BCM2709"; - -- interrupt-parent = <&intc>; -- - chosen { - /* No padding required - the boot loader can do that. */ - bootargs = ""; - }; - -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -+ soc { - ranges = <0x7e000000 0x3f000000 0x01000000>; - -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- #dma-cells = <1>; -- }; -- -- intc: interrupt-controller { -- compatible = "brcm,bcm2708-armctrl-ic"; -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- gpio: gpio { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&clk_mmc>; -- dmas = <&dma 11>, -- <&dma 11>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2708-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -- -- //dmas = <&dma 2>, -- // <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&clk_spi>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- - arm-pmu { - compatible = "arm,cortex-a7-pmu"; - interrupts = <3 9>; - }; - }; - -- clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_mmc: clock@0 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "mmc"; -- clock-frequency = <250000000>; -- }; -- -- clk_i2c: i2c { -- compatible = "fixed-clock"; -- reg = <1>; -- #clock-cells = <0>; -- clock-frequency = <250000000>; -- }; -- -- clk_spi: clock@2 { -- compatible = "fixed-clock"; -- reg = <2>; -- #clock-cells = <0>; -- clock-output-names = "spi"; -- clock-frequency = <250000000>; -- }; -- }; -- - timer { - compatible = "arm,armv7-timer"; - clock-frequency = <19200000>; - -From 5d44aea95dbfd69851ffeb426ccf419f5894e70e Mon Sep 17 00:00:00 2001 +From 331cdec0de30933d5e7839f0e3def9b98d3fa968 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 102/216] Add driver for rpi-proto +Subject: [PATCH 62/77] 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 @@ -128380,74 +128063,14 @@ Playback tested with devicetree enabled. Signed-off-by: Waldemar Brodkorb --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-proto-overlay.dts | 39 ++++++++ - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-proto.c | 153 ++++++++++++++++++++++++++++++++ - 5 files changed, 202 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-proto-overlay.dts + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-proto.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 162 insertions(+) create mode 100644 sound/soc/bcm/rpi-proto.c -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index f99eccf..daf51d2 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -24,6 +24,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb -diff --git a/arch/arm/boot/dts/rpi-proto-overlay.dts b/arch/arm/boot/dts/rpi-proto-overlay.dts -new file mode 100644 -index 0000000..2029930 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-proto-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for Rpi-Proto -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-proto"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8731@1a { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8731"; -+ reg = <0x1a>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 40d27c1..003ae28 100644 +index bdcf12f..fc151ea 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -54,6 +54,13 @@ config SND_BCM2708_SOC_RPI_DAC @@ -128456,14 +128079,14 @@ index 40d27c1..003ae28 100644 +config SND_BCM2708_SOC_RPI_PROTO + tristate "Support for Rpi-PROTO" -+ depends on SND_BCM2708_SOC_I2S ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8731 + help + Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). + config SND_BCM2708_SOC_IQAUDIO_DAC tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile index 17ea2b0..883241b 100644 --- a/sound/soc/bcm/Makefile @@ -128642,71 +128265,16 @@ index 0000000..c6e45a0 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From b1c2c58f341642e8bcc337b592f19d5543ae51ad Mon Sep 17 00:00:00 2001 +From 2079392f1bde4f50d8c1ad65c2f7b52a6ff34848 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Thu, 2 Apr 2015 12:22:55 +0100 -Subject: [PATCH 103/216] Add Device Tree support for RPi-DAC. +Subject: [PATCH 63/77] Add Device Tree support for RPi-DAC. --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-dac-overlay.dts | 34 ++++++++++++++++++++++++++++++++++ - sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ - sound/soc/codecs/pcm1794a.c | 7 +++++++ - 4 files changed, 63 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-dac-overlay.dts + sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ + sound/soc/codecs/pcm1794a.c | 7 +++++++ + 2 files changed, 28 insertions(+) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index daf51d2..980b78e0 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -24,6 +24,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb -diff --git a/arch/arm/boot/dts/rpi-dac-overlay.dts b/arch/arm/boot/dts/rpi-dac-overlay.dts -new file mode 100644 -index 0000000..7fc6ac9 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for RPi DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm1794a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm1794a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c index 6d6e0ba..d5fac1b 100644 --- a/sound/soc/bcm/rpi-dac.c @@ -128775,24 +128343,24 @@ index b4eaa44..afe1b41 100644 }; -From c3bd8511bef07e4a3ebf9e78fc1ed0889aaf1d62 Mon Sep 17 00:00:00 2001 +From 4725644a3f7c09811486c1324f9653e79ecbdcb7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 104/216] config: Add default configs +Subject: [PATCH 64/77] config: Add default configs --- - arch/arm/configs/bcm2709_defconfig | 1191 ++++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1186 +++++++++++++++++++++++++++++++++++ - 2 files changed, 2377 insertions(+) + arch/arm/configs/bcm2709_defconfig | 1204 ++++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1199 +++++++++++++++++++++++++++++++++++ + 2 files changed, 2403 insertions(+) create mode 100644 arch/arm/configs/bcm2709_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000..7cec5f8 +index 0000000..a3067bf --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1191 @@ +@@ -0,0 +1,1204 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +CONFIG_LOCALVERSION="-v7" @@ -129315,7 +128883,8 @@ index 0000000..7cec5f8 +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m -+# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m @@ -129350,6 +128919,7 @@ index 0000000..7cec5f8 +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y @@ -129392,6 +128962,7 @@ index 0000000..7cec5f8 +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m ++CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y @@ -129564,6 +129135,7 @@ index 0000000..7cec5f8 +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -129751,6 +129323,7 @@ index 0000000..7cec5f8 +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m @@ -129846,9 +129419,16 @@ index 0000000..7cec5f8 +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=y ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_DHT11=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y @@ -129910,6 +129490,7 @@ index 0000000..7cec5f8 +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m @@ -129986,10 +129567,10 @@ index 0000000..7cec5f8 +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 0000000..e77173b +index 0000000..6a41231 --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1186 @@ +@@ -0,0 +1,1199 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +# CONFIG_LOCALVERSION_AUTO is not set @@ -130505,7 +130086,8 @@ index 0000000..e77173b +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m -+# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m @@ -130540,6 +130122,7 @@ index 0000000..e77173b +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y @@ -130582,6 +130165,7 @@ index 0000000..e77173b +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m ++CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y @@ -130754,6 +130338,7 @@ index 0000000..e77173b +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -130941,6 +130526,7 @@ index 0000000..e77173b +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m @@ -131036,9 +130622,16 @@ index 0000000..e77173b +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=y ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_DHT11=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y @@ -131100,6 +130693,7 @@ index 0000000..e77173b +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m @@ -131177,1110 +130771,10 @@ index 0000000..e77173b +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 196c354f9d8f85f9e56bd2ce11113883f98bccaa Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Mon, 2 Mar 2015 16:34:37 +0100 -Subject: [PATCH 105/216] bcm2708: fix uart1 parameters - -System clock is 250MHz, but the device uses a non-standard -oversampling rate (8 instead of 16) hence the clock rate -has to be multiplied by 16/8 = 2. Currently the clock -rate seems to be divided by 2. - -Also correct the .type and .flags. - -Signed-off-by: Jakub Kicinski ---- - arch/arm/mach-bcm2708/bcm2708.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 16ba248..b848e4a 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -312,11 +312,12 @@ static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { - { - .mapbase = UART1_BASE + 0x40, - .irq = IRQ_AUX, -- .uartclk = 125000000, -+ .uartclk = 500000000, - .regshift = 2, - .iotype = UPIO_MEM, -- .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_8250, -+ .flags = UPF_SHARE_IRQ | UPF_FIXED_TYPE | UPF_FIXED_PORT | -+ UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_16550, - }, - {}, - }; - -From 8243fc28ee2c92452173c695fdb7990e3758fdc3 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 20 Mar 2015 15:26:11 +0100 -Subject: [PATCH 106/216] spi: bcm2835: fix all checkpath --strict messages - -The following errors/warnings issued by checkpatch.pl --strict have been fixed: -drivers/spi/spi-bcm2835.c:182: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:191: CHECK: braces {} should be used on all arms of this statement -drivers/spi/spi-bcm2835.c:234: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:256: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:271: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:346: CHECK: Alignment should match open parenthesis -total: 0 errors, 0 warnings, 6 checks, 403 lines checked - -In 2 locations the arguments had to get split/moved to the next line so that the -line width stays below 80 chars. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 419a782..779d3a8 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -179,7 +179,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - } - - static int bcm2835_spi_start_transfer(struct spi_device *spi, -- struct spi_transfer *tfr) -+ struct spi_transfer *tfr) - { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - unsigned long spi_hz, clk_hz, cdiv; -@@ -196,8 +196,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - - if (cdiv >= 65536) - cdiv = 0; /* 0 is the slowest we can go */ -- } else -+ } else { - cdiv = 0; /* 0 is the slowest we can go */ -+ } - - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; -@@ -231,7 +232,8 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - } - - static int bcm2835_spi_finish_transfer(struct spi_device *spi, -- struct spi_transfer *tfr, bool cs_change) -+ struct spi_transfer *tfr, -+ bool cs_change) - { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -@@ -253,7 +255,7 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, - } - - static int bcm2835_spi_transfer_one(struct spi_master *master, -- struct spi_message *mesg) -+ struct spi_message *mesg) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); - struct spi_transfer *tfr; -@@ -267,8 +269,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - if (err) - goto out; - -- timeout = wait_for_completion_timeout(&bs->done, -- msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS)); -+ timeout = wait_for_completion_timeout( -+ &bs->done, -+ msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) -+ ); - if (!timeout) { - err = -ETIMEDOUT; - goto out; -@@ -343,7 +347,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - clk_prepare_enable(bs->clk); - - err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, -- dev_name(&pdev->dev), master); -+ dev_name(&pdev->dev), master); - if (err) { - dev_err(&pdev->dev, "could not request IRQ: %d\n", err); - goto out_clk_disable; - -From 54e38f321ea8bb1990d6f496c0710532224a35ad Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 23 Mar 2015 15:11:53 +0100 -Subject: [PATCH 107/216] spi: bcm2835: fill/drain SPI-fifo as much as possible - during interrupt - -Implement the recommendation from the BCM2835 data-sheet -with regards to polling drivers to fill/drain the FIFO as much data as possible -also for the interrupt-driven case (which this driver is making use of). - -This means that for long transfers (>64bytes) we need one interrupt -every 64 bytes instead of every 12 bytes, as the FIFO is 16 words (not bytes) wide. - -Tested with mcp251x (can bus), fb_st7735 (TFT framebuffer device) -and enc28j60 (ethernet) drivers. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 78 +++++++++++------------------------------------ - 1 file changed, 17 insertions(+), 61 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 779d3a8..960dcce 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -91,25 +91,23 @@ static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val) - writel(val, bs->regs + reg); - } - --static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len) -+static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while (len--) { -+ while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { - byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); - if (bs->rx_buf) - *bs->rx_buf++ = byte; - } - } - --static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len) -+static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- if (len > bs->len) -- len = bs->len; -- -- while (len--) { -+ while ((bs->len) && -+ (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { - byte = bs->tx_buf ? *bs->tx_buf++ : 0; - bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); - bs->len--; -@@ -122,60 +120,24 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - struct bcm2835_spi *bs = spi_master_get_devdata(master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -- /* -- * RXR - RX needs Reading. This means 12 (or more) bytes have been -- * transmitted and hence 12 (or more) bytes have been received. -- * -- * The FIFO is 16-bytes deep. We check for this interrupt to keep the -- * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check -- * this before DONE (TX empty) just in case we delayed processing this -- * interrupt for some reason. -- * -- * We only check for this case if we have more bytes to TX; at the end -- * of the transfer, we ignore this pipelining optimization, and let -- * bcm2835_spi_finish_transfer() drain the RX FIFO. -- */ -- if (bs->len && (cs & BCM2835_SPI_CS_RXR)) { -- /* Read 12 bytes of data */ -- bcm2835_rd_fifo(bs, 12); -+ /* Read as many bytes as possible from FIFO */ -+ bcm2835_rd_fifo(bs); - -- /* Write up to 12 bytes */ -- bcm2835_wr_fifo(bs, 12); -+ if (bs->len) { /* there is more data to transmit */ -+ bcm2835_wr_fifo(bs); -+ } else { /* Transfer complete */ -+ /* Disable SPI interrupts */ -+ cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); - - /* -- * We must have written something to the TX FIFO due to the -- * bs->len check above, so cannot be DONE. Hence, return -- * early. Note that DONE could also be set if we serviced an -- * RXR interrupt really late. -+ * Wake up bcm2835_spi_transfer_one(), which will call -+ * bcm2835_spi_finish_transfer(), to drain the RX FIFO. - */ -- return IRQ_HANDLED; -+ complete(&bs->done); - } - -- /* -- * DONE - TX empty. This occurs when we first enable the transfer -- * since we do not pre-fill the TX FIFO. At any other time, given that -- * we refill the TX FIFO above based on RXR, and hence ignore DONE if -- * RXR is set, DONE really does mean end-of-transfer. -- */ -- if (cs & BCM2835_SPI_CS_DONE) { -- if (bs->len) { /* First interrupt in a transfer */ -- bcm2835_wr_fifo(bs, 16); -- } else { /* Transfer complete */ -- /* Disable SPI interrupts */ -- cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -- -- /* -- * Wake up bcm2835_spi_transfer_one(), which will call -- * bcm2835_spi_finish_transfer(), to drain the RX FIFO. -- */ -- complete(&bs->done); -- } -- -- return IRQ_HANDLED; -- } -- -- return IRQ_NONE; -+ return IRQ_HANDLED; - } - - static int bcm2835_spi_start_transfer(struct spi_device *spi, -@@ -238,12 +200,6 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -- /* Drain RX FIFO */ -- while (cs & BCM2835_SPI_CS_RXD) { -- bcm2835_rd_fifo(bs, 1); -- cs = bcm2835_rd(bs, BCM2835_SPI_CS); -- } -- - if (tfr->delay_usecs) - udelay(tfr->delay_usecs); - - -From 52469b2a3843dbd5aad2109a73e1b41371f83be3 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 19 Mar 2015 09:01:52 +0000 -Subject: [PATCH 108/216] spi: bcm2835: clock divider can be a multiple of 2 - -The official documentation is wrong in this respect. -Has been tested empirically for dividers 2-1024 - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 960dcce..8de1925 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -153,8 +153,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - if (spi_hz >= clk_hz / 2) { - cdiv = 2; /* clk_hz/2 is the fastest we can go */ - } else if (spi_hz) { -- /* CDIV must be a power of two */ -- cdiv = roundup_pow_of_two(DIV_ROUND_UP(clk_hz, spi_hz)); -+ /* CDIV must be a multiple of two */ -+ cdiv = DIV_ROUND_UP(clk_hz, spi_hz); -+ cdiv += (cdiv % 2); - - if (cdiv >= 65536) - cdiv = 0; /* 0 is the slowest we can go */ - -From b3622510de92a35d73778905be9ab4ad4235bd66 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 19 Mar 2015 09:01:53 +0000 -Subject: [PATCH 109/216] spi: bcm2835: enable support of 3-wire mode - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 8de1925..3f93718 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -67,7 +67,8 @@ - #define BCM2835_SPI_CS_CS_01 0x00000001 - - #define BCM2835_SPI_TIMEOUT_MS 30000 --#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS) -+#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ -+ | SPI_NO_CS | SPI_3WIRE) - - #define DRV_NAME "spi-bcm2835" - -@@ -163,6 +164,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - cdiv = 0; /* 0 is the slowest we can go */ - } - -+ if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) -+ cs |= BCM2835_SPI_CS_REN; -+ - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - -From c71501bcc7b07a82119e2f7b27309a62f90aa02a Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 26 Mar 2015 11:08:36 +0100 -Subject: [PATCH 110/216] spi: bcm2835: move to the transfer_one driver model - -This also allows for GPIO-CS to get used removing the limitation of -2/3 SPI devises on the SPI bus. - -Fixes: spi-cs-high with native CS with multiple devices on the spi-bus -resetting the chip selects to "normal" polarity after a finished -transfer. - -No other functionality/improvements added. - -Tested with the following 4 devices on the spi-bus: -* mcp2515 with native CS -* mcp2515 with gpio CS -* fb_st7735r with native CS - (plus spi-cs-high via transistor inverting polarity) -* enc28j60 with gpio-CS -Tested-by: Martin Sperl - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 212 +++++++++++++++++++++++++++------------------- - 1 file changed, 124 insertions(+), 88 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 3f93718..31d80eb0 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -3,6 +3,7 @@ - * - * Copyright (C) 2012 Chris Boot - * Copyright (C) 2013 Stephen Warren -+ * Copyright (C) 2015 Martin Sperl - * - * This driver is inspired by: - * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos -@@ -29,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -76,10 +78,10 @@ struct bcm2835_spi { - void __iomem *regs; - struct clk *clk; - int irq; -- struct completion done; - const u8 *tx_buf; - u8 *rx_buf; -- int len; -+ int tx_len; -+ int rx_len; - }; - - static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg) -@@ -96,10 +98,12 @@ static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { -+ while ((bs->rx_len) && -+ (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { - byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); - if (bs->rx_buf) - *bs->rx_buf++ = byte; -+ bs->rx_len--; - } - } - -@@ -107,47 +111,60 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while ((bs->len) && -+ while ((bs->tx_len) && - (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { - byte = bs->tx_buf ? *bs->tx_buf++ : 0; - bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); -- bs->len--; -+ bs->tx_len--; - } - } - -+static void bcm2835_spi_reset_hw(struct spi_master *master) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -+ -+ /* Disable SPI interrupts and transfer */ -+ cs &= ~(BCM2835_SPI_CS_INTR | -+ BCM2835_SPI_CS_INTD | -+ BCM2835_SPI_CS_TA); -+ /* and reset RX/TX FIFOS */ -+ cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; -+ -+ /* and reset the SPI_HW */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+} -+ - static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - { - struct spi_master *master = dev_id; - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - - /* Read as many bytes as possible from FIFO */ - bcm2835_rd_fifo(bs); -- -- if (bs->len) { /* there is more data to transmit */ -- bcm2835_wr_fifo(bs); -- } else { /* Transfer complete */ -- /* Disable SPI interrupts */ -- cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -- -- /* -- * Wake up bcm2835_spi_transfer_one(), which will call -- * bcm2835_spi_finish_transfer(), to drain the RX FIFO. -- */ -- complete(&bs->done); -+ /* Write as many bytes as possible to FIFO */ -+ bcm2835_wr_fifo(bs); -+ -+ /* based on flags decide if we can finish the transfer */ -+ if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) { -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* wake up the framework */ -+ complete(&master->xfer_completion); - } - - return IRQ_HANDLED; - } - --static int bcm2835_spi_start_transfer(struct spi_device *spi, -- struct spi_transfer *tfr) -+static int bcm2835_spi_transfer_one(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr) - { -- struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, cdiv; -- u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -+ /* set clock */ - spi_hz = tfr->speed_hz; - clk_hz = clk_get_rate(bs->clk); - -@@ -163,100 +180,118 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - } else { - cdiv = 0; /* 0 is the slowest we can go */ - } -+ bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - -+ /* handle all the modes */ - if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) - cs |= BCM2835_SPI_CS_REN; -- - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; - -- if (!(spi->mode & SPI_NO_CS)) { -- if (spi->mode & SPI_CS_HIGH) { -- cs |= BCM2835_SPI_CS_CSPOL; -- cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; -- } -- -- cs |= spi->chip_select; -- } -+ /* for gpio_cs set dummy CS so that no HW-CS get changed -+ * we can not run this in bcm2835_spi_set_cs, as it does -+ * not get called for cs_gpio cases, so we need to do it here -+ */ -+ if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - -- reinit_completion(&bs->done); -+ /* set transmit buffers and length */ - bs->tx_buf = tfr->tx_buf; - bs->rx_buf = tfr->rx_buf; -- bs->len = tfr->len; -+ bs->tx_len = tfr->len; -+ bs->rx_len = tfr->len; - -- bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - /* - * Enable the HW block. This will immediately trigger a DONE (TX - * empty) interrupt, upon which we will fill the TX FIFO with the - * first TX bytes. Pre-filling the TX FIFO here to avoid the - * interrupt doesn't work:-( - */ -+ cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - -- return 0; -+ /* signal that we need to wait for completion */ -+ return 1; - } - --static int bcm2835_spi_finish_transfer(struct spi_device *spi, -- struct spi_transfer *tfr, -- bool cs_change) -+static void bcm2835_spi_handle_err(struct spi_master *master, -+ struct spi_message *msg) - { -- struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); -- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -- -- if (tfr->delay_usecs) -- udelay(tfr->delay_usecs); -- -- if (cs_change) -- /* Clear TA flag */ -- bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA); -- -- return 0; -+ bcm2835_spi_reset_hw(master); - } - --static int bcm2835_spi_transfer_one(struct spi_master *master, -- struct spi_message *mesg) -+static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - { -+ /* -+ * we can assume that we are "native" as per spi_set_cs -+ * calling us ONLY when cs_gpio is not set -+ * we can also assume that we are CS < 3 as per bcm2835_spi_setup -+ * we would not get called because of error handling there. -+ * the level passed is the electrical level not enabled/disabled -+ * so it has to get translated back to enable/disable -+ * see spi_set_cs in spi.c for the implementation -+ */ -+ -+ struct spi_master *master = spi->master; - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- struct spi_transfer *tfr; -- struct spi_device *spi = mesg->spi; -- int err = 0; -- unsigned int timeout; -- bool cs_change; -- -- list_for_each_entry(tfr, &mesg->transfers, transfer_list) { -- err = bcm2835_spi_start_transfer(spi, tfr); -- if (err) -- goto out; -- -- timeout = wait_for_completion_timeout( -- &bs->done, -- msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) -- ); -- if (!timeout) { -- err = -ETIMEDOUT; -- goto out; -- } -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -+ bool enable; - -- cs_change = tfr->cs_change || -- list_is_last(&tfr->transfer_list, &mesg->transfers); -+ /* calculate the enable flag from the passed gpio_level */ -+ enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level; - -- err = bcm2835_spi_finish_transfer(spi, tfr, cs_change); -- if (err) -- goto out; -+ /* set flags for "reverse" polarity in the registers */ -+ if (spi->mode & SPI_CS_HIGH) { -+ /* set the correct CS-bits */ -+ cs |= BCM2835_SPI_CS_CSPOL; -+ cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; -+ } else { -+ /* clean the CS-bits */ -+ cs &= ~BCM2835_SPI_CS_CSPOL; -+ cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select); -+ } - -- mesg->actual_length += (tfr->len - bs->len); -+ /* select the correct chip_select depending on disabled/enabled */ -+ if (enable) { -+ /* set cs correctly */ -+ if (spi->mode & SPI_NO_CS) { -+ /* use the "undefined" chip-select */ -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; -+ } else { -+ /* set the chip select */ -+ cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01); -+ cs |= spi->chip_select; -+ } -+ } else { -+ /* disable CSPOL which puts HW-CS into deselected state */ -+ cs &= ~BCM2835_SPI_CS_CSPOL; -+ /* use the "undefined" chip-select as precaution */ -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - } - --out: -- /* Clear FIFOs, and disable the HW block */ -- bcm2835_wr(bs, BCM2835_SPI_CS, -- BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); -- mesg->status = err; -- spi_finalize_current_message(master); -+ /* finally set the calculated flags in SPI_CS */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+} - -- return 0; -+static int bcm2835_spi_setup(struct spi_device *spi) -+{ -+ /* -+ * sanity checking the native-chipselects -+ */ -+ if (spi->mode & SPI_NO_CS) -+ return 0; -+ if (gpio_is_valid(spi->cs_gpio)) -+ return 0; -+ if (spi->chip_select < 3) -+ return 0; -+ -+ /* error in the case of native CS requested with CS-id > 2 */ -+ dev_err(&spi->dev, -+ "setup: only three native chip-selects are supported\n" -+ ); -+ return -EINVAL; - } - - static int bcm2835_spi_probe(struct platform_device *pdev) -@@ -277,13 +312,14 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - master->mode_bits = BCM2835_SPI_MODE_BITS; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->num_chipselect = 3; -- master->transfer_one_message = bcm2835_spi_transfer_one; -+ master->setup = bcm2835_spi_setup; -+ master->set_cs = bcm2835_spi_set_cs; -+ master->transfer_one = bcm2835_spi_transfer_one; -+ //master->handle_err = bcm2835_spi_handle_err; - master->dev.of_node = pdev->dev.of_node; - - bs = spi_master_get_devdata(master); - -- init_completion(&bs->done); -- - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(bs->regs)) { -@@ -314,7 +350,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - goto out_clk_disable; - } - -- /* initialise the hardware */ -+ /* initialise the hardware with the default polarities */ - bcm2835_wr(bs, BCM2835_SPI_CS, - BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - - -From cf51ed163d8109aa02dfc267633ed4c0a4a81f08 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sun, 29 Mar 2015 16:03:23 +0200 -Subject: [PATCH 111/216] spi: bcm2835: fix code formatting issue - -Signed-off-by: Martin Sperl -Tested-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 31d80eb0..4aa80fd 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -289,8 +289,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) - - /* error in the case of native CS requested with CS-id > 2 */ - dev_err(&spi->dev, -- "setup: only three native chip-selects are supported\n" -- ); -+ "setup: only three native chip-selects are supported\n"); - return -EINVAL; - } - - -From 8f0e96a797cebd49ab5054b3c150386a5f840855 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sun, 29 Mar 2015 16:03:25 +0200 -Subject: [PATCH 112/216] spi: bcm2835: fill FIFO before enabling interrupts to - reduce interrupts/message - -To reduce the number of interrupts/message we fill the FIFO before -enabling interrupts - for short messages this reduces the interrupt count -from 2 to 1 interrupt. - -There have been rare cases where short (<200ns) chip-select switches with -native CS have been observed during such operation, this is why this -optimization is only enabled for GPIO-CS. - -Signed-off-by: Martin Sperl -Tested-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 4aa80fd..321dbe2 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -203,6 +203,22 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - bs->tx_len = tfr->len; - bs->rx_len = tfr->len; - -+ /* fill in fifo if we have gpio-cs -+ * note that there have been rare events where the native-CS -+ * flapped for <1us which may change the behaviour -+ * with gpio-cs this does not happen, so it is implemented -+ * only for this case -+ */ -+ if (gpio_is_valid(spi->cs_gpio)) { -+ /* enable HW block, but without interrupts enabled -+ * this would triggern an immediate interrupt -+ */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, -+ cs | BCM2835_SPI_CS_TA); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ } -+ - /* - * Enable the HW block. This will immediately trigger a DONE (TX - * empty) interrupt, upon which we will fill the TX FIFO with the - -From 31a827ccaeac10f8a5ac4ee4dc4fcdda68470eb7 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 6 Apr 2015 17:16:31 +0000 -Subject: [PATCH 113/216] spi: bcm2835: transform native-cs to gpio-cs on first - spi_setup - -Transforms the bcm-2835 native SPI-chip select to their gpio-cs equivalent. - -This allows for some support of some optimizations that are not -possible due to HW-gliches on the CS line - especially filling -the FIFO before enabling SPI interrupts (by writing to CS register) -while the transfer is already in progress (See commit: e3a2be3030e2) - -This patch also works arround some issues in bcm2835-pinctrl which does not -set the value when setting the GPIO as output - it just sets up output and -(typically) leaves the GPIO as low. When a fix for this is merged then this -gpio_set_value can get removed from bcm2835_spi_setup. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 49 ++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 44 insertions(+), 5 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 321dbe2..033b93f 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -291,8 +291,15 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - } - -+static int chip_match_name(struct gpio_chip *chip, void *data) -+{ -+ return !strcmp(chip->label, data); -+} -+ - static int bcm2835_spi_setup(struct spi_device *spi) - { -+ int err; -+ struct gpio_chip *chip; - /* - * sanity checking the native-chipselects - */ -@@ -300,13 +307,45 @@ static int bcm2835_spi_setup(struct spi_device *spi) - return 0; - if (gpio_is_valid(spi->cs_gpio)) - return 0; -- if (spi->chip_select < 3) -+ if (spi->chip_select > 1) { -+ /* error in the case of native CS requested with CS > 1 -+ * officially there is a CS2, but it is not documented -+ * which GPIO is connected with that... -+ */ -+ dev_err(&spi->dev, -+ "setup: only two native chip-selects are supported\n"); -+ return -EINVAL; -+ } -+ /* now translate native cs to GPIO */ -+ -+ /* get the gpio chip for the base */ -+ chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); -+ if (!chip) - return 0; - -- /* error in the case of native CS requested with CS-id > 2 */ -- dev_err(&spi->dev, -- "setup: only three native chip-selects are supported\n"); -- return -EINVAL; -+ /* and calculate the real CS */ -+ spi->cs_gpio = chip->base + 8 - spi->chip_select; -+ -+ /* and set up the "mode" and level */ -+ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -+ spi->chip_select, spi->cs_gpio); -+ -+ /* set up GPIO as output and pull to the correct level */ -+ err = gpio_direction_output(spi->cs_gpio, -+ (spi->mode & SPI_CS_HIGH) ? 0 : 1); -+ if (err) { -+ dev_err(&spi->dev, -+ "could not set CS%i gpio %i as output: %i", -+ spi->chip_select, spi->cs_gpio, err); -+ return err; -+ } -+ /* the implementation of pinctrl-bcm2835 currently does not -+ * set the GPIO value when using gpio_direction_output -+ * so we are setting it here explicitly -+ */ -+ gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1); -+ -+ return 0; - } - - static int bcm2835_spi_probe(struct platform_device *pdev) - -From 776aadc5da23cf97862d5eb535d8d9b8a038552f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 6 Apr 2015 17:16:30 +0000 -Subject: [PATCH 114/216] spi: bcm2835: enabling polling mode for transfers - shorter than 30us - -In cases of short transfer times the CPU is spending lots of time -in the interrupt handler and scheduler to reschedule the worker thread. - -Measurements show that we have times where it takes 29.32us to between -the last clock change and the time that the worker-thread is running again -returning from wait_for_completion_timeout(). - -During this time the interrupt-handler is running calling complete() -and then also the scheduler is rescheduling the worker thread. - -This time can vary depending on how much of the code is still in -CPU-caches, when there is a burst of spi transfers the subsequent delays -are in the order of 25us, so the value of 30us seems reasonable. - -With polling the whole transfer of 4 bytes at 10MHz finishes after 6.16us -(CS down to up) with the real transfer (clock running) taking 3.56us. -So the efficiency has much improved and is also freeing CPU cycles, -reducing interrupts and context switches. - -Because of the above 30us seems to be a reasonable limit for polling. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 112 +++++++++++++++++++++++++++++++++++----------- - 1 file changed, 86 insertions(+), 26 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 033b93f..44ee1f3 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -68,7 +68,8 @@ - #define BCM2835_SPI_CS_CS_10 0x00000002 - #define BCM2835_SPI_CS_CS_01 0x00000001 - --#define BCM2835_SPI_TIMEOUT_MS 30000 -+#define BCM2835_SPI_POLLING_LIMIT_US 30 -+#define BCM2835_SPI_TIMEOUT_MS 30000 - #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ - | SPI_NO_CS | SPI_3WIRE) - -@@ -156,12 +157,86 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+static int bcm2835_spi_transfer_one_poll(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr, -+ u32 cs, -+ unsigned long xfer_time_us) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ unsigned long timeout = jiffies + -+ max(4 * xfer_time_us * HZ / 1000000, 2uL); -+ -+ /* enable HW block without interrupts */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); -+ -+ /* set timeout to 4x the expected time, or 2 jiffies */ -+ /* loop until finished the transfer */ -+ while (bs->rx_len) { -+ /* read from fifo as much as possible */ -+ bcm2835_rd_fifo(bs); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ /* if we still expect some data after the read, -+ * check for a possible timeout -+ */ -+ if (bs->rx_len && time_after(jiffies, timeout)) { -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* and return timeout */ -+ return -ETIMEDOUT; -+ } -+ } -+ -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* and return without waiting for completion */ -+ return 0; -+} -+ -+static int bcm2835_spi_transfer_one_irq(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr, -+ u32 cs) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ -+ /* fill in fifo if we have gpio-cs -+ * note that there have been rare events where the native-CS -+ * flapped for <1us which may change the behaviour -+ * with gpio-cs this does not happen, so it is implemented -+ * only for this case -+ */ -+ if (gpio_is_valid(spi->cs_gpio)) { -+ /* enable HW block, but without interrupts enabled -+ * this would triggern an immediate interrupt -+ */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, -+ cs | BCM2835_SPI_CS_TA); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ } -+ -+ /* -+ * Enable the HW block. This will immediately trigger a DONE (TX -+ * empty) interrupt, upon which we will fill the TX FIFO with the -+ * first TX bytes. Pre-filling the TX FIFO here to avoid the -+ * interrupt doesn't work:-( -+ */ -+ cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+ -+ /* signal that we need to wait for completion */ -+ return 1; -+} -+ - static int bcm2835_spi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *tfr) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, cdiv; -+ unsigned long spi_used_hz, xfer_time_us; - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - - /* set clock */ -@@ -180,6 +255,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - } else { - cdiv = 0; /* 0 is the slowest we can go */ - } -+ spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); - bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - - /* handle all the modes */ -@@ -203,33 +279,17 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - bs->tx_len = tfr->len; - bs->rx_len = tfr->len; - -- /* fill in fifo if we have gpio-cs -- * note that there have been rare events where the native-CS -- * flapped for <1us which may change the behaviour -- * with gpio-cs this does not happen, so it is implemented -- * only for this case -- */ -- if (gpio_is_valid(spi->cs_gpio)) { -- /* enable HW block, but without interrupts enabled -- * this would triggern an immediate interrupt -- */ -- bcm2835_wr(bs, BCM2835_SPI_CS, -- cs | BCM2835_SPI_CS_TA); -- /* fill in tx fifo as much as possible */ -- bcm2835_wr_fifo(bs); -- } -+ /* calculate the estimated time in us the transfer runs */ -+ xfer_time_us = tfr->len -+ * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ -+ * 1000000 / spi_used_hz; - -- /* -- * Enable the HW block. This will immediately trigger a DONE (TX -- * empty) interrupt, upon which we will fill the TX FIFO with the -- * first TX bytes. Pre-filling the TX FIFO here to avoid the -- * interrupt doesn't work:-( -- */ -- cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+ /* for short requests run polling*/ -+ if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) -+ return bcm2835_spi_transfer_one_poll(master, spi, tfr, -+ cs, xfer_time_us); - -- /* signal that we need to wait for completion */ -- return 1; -+ return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); - } - - static void bcm2835_spi_handle_err(struct spi_master *master, - -From 0a92a30733013eae878dc15c597dfa718f2865f5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 16 Apr 2015 21:18:47 +0100 -Subject: [PATCH 115/216] spi: bcm2835: change timeout of polling driver to 1s - -The way that the timeout code is written in the polling function -the timeout does also trigger when interrupted or rescheduled while -in the polling loop. - -This patch changes the timeout from effectively 20ms (=2 jiffies) to -1 second and removes the time that the transfer really takes out of -the computation, as - per design - this is <30us and the jiffie resolution -is 10ms so that does not make any difference what so ever. - -Signed-off-by: Martin Sperl ---- - drivers/spi/spi-bcm2835.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 44ee1f3..1a915e5 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -164,13 +164,12 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, - unsigned long xfer_time_us) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- unsigned long timeout = jiffies + -- max(4 * xfer_time_us * HZ / 1000000, 2uL); -+ /* set timeout to 1 second of maximum polling */ -+ unsigned long timeout = jiffies + HZ; - - /* enable HW block without interrupts */ - bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); - -- /* set timeout to 4x the expected time, or 2 jiffies */ - /* loop until finished the transfer */ - while (bs->rx_len) { - /* read from fifo as much as possible */ - -From a53606a32ae4bdadc08985d0a67a6924c09633f1 Mon Sep 17 00:00:00 2001 +From 7de29243d1ac891a526c77e17129d6e2d547361d Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 116/216] smsx95xx: fix crimes against truesize +Subject: [PATCH 65/77] 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. @@ -132315,10 +130809,10 @@ index e29a323..aff63dc usbnet_skb_return(dev, ax_skb); } -From a6f41e34aeb0834ce943e48ee5f6655716dd53c4 Mon Sep 17 00:00:00 2001 +From 4772a6e4cc3921cb41515b7b0a91ad646d1491aa Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 117/216] smsc95xx: Disable turbo mode by default +Subject: [PATCH 66/77] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- @@ -132338,133 +130832,10 @@ index aff63dc..08a8a8c 100755 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From d8512fe40402051a7fb3ec7e7ad25f38d0abab65 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 18 Mar 2015 18:06:52 +0100 -Subject: [PATCH 118/216] HiFiBerry Digi: set SPDIF status bits for sample rate - -The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. -While this is optional, some DACs and receivers do not accept this signal. This patch -adds the sample rate bits in the SPDIF status block. ---- - sound/soc/bcm/hifiberry_digi.c | 28 ++++++++++++++++++++++++---- - 1 file changed, 24 insertions(+), 4 deletions(-) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index a294a1b..80732b8 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -74,24 +74,41 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - - long mclk_freq=0; - int mclk_div=1; -+ int sampling_freq=1; - - int ret; - - samplerate = params_rate(params); - -+ if (samplerate<=96000) { -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ } -+ - switch (samplerate) { - case 32000: -+ sampling_freq=0x03; -+ break; - case 44100: -+ sampling_freq=0x00; -+ break; - case 48000: -+ sampling_freq=0x02; -+ break; - case 88200: -+ sampling_freq=0x08; -+ break; - case 96000: -- mclk_freq=samplerate*256; -- mclk_div=WM8804_MCLKDIV_256FS; -+ sampling_freq=0x0a; - break; - case 176400: -+ sampling_freq=0x0c; -+ break; - case 192000: -- mclk_freq=samplerate*128; -- mclk_div=WM8804_MCLKDIV_128FS; -+ sampling_freq=0x0e; - break; - default: - dev_err(codec->dev, -@@ -116,6 +133,9 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - /* Power on */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); - -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ - return snd_soc_dai_set_bclk_ratio(cpu_dai,64); - } - - -From 496a822ba4493536df3181be27d4b2d2906d4fde Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 18 Apr 2015 17:20:14 +0100 -Subject: [PATCH 119/216] bcm2708-dmaengine: Add debug options - ---- - drivers/dma/bcm2708-dmaengine.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 6150b8f..8182b16 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -56,6 +56,7 @@ - - #include "virt-dma.h" - -+static unsigned dma_debug; - - struct bcm2835_dmadev { - struct dma_device ddev; -@@ -600,7 +601,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( - } - - /* Common part */ -- control_block->info |= BCM2835_DMA_WAITS(SDHCI_BCM_DMA_WAITS); -+ u32 waits = SDHCI_BCM_DMA_WAITS; -+ if ((dma_debug >> 0) & 0x1f) -+ waits = (dma_debug >> 0) & 0x1f; -+ control_block->info |= BCM2835_DMA_WAITS(waits); - control_block->info |= BCM2835_DMA_WAIT_RESP; - - /* Enable */ -@@ -952,6 +956,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - } - - dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n"); -+ dev_info(&pdev->dev, "dma_debug:%x\n", dma_debug); - - return 0; - -@@ -982,6 +987,7 @@ static struct platform_driver bcm2835_dma_driver = { - - module_platform_driver(bcm2835_dma_driver); - -+module_param(dma_debug, uint, 0644); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); - -From 4dc3a781a0d5718153bc38b1f1294523d44b8f66 Mon Sep 17 00:00:00 2001 +From 9d1fbb7b2dbe16c506f54984c361a55d1b2603fb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Apr 2015 19:30:22 +0100 -Subject: [PATCH 120/216] Add blk_pos parameter to mmc multi_io_quirk callback +Subject: [PATCH 67/77] Add blk_pos parameter to mmc multi_io_quirk callback --- drivers/mmc/card/block.c | 1 + @@ -132475,7 +130846,7 @@ Subject: [PATCH 120/216] Add blk_pos parameter to mmc multi_io_quirk callback 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index ed2e71a..ce854a9 100644 +index 60f7141..1f15cb5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1413,6 +1413,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, @@ -132487,10 +130858,10 @@ index ed2e71a..ce854a9 100644 } diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c -index f84cfb0..fec8c12 100644 +index 9df2b68..8c0ee4a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c -@@ -1798,7 +1798,9 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc) +@@ -1749,7 +1749,9 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) } static int omap_hsmmc_multi_io_quirk(struct mmc_card *card, @@ -132502,7 +130873,7 @@ index f84cfb0..fec8c12 100644 /* This controller can't do multiblock reads due to hw bugs */ if (direction == MMC_DATA_READ) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c -index 6906a90..1fb7577 100644 +index 354f4f3..4f1ccf3 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -170,7 +170,9 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) @@ -132532,10 +130903,10 @@ index dba7e1c..0c87f4f 100644 struct tmio_mmc_host *host = mmc_priv(card->host); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index c3b84a2..c1c3868f 100644 +index b0258e8..d3cdad9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -146,7 +146,9 @@ struct mmc_host_ops { +@@ -140,7 +140,9 @@ struct mmc_host_ops { * I/O. Returns the number of supported blocks for the request. */ int (*multi_io_quirk)(struct mmc_card *card, @@ -132547,3870 +130918,10 @@ index c3b84a2..c1c3868f 100644 struct mmc_card; -From 12b12cf1a7a825c46dcefa06bdde683cac053189 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 121/216] Adding bcm2835-sdhost driver, and an overlay to - enable it - -BCM2835 has two SD card interfaces. This driver uses the other one. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/sdhost-overlay.dts | 73 ++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - drivers/mmc/host/Kconfig | 10 + - drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 1685 ++++++++++++++++++++++++++++++++++ - 7 files changed, 1772 insertions(+) - create mode 100644 arch/arm/boot/dts/sdhost-overlay.dts - create mode 100644 drivers/mmc/host/bcm2835-sdhost.c - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 980b78e0..9cb5a2d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -34,6 +34,7 @@ dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -new file mode 100644 -index 0000000..33db96e ---- /dev/null -+++ b/arch/arm/boot/dts/sdhost-overlay.dts -@@ -0,0 +1,73 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&soc>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&clk_sdhost>; -+ dmas = <&dma 13>, -+ <&dma 13>; -+ dma-names = "tx", "rx"; -+ brcm,delay-after-stop = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; -+ status = "okay"; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_sdhost: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ sdhost_pins: sdhost_pins { -+ brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&mmc>; -+ __overlay__ { -+ /* Find a way to disable the other driver */ -+ compatible = ""; -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/__overrides__"; -+ __overlay__ { -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+ }; -+ -+ __overrides__ { -+ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ force_pio = <&sdhost>,"brcm,force-pio?"; -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 7cec5f8..367a04a 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -956,6 +956,7 @@ CONFIG_MMC=y - CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SPI=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e77173b..db287f3 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -949,6 +949,7 @@ CONFIG_MMC=y - CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SPI=m -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 7c093a6..1666c6c 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER - - If unsure, say 2 here. - -+config MMC_BCM2835_SDHOST -+ tristate "Support for the SDHost controller on BCM2708/9" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ help -+ This selects the SDHost controller on BCM2835/6. -+ -+ If you have a controller with this interface, say Y or M here. -+ -+ If unsure, say N. -+ - config MMC_ARMMMCI - tristate "ARM AMBA Multimedia Card Interface support" - depends on ARM_AMBA -diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 9d41de9..8a7e43e 100644 ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o - obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o - obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o - obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o -+obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o - obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o - obj-$(CONFIG_MMC_WBSD) += wbsd.o - obj-$(CONFIG_MMC_AU1X) += au1xmmc.o -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -new file mode 100644 -index 0000000..0c311b5 ---- /dev/null -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,1685 @@ -+/* -+ * BCM2835 SD host driver. -+ * -+ * Author: Phil Elwell -+ * Copyright 2015 -+ * -+ * Based on -+ * mmc-bcm2835.c by Gellert Weisz -+ * which is, in turn, based on -+ * sdhci-bcm2708.c by Broadcom -+ * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko -+ * sdhci.c and sdhci-pci.c by Pierre Ossman -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#define SAFE_READ_THRESHOLD 4 -+#define SAFE_WRITE_THRESHOLD 4 -+#define ALLOW_DMA 1 -+#define ALLOW_CMD23 0 -+#define ALLOW_FAST 1 -+#define USE_BLOCK_IRQ 1 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "sdhost-bcm2835" -+ -+#define SDCMD 0x00 /* Command to SD card - 16 R/W */ -+#define SDARG 0x04 /* Argument to SD card - 32 R/W */ -+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ -+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ -+#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ -+#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ -+#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ -+#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ -+#define SDHSTS 0x20 /* SD host status - 11 R */ -+#define SDVDD 0x30 /* SD card power control - 1 R/W */ -+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ -+#define SDHCFG 0x38 /* Host configuration - 2 R/W */ -+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ -+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ -+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ -+ -+#define SDCMD_NEW_FLAG 0x8000 -+#define SDCMD_FAIL_FLAG 0x4000 -+#define SDCMD_BUSYWAIT 0x800 -+#define SDCMD_NO_RESPONSE 0x400 -+#define SDCMD_LONG_RESPONSE 0x200 -+#define SDCMD_WRITE_CMD 0x80 -+#define SDCMD_READ_CMD 0x40 -+#define SDCMD_CMD_MASK 0x3f -+ -+#define SDCDIV_MAX_CDIV 0x7ff -+ -+#define SDHSTS_BUSY_IRPT 0x400 -+#define SDHSTS_BLOCK_IRPT 0x200 -+#define SDHSTS_SDIO_IRPT 0x100 -+#define SDHSTS_REW_TIME_OUT 0x80 -+#define SDHSTS_CMD_TIME_OUT 0x40 -+#define SDHSTS_CRC16_ERROR 0x20 -+#define SDHSTS_CRC7_ERROR 0x10 -+#define SDHSTS_FIFO_ERROR 0x08 -+/* Reserved */ -+/* Reserved */ -+#define SDHSTS_DATA_FLAG 0x01 -+ -+#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) -+#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) -+/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ -+ -+#define SDHCFG_BUSY_IRPT_EN (1<<10) -+#define SDHCFG_BLOCK_IRPT_EN (1<<8) -+#define SDHCFG_SDIO_IRPT_EN (1<<5) -+#define SDHCFG_DATA_IRPT_EN (1<<4) -+#define SDHCFG_SLOW_CARD (1<<3) -+#define SDHCFG_WIDE_EXT_BUS (1<<2) -+#define SDHCFG_WIDE_INT_BUS (1<<1) -+#define SDHCFG_REL_CMD_LINE (1<<0) -+ -+#define SDEDM_FORCE_DATA_MODE (1<<19) -+#define SDEDM_CLOCK_PULSE (1<<20) -+#define SDEDM_BYPASS (1<<21) -+ -+#define SDEDM_WRITE_THRESHOLD_SHIFT 9 -+#define SDEDM_READ_THRESHOLD_SHIFT 14 -+#define SDEDM_THRESHOLD_MASK 0x1f -+ -+/* the inclusive limit in bytes under which PIO will be used instead of DMA */ -+#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER -+#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER -+#else -+#define PIO_DMA_BARRIER 0 -+#endif -+ -+#define MIN_FREQ 400000 -+#define TIMEOUT_VAL 0xE -+#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) -+ -+#ifndef BCM2708_PERI_BASE -+ #define BCM2708_PERI_BASE 0x20000000 -+#endif -+ -+/* FIXME: Needs IOMMU support */ -+#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) -+ -+ -+struct bcm2835_host { -+ spinlock_t lock; -+ -+ void __iomem *ioaddr; -+ u32 phys_addr; -+ -+ struct mmc_host *mmc; -+ -+ u32 timeout; -+ -+ int clock; /* Current clock speed */ -+ -+ bool slow_card; /* Force 11-bit divisor */ -+ -+ unsigned int max_clk; /* Max possible freq */ -+ unsigned int timeout_clk; /* Timeout freq (KHz) */ -+ -+ struct tasklet_struct finish_tasklet; /* Tasklet structures */ -+ -+ struct timer_list timer; /* Timer for timeouts */ -+ -+ struct sg_mapping_iter sg_miter; /* SG state for PIO */ -+ unsigned int blocks; /* remaining PIO blocks */ -+ -+ int irq; /* Device IRQ */ -+ -+ -+ /* cached registers */ -+ u32 hcfg; -+ u32 cdiv; -+ -+ struct mmc_request *mrq; /* Current request */ -+ struct mmc_command *cmd; /* Current command */ -+ struct mmc_data *data; /* Current data request */ -+ unsigned int data_complete:1; /* Data finished before cmd */ -+ -+ unsigned int flush_fifo:1; /* Drain the fifo when finishing */ -+ -+ unsigned int use_busy:1; /* Wait for busy interrupt */ -+ -+ u32 thread_isr; -+ -+ /*DMA part*/ -+ struct dma_chan *dma_chan_rx; /* DMA channel for reads */ -+ struct dma_chan *dma_chan_tx; /* DMA channel for writes */ -+ -+ bool allow_dma; -+ bool have_dma; -+ bool use_dma; -+ /*end of DMA part*/ -+ -+ int max_delay; /* maximum length of time spent waiting */ -+ struct timeval stop_time; /* when the last stop was issued */ -+ u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ -+}; -+ -+ -+static inline void bcm2835_sdhost_write(struct bcm2835_host *host, u32 val, int reg) -+{ -+ writel(val, host->ioaddr + reg); -+} -+ -+static inline u32 bcm2835_sdhost_read(struct bcm2835_host *host, int reg) -+{ -+ return readl(host->ioaddr + reg); -+} -+ -+static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg) -+{ -+ return readl_relaxed(host->ioaddr + reg); -+} -+ -+static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) -+{ -+ pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", -+ mmc_hostname(host->mmc)); -+ -+ pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", -+ bcm2835_sdhost_read(host, SDCMD)); -+ pr_info(DRIVER_NAME ": SDARG 0x%08x\n", -+ bcm2835_sdhost_read(host, SDARG)); -+ pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", -+ bcm2835_sdhost_read(host, SDTOUT)); -+ pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", -+ bcm2835_sdhost_read(host, SDCDIV)); -+ pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP0)); -+ pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP1)); -+ pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP2)); -+ pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP3)); -+ pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHSTS)); -+ pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", -+ bcm2835_sdhost_read(host, SDVDD)); -+ pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", -+ bcm2835_sdhost_read(host, SDEDM)); -+ pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHCFG)); -+ pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHBCT)); -+ pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHBLC)); -+ -+ pr_debug(DRIVER_NAME ": ===========================================\n"); -+} -+ -+ -+static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) -+{ -+ bcm2835_sdhost_write(host, on ? 1 : 0, SDVDD); -+} -+ -+ -+static void bcm2835_sdhost_reset(struct bcm2835_host *host) -+{ -+ u32 temp; -+ -+ pr_debug("bcm2835_sdhost_reset\n"); -+ -+ bcm2835_sdhost_set_power(host, false); -+ -+ bcm2835_sdhost_write(host, 0, SDCMD); -+ bcm2835_sdhost_write(host, 0, SDARG); -+ bcm2835_sdhost_write(host, 0xf00000, SDTOUT); -+ bcm2835_sdhost_write(host, 0, SDCDIV); -+ bcm2835_sdhost_write(host, 0x7f8, SDHSTS); /* Write 1s to clear */ -+ bcm2835_sdhost_write(host, 0, SDHCFG); -+ bcm2835_sdhost_write(host, 0, SDHBCT); -+ bcm2835_sdhost_write(host, 0, SDHBLC); -+ -+ /* Limit fifo usage due to silicon bug */ -+ temp = bcm2835_sdhost_read(host, SDEDM); -+ temp &= ~((SDEDM_THRESHOLD_MASK<clock = 0; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ mmiowb(); -+} -+ -+static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); -+ -+static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) -+{ -+ pr_debug("bcm2835_sdhost_init(%d)\n", soft); -+ -+ /* Set interrupt enables */ -+ host->hcfg = SDHCFG_BUSY_IRPT_EN; -+ -+ bcm2835_sdhost_reset(host); -+ -+ if (soft) { -+ /* force clock reconfiguration */ -+ host->clock = 0; -+ bcm2835_sdhost_set_ios(host->mmc, &host->mmc->ios); -+ } -+} -+ -+static bool bcm2835_sdhost_is_write_complete(struct bcm2835_host *host) -+{ -+ bool write_complete = ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1); -+ -+ if (!write_complete) { -+ /* Request an IRQ for the last block */ -+ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ if ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1) { -+ /* The write has now completed. Disable the interrupt -+ and clear the status flag */ -+ host->hcfg &= ~SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ bcm2835_sdhost_write(host, SDHSTS_BLOCK_IRPT, SDHSTS); -+ write_complete = true; -+ } -+ } -+ -+ return write_complete; -+} -+ -+static void bcm2835_sdhost_wait_write_complete(struct bcm2835_host *host) -+{ -+ int timediff; -+#ifdef DEBUG -+ static struct timeval start_time; -+ static int max_stall_time = 0; -+ static int total_stall_time = 0; -+ struct timeval before, after; -+ -+ do_gettimeofday(&before); -+ if (max_stall_time == 0) -+ start_time = before; -+#endif -+ -+ timediff = 0; -+ -+ while (1) { -+ u32 edm = bcm2835_sdhost_read(host, SDEDM); -+ if ((edm & 0xf) == 1) -+ break; -+ timediff++; -+ if (timediff > 5000000) { -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + -+ (after.tv_usec - before.tv_usec); -+ -+ pr_err(" wait_write_complete - still waiting after %dus\n", -+ timediff); -+#else -+ pr_err(" wait_write_complete - still waiting after %d retries\n", -+ timediff); -+#endif -+ bcm2835_sdhost_dumpregs(host); -+ host->data->error = -ETIMEDOUT; -+ return; -+ } -+ } -+ -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + (after.tv_usec - before.tv_usec); -+ -+ total_stall_time += timediff; -+ if (timediff > max_stall_time) -+ max_stall_time = timediff; -+ -+ if ((after.tv_sec - start_time.tv_sec) > 10) { -+ pr_debug(" wait_write_complete - max wait %dus, total %dus\n", -+ max_stall_time, total_stall_time); -+ start_time = after; -+ max_stall_time = 0; -+ total_stall_time = 0; -+ } -+#endif -+} -+ -+static void bcm2835_sdhost_finish_data(struct bcm2835_host *host); -+ -+static void bcm2835_sdhost_dma_complete(void *param) -+{ -+ struct bcm2835_host *host = param; -+ struct dma_chan *dma_chan; -+ unsigned long flags; -+ u32 dir_data; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (host->data) { -+ bool write_complete; -+ if (USE_BLOCK_IRQ) -+ write_complete = bcm2835_sdhost_is_write_complete(host); -+ else { -+ bcm2835_sdhost_wait_write_complete(host); -+ write_complete = true; -+ } -+ pr_debug("dma_complete() - write_complete=%d\n", -+ write_complete); -+ -+ if (write_complete || (host->data->flags & MMC_DATA_READ)) -+ { -+ if (write_complete) { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ } else { -+ dma_chan = host->dma_chan_rx; -+ dir_data = DMA_FROM_DEVICE; -+ } -+ -+ dma_unmap_sg(dma_chan->device->dev, -+ host->data->sg, host->data->sg_len, -+ dir_data); -+ -+ bcm2835_sdhost_finish_data(host); -+ } -+ } -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) -+{ -+ unsigned long flags; -+ size_t blksize, len; -+ u32 *buf; -+ -+ blksize = host->data->blksz; -+ -+ local_irq_save(flags); -+ -+ while (blksize) { -+ if (!sg_miter_next(&host->sg_miter)) -+ BUG(); -+ -+ len = min(host->sg_miter.length, blksize); -+ BUG_ON(len % 4); -+ -+ blksize -= len; -+ host->sg_miter.consumed = len; -+ -+ buf = (u32 *)host->sg_miter.addr; -+ -+ while (len) { -+ while (1) { -+ u32 hsts; -+ hsts = bcm2835_sdhost_read(host, SDHSTS); -+ if (hsts & SDHSTS_DATA_FLAG) -+ break; -+ -+ if (hsts & SDHSTS_ERROR_MASK) { -+ pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", -+ mmc_hostname(host->mmc), -+ hsts, -+ bcm2835_sdhost_read(host, SDHBCT), -+ blksize + len); -+ if (hsts & SDHSTS_REW_TIME_OUT) -+ host->data->error = -ETIMEDOUT; -+ else if (hsts & (SDHSTS_CRC16_ERROR || -+ SDHSTS_CRC7_ERROR)) -+ host->data->error = -EILSEQ; -+ else { -+ pr_err("%s: unexpected data error\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ } -+ } -+ } -+ -+ *(buf++) = bcm2835_sdhost_read(host, SDDATA); -+ len -= 4; -+ } -+ } -+ -+ sg_miter_stop(&host->sg_miter); -+ -+ local_irq_restore(flags); -+} -+ -+static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) -+{ -+ unsigned long flags; -+ size_t blksize, len; -+ u32 *buf; -+ -+ blksize = host->data->blksz; -+ -+ local_irq_save(flags); -+ -+ while (blksize) { -+ if (!sg_miter_next(&host->sg_miter)) -+ BUG(); -+ -+ len = min(host->sg_miter.length, blksize); -+ BUG_ON(len % 4); -+ -+ blksize -= len; -+ host->sg_miter.consumed = len; -+ -+ buf = host->sg_miter.addr; -+ -+ while (len) { -+ while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) -+ continue; -+ bcm2835_sdhost_write(host, *(buf++), SDDATA); -+ len -= 4; -+ } -+ } -+ -+ sg_miter_stop(&host->sg_miter); -+ -+ local_irq_restore(flags); -+} -+ -+ -+static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) -+{ -+ BUG_ON(!host->data); -+ -+ if (host->data->flags & MMC_DATA_READ) -+ bcm2835_sdhost_read_block_pio(host); -+ else -+ bcm2835_sdhost_write_block_pio(host); -+} -+ -+ -+static void bcm2835_sdhost_transfer_dma(struct bcm2835_host *host) -+{ -+ u32 len, dir_data, dir_slave; -+ struct dma_async_tx_descriptor *desc = NULL; -+ struct dma_chan *dma_chan; -+ -+ pr_debug("bcm2835_sdhost_transfer_dma()\n"); -+ -+ WARN_ON(!host->data); -+ -+ if (!host->data) -+ return; -+ -+ if (host->data->flags & MMC_DATA_READ) { -+ dma_chan = host->dma_chan_rx; -+ dir_data = DMA_FROM_DEVICE; -+ dir_slave = DMA_DEV_TO_MEM; -+ } else { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ dir_slave = DMA_MEM_TO_DEV; -+ } -+ -+ BUG_ON(!dma_chan->device); -+ BUG_ON(!dma_chan->device->dev); -+ BUG_ON(!host->data->sg); -+ -+ len = dma_map_sg(dma_chan->device->dev, host->data->sg, -+ host->data->sg_len, dir_data); -+ if (len > 0) { -+ desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg, -+ len, dir_slave, -+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -+ } else { -+ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); -+ } -+ if (desc) { -+ desc->callback = bcm2835_sdhost_dma_complete; -+ desc->callback_param = host; -+ dmaengine_submit(desc); -+ dma_async_issue_pending(dma_chan); -+ } -+ -+} -+ -+ -+static void bcm2835_sdhost_set_transfer_irqs(struct bcm2835_host *host) -+{ -+ u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN | -+ SDHCFG_BUSY_IRPT_EN; -+ if (host->use_dma) -+ host->hcfg = (host->hcfg & ~all_irqs) | -+ SDHCFG_BUSY_IRPT_EN; -+ else -+ host->hcfg = (host->hcfg & ~all_irqs) | -+ SDHCFG_DATA_IRPT_EN | -+ SDHCFG_BUSY_IRPT_EN; -+ -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+} -+ -+ -+static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd) -+{ -+ struct mmc_data *data = cmd->data; -+ -+ WARN_ON(host->data); -+ -+ if (!data) -+ return; -+ -+ /* Sanity checks */ -+ BUG_ON(data->blksz * data->blocks > 524288); -+ BUG_ON(data->blksz > host->mmc->max_blk_size); -+ BUG_ON(data->blocks > 65535); -+ -+ host->data = data; -+ host->data_complete = 0; -+ host->flush_fifo = 0; -+ host->data->bytes_xfered = 0; -+ -+ if (!host->use_dma) { -+ int flags; -+ -+ flags = SG_MITER_ATOMIC; -+ if (data->flags & MMC_DATA_READ) -+ flags |= SG_MITER_TO_SG; -+ else -+ flags |= SG_MITER_FROM_SG; -+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); -+ host->blocks = data->blocks; -+ } -+ -+ host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; -+ -+ bcm2835_sdhost_set_transfer_irqs(host); -+ -+ bcm2835_sdhost_write(host, data->blksz, SDHBCT); -+ if (host->use_dma) -+ bcm2835_sdhost_write(host, data->blocks, SDHBLC); -+ -+ BUG_ON(!host->data); -+} -+ -+ -+void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd) -+{ -+ u32 sdcmd; -+ unsigned long timeout; -+ -+ WARN_ON(host->cmd); -+ -+ if (1) { -+ pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", -+ cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); -+ if (cmd->data) -+ pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", -+ (cmd->data->flags & MMC_DATA_READ) ? -+ "read" : "write", cmd->data->blocks, -+ cmd->data->blksz); -+ } -+ -+ /* Wait max 10 ms */ -+ timeout = 1000; -+ -+ while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { -+ if (timeout == 0) { -+ pr_err("%s: Previous command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ timeout--; -+ udelay(10); -+ } -+ -+ if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { -+ host->max_delay = (1000-timeout)/100; -+ pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); -+ } -+ -+ timeout = jiffies; -+#ifdef CONFIG_ARCH_BCM2835 -+ if (!cmd->data && cmd->busy_timeout > 9000) -+ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; -+ else -+#endif -+ timeout += 10 * HZ; -+ mod_timer(&host->timer, timeout); -+ -+ host->cmd = cmd; -+ -+ bcm2835_sdhost_prepare_data(host, cmd); -+ -+ bcm2835_sdhost_write(host, cmd->arg, SDARG); -+ -+ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { -+ pr_err("%s: Unsupported response type!\n", -+ mmc_hostname(host->mmc)); -+ cmd->error = -EINVAL; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ sdcmd = cmd->opcode & SDCMD_CMD_MASK; -+ -+ if (!(cmd->flags & MMC_RSP_PRESENT)) -+ sdcmd |= SDCMD_NO_RESPONSE; -+ else { -+ if (cmd->flags & MMC_RSP_136) -+ sdcmd |= SDCMD_LONG_RESPONSE; -+ if (cmd->flags & MMC_RSP_BUSY) { -+ sdcmd |= SDCMD_BUSYWAIT; -+ host->use_busy = 1; -+ } -+ } -+ -+ if (cmd->data) { -+ if (host->delay_after_stop) { -+ struct timeval now; -+ int time_since_stop; -+ do_gettimeofday(&now); -+ time_since_stop = (now.tv_sec - host->stop_time.tv_sec); -+ if (time_since_stop < 2) { -+ /* Possibly less than one second */ -+ time_since_stop = time_since_stop * 1000000 + -+ (now.tv_usec - host->stop_time.tv_usec); -+ if (time_since_stop < host->delay_after_stop) -+ udelay(host->delay_after_stop - -+ time_since_stop); -+ } -+ } -+ -+ if (cmd->data->flags & MMC_DATA_WRITE) -+ sdcmd |= SDCMD_WRITE_CMD; -+ if (cmd->data->flags & MMC_DATA_READ) -+ sdcmd |= SDCMD_READ_CMD; -+ } -+ -+ bcm2835_sdhost_write(host, sdcmd | SDCMD_NEW_FLAG, SDCMD); -+} -+ -+ -+static void bcm2835_sdhost_finish_command(struct bcm2835_host *host); -+static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host); -+ -+static void bcm2835_sdhost_finish_data(struct bcm2835_host *host) -+{ -+ struct mmc_data *data; -+ -+ data = host->data; -+ BUG_ON(!data); -+ -+ pr_debug("finish_data(error %d, stop %d, sbc %d)\n", -+ data->error, data->stop ? 1 : 0, -+ host->mrq->sbc ? 1 : 0); -+ -+ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ -+ if (data->error) { -+ data->bytes_xfered = 0; -+ } else -+ data->bytes_xfered = data->blksz * data->blocks; -+ -+ host->data_complete = 1; -+ -+ if (host->cmd) { -+ /* -+ * Data managed to finish before the -+ * command completed. Make sure we do -+ * things in the proper order. -+ */ -+ pr_debug("Finished early - HSTS %x\n", -+ bcm2835_sdhost_read(host, SDHSTS)); -+ } -+ else -+ bcm2835_sdhost_transfer_complete(host); -+} -+ -+ -+static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) -+{ -+ struct mmc_data *data; -+ -+ BUG_ON(host->cmd); -+ BUG_ON(!host->data); -+ BUG_ON(!host->data_complete); -+ -+ data = host->data; -+ host->data = NULL; -+ -+ pr_debug("transfer_complete(error %d, stop %d)\n", -+ data->error, data->stop ? 1 : 0); -+ -+ if (data->error) -+ /* -+ * The controller needs a reset of internal state machines -+ * upon error conditions. -+ */ -+ bcm2835_sdhost_reset(host); -+ -+ /* -+ * Need to send CMD12 if - -+ * a) open-ended multiblock transfer (no CMD23) -+ * b) error in multiblock transfer -+ */ -+ if (data->stop && -+ (data->error || -+ !host->mrq->sbc)) { -+ host->flush_fifo = 1; -+ bcm2835_sdhost_send_command(host, data->stop); -+ if (host->delay_after_stop) -+ do_gettimeofday(&host->stop_time); -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+ } else { -+ tasklet_schedule(&host->finish_tasklet); -+ } -+} -+ -+static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) -+{ -+ u32 sdcmd; -+ int timeout = 1000; -+#ifdef DEBUG -+ struct timeval before, after; -+ int timediff = 0; -+#endif -+ -+ pr_debug("finish_command(%x)\n", bcm2835_sdhost_read(host, SDCMD)); -+ -+ BUG_ON(!host->cmd || !host->mrq); -+ -+#ifdef DEBUG -+ do_gettimeofday(&before); -+#endif -+ for (sdcmd = bcm2835_sdhost_read(host, SDCMD); -+ (sdcmd & SDCMD_NEW_FLAG) && timeout; -+ timeout--) { -+ if (host->flush_fifo) { -+ while (bcm2835_sdhost_read(host, SDHSTS) & -+ SDHSTS_DATA_FLAG) -+ (void)bcm2835_sdhost_read(host, SDDATA); -+ } -+ udelay(10); -+ sdcmd = bcm2835_sdhost_read(host, SDCMD); -+ } -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + -+ (after.tv_usec - before.tv_usec); -+ -+ pr_debug(" finish_command - waited %dus\n", timediff); -+#endif -+ -+ if (timeout == 0) { -+ pr_err("%s: Command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ if (host->flush_fifo) { -+ for (timeout = 100; -+ (bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG) && timeout; -+ timeout--) { -+ (void)bcm2835_sdhost_read(host, SDDATA); -+ } -+ host->flush_fifo = 0; -+ if (timeout == 0) { -+ pr_err("%s: FIFO never drained.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ } -+ -+ /* Check for errors */ -+ if (sdcmd & SDCMD_FAIL_FLAG) -+ { -+ u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); -+ -+ pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", -+ mmc_hostname(host->mmc), sdcmd, sdhsts, -+ bcm2835_sdhost_read(host, SDEDM)); -+ -+ if (sdhsts & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else -+ { -+ pr_err("%s: unexpected command error\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ } -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ if (host->cmd->flags & MMC_RSP_PRESENT) { -+ if (host->cmd->flags & MMC_RSP_136) { -+ int i; -+ for (i = 0; i < 4; i++) -+ host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); -+ pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", -+ host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); -+ } else { -+ host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); -+ pr_debug("bcm2835_sdhost_finish_command: %08x\n", -+ host->cmd->resp[0]); -+ } -+ } -+ -+ host->cmd->error = 0; -+ -+ if (host->cmd == host->mrq->sbc) { -+ /* Finished CMD23, now send actual command. */ -+ host->cmd = NULL; -+ bcm2835_sdhost_send_command(host, host->mrq->cmd); -+ -+ if (host->cmd->data && host->use_dma) -+ /* DMA transfer starts now, PIO starts after irq */ -+ bcm2835_sdhost_transfer_dma(host); -+ -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+ } else if (host->cmd == host->mrq->stop) -+ /* Finished CMD12 */ -+ tasklet_schedule(&host->finish_tasklet); -+ else { -+ /* Processed actual command. */ -+ host->cmd = NULL; -+ if (!host->data) -+ tasklet_schedule(&host->finish_tasklet); -+ else if (host->data_complete) -+ bcm2835_sdhost_transfer_complete(host); -+ } -+} -+ -+static void bcm2835_sdhost_timeout_timer(unsigned long data) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ -+ host = (struct bcm2835_host *)data; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (host->mrq) { -+ pr_err("%s: Timeout waiting for hardware interrupt.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ -+ if (host->data) { -+ host->data->error = -ETIMEDOUT; -+ bcm2835_sdhost_finish_data(host); -+ } else { -+ if (host->cmd) -+ host->cmd->error = -ETIMEDOUT; -+ else -+ host->mrq->cmd->error = -ETIMEDOUT; -+ -+ pr_debug("timeout_timer tasklet_schedule\n"); -+ tasklet_schedule(&host->finish_tasklet); -+ } -+ } -+ -+ mmiowb(); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) -+{ -+ if (enable) -+ host->hcfg |= SDHCFG_SDIO_IRPT_EN; -+ else -+ host->hcfg &= ~SDHCFG_SDIO_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ mmiowb(); -+} -+ -+static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) -+{ -+ struct bcm2835_host *host = mmc_priv(mmc); -+ unsigned long flags; -+ -+ pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); -+ spin_lock_irqsave(&host->lock, flags); -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ if (!host->cmd) { -+ pr_err("%s: Got command busy interrupt 0x%08x even " -+ "though no command operation was in progress.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return 0; -+ } -+ -+ if (!host->use_busy) { -+ pr_err("%s: Got command busy interrupt 0x%08x even " -+ "though not expecting one.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return 0; -+ } -+ host->use_busy = 0; -+ -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | -+ SDHSTS_FIFO_ERROR)) -+ host->cmd->error = -EILSEQ; -+ -+ if (host->cmd->error) -+ tasklet_schedule(&host->finish_tasklet); -+ else -+ bcm2835_sdhost_finish_command(host); -+ -+ return handled; -+} -+ -+static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ /* There are no dedicated data/space available interrupt -+ status bits, so it is necessary to use the single shared -+ data/space available FIFO status bits. It is therefore not -+ an error to get here when there is no data transfer in -+ progress. */ -+ if (!host->data) -+ return 0; -+ -+ // XXX FIFO_ERROR -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && -+ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) -+ != MMC_BUS_TEST_R)) -+ host->cmd->error = -EILSEQ; -+ -+ /* Use the block interrupt for writes after the first block */ -+ if (!(host->data->flags & MMC_DATA_READ)) { -+ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); -+ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ if (host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ bcm2835_sdhost_transfer_pio(host); -+ } else { -+ if (!host->data->error) { -+ bcm2835_sdhost_transfer_pio(host); -+ host->blocks--; -+ } -+ if ((host->blocks == 0) || host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ } -+ -+ return handled; -+} -+ -+static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ struct dma_chan *dma_chan; -+ u32 dir_data; -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ if (!host->data) { -+ pr_err("%s: Got block interrupt 0x%08x even " -+ "though no data operation was in progress.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return handled; -+ } -+ -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && -+ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) -+ != MMC_BUS_TEST_R)) -+ host->cmd->error = -EILSEQ; -+ -+ if (!host->use_dma) { -+ BUG_ON(!host->blocks); -+ host->blocks--; -+ if ((host->blocks == 0) || host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ else -+ bcm2835_sdhost_transfer_pio(host); -+ } else if (host->data->flags & MMC_DATA_WRITE) { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ dma_unmap_sg(dma_chan->device->dev, -+ host->data->sg, host->data->sg_len, -+ dir_data); -+ -+ bcm2835_sdhost_finish_data(host); -+ } -+ -+ return handled; -+} -+ -+ -+static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) -+{ -+ irqreturn_t result = IRQ_NONE; -+ struct bcm2835_host *host = dev_id; -+ u32 unexpected = 0, early = 0; -+ int loops = 0; -+#ifndef CONFIG_ARCH_BCM2835 -+ int cardint = 0; -+#endif -+ spin_lock(&host->lock); -+ -+ for (loops = 0; loops < 1; loops++) { -+ u32 intmask, handled; -+ -+ intmask = bcm2835_sdhost_read(host, SDHSTS); -+ handled = intmask & (SDHSTS_BUSY_IRPT | -+ SDHSTS_BLOCK_IRPT | -+ SDHSTS_SDIO_IRPT | -+ SDHSTS_DATA_FLAG); -+ if ((handled == SDHSTS_DATA_FLAG) && // XXX -+ (loops == 0) && !host->data) { -+ pr_err("%s: sdhost_irq data interrupt 0x%08x even " -+ "though no data operation was in progress.\n", -+ mmc_hostname(host->mmc), -+ (unsigned)intmask); -+ -+ bcm2835_sdhost_dumpregs(host); -+ } -+ -+ if (loops) -+ early |= handled; -+ -+ if (!handled) -+ break; -+ -+ result = IRQ_HANDLED; -+ -+ /* Clear all interrupts and notifications */ -+ bcm2835_sdhost_write(host, intmask, SDHSTS); -+ -+ if (intmask & SDHSTS_BUSY_IRPT) -+ handled |= bcm2835_sdhost_busy_irq(host, intmask); -+ -+ /* There is no true data interrupt status bit, so it is -+ necessary to qualify the data flag with the interrupt -+ enable bit */ -+ if ((intmask & SDHSTS_DATA_FLAG) && -+ (host->hcfg & SDHCFG_DATA_IRPT_EN)) -+ handled |= bcm2835_sdhost_data_irq(host, intmask); -+ -+ if (intmask & SDHSTS_BLOCK_IRPT) -+ handled |= bcm2835_sdhost_block_irq(host, intmask); -+ -+ if (intmask & SDHSTS_SDIO_IRPT) { -+#ifndef CONFIG_ARCH_BCM2835 -+ cardint = 1; -+#else -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, false); -+ host->thread_isr |= SDHSTS_SDIO_IRPT; -+ result = IRQ_WAKE_THREAD; -+#endif -+ } -+ -+ unexpected |= (intmask & ~handled); -+ } -+ -+ mmiowb(); -+ -+ spin_unlock(&host->lock); -+ -+ if (early) -+ pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); -+ -+ if (unexpected) { -+ pr_err("%s: Unexpected interrupt 0x%08x.\n", -+ mmc_hostname(host->mmc), unexpected); -+ bcm2835_sdhost_dumpregs(host); -+ } -+ -+#ifndef CONFIG_ARCH_BCM2835 -+ if (cardint) -+ mmc_signal_sdio_irq(host->mmc); -+#endif -+ -+ return result; -+} -+ -+#ifdef CONFIG_ARCH_BCM2835 -+static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) -+{ -+ struct bcm2835_host *host = dev_id; -+ unsigned long flags; -+ u32 isr; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ isr = host->thread_isr; -+ host->thread_isr = 0; -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ if (isr & SDHSTS_SDIO_IRPT) { -+ sdio_run_irqs(host->mmc); -+ -+/* Is this necessary? Why re-enable an interrupt which is enabled? -+ spin_lock_irqsave(&host->lock, flags); -+ if (host->flags & SDHSTS_SDIO_IRPT_ENABLED) -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, true); -+ spin_unlock_irqrestore(&host->lock, flags); -+*/ -+ } -+ -+ return isr ? IRQ_HANDLED : IRQ_NONE; -+} -+#endif -+ -+ -+ -+void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) -+{ -+ int div = 0; /* Initialized for compiler warning */ -+ -+ /* The SDCDIV register has 11 bits, and holds (div - 2). -+ But in data mode the max is 50MHz wihout a minimum, and only the -+ bottom 3 bits are used. Since the switch over is automatic (unless -+ we have marked the card as slow...), chosen values have to make -+ sense in both modes. -+ Ident mode must be 100-400KHz, so can range check the requested -+ clock. CMD15 must be used to return to data mode, so this can be -+ monitored. -+ -+ clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz -+ 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz -+ -+ 623->400KHz/27.8MHz -+ reset value (507)->491159/50MHz -+ -+ BUT, the 3-bit clock divisor in data mode is too small if the -+ core clock is higher than 250MHz, so instead use the SLOW_CARD -+ configuration bit to force the use of the ident clock divisor -+ at all times. -+ */ -+ -+ host->mmc->actual_clock = 0; -+ -+ if (clock < 100000) { -+ /* Can't stop the clock, but make it as slow as possible -+ * to show willing -+ */ -+ host->cdiv = SDCDIV_MAX_CDIV; -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ return; -+ } -+ -+ div = host->max_clk / clock; -+ if (div < 2) -+ div = 2; -+ if ((host->max_clk / div) > clock) -+ div++; -+ div -= 2; -+ -+ if (div > SDCDIV_MAX_CDIV) -+ div = SDCDIV_MAX_CDIV; -+ -+ host->mmc->actual_clock = host->max_clk / (div + 2); -+ -+ host->cdiv = div; -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ -+ pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", -+ clock, host->max_clk, host->cdiv, host->mmc->actual_clock); -+} -+ -+static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ -+ if (1) { -+ struct mmc_command *cmd = mrq->cmd; -+ const char *src = "cmd"; -+ BUG_ON(!cmd); -+ pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", -+ src, cmd->opcode, cmd->arg, cmd->flags); -+ if (cmd->data) -+ pr_debug("bcm2835_sdhost_request: %s %d*%d\n", -+ (cmd->data->flags & MMC_DATA_READ) ? -+ "read" : "write", cmd->data->blocks, -+ cmd->data->blksz); -+ } -+ -+ if (mrq->data && !is_power_of_2(mrq->data->blksz)) { -+ pr_err("%s: Unsupported block size (%d bytes)\n", -+ mmc_hostname(mmc), mrq->data->blksz); -+ mrq->cmd->error = -EINVAL; -+ mmc_request_done(mmc, mrq); -+ return; -+ } -+ -+ host = mmc_priv(mmc); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ WARN_ON(host->mrq != NULL); -+ -+ host->mrq = mrq; -+ -+ if (mrq->sbc) -+ bcm2835_sdhost_send_command(host, mrq->sbc); -+ else -+ bcm2835_sdhost_send_command(host, mrq->cmd); -+ -+ mmiowb(); -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ if (!mrq->sbc && mrq->cmd->data && host->use_dma) -+ /* DMA transfer starts now, PIO starts after irq */ -+ bcm2835_sdhost_transfer_dma(host); -+ -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+} -+ -+ -+static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ -+ struct bcm2835_host *host = mmc_priv(mmc); -+ unsigned long flags; -+ -+ pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", -+ ios->clock, ios->power_mode, ios->bus_width, -+ ios->timing, ios->signal_voltage, ios->drv_type); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (!ios->clock || ios->clock != host->clock) { -+ bcm2835_sdhost_set_clock(host, ios->clock); -+ host->clock = ios->clock; -+ } -+ -+ /* set bus width */ -+ host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; -+ if (ios->bus_width == MMC_BUS_WIDTH_4) -+ host->hcfg |= SDHCFG_WIDE_EXT_BUS; -+ -+ host->hcfg |= SDHCFG_WIDE_INT_BUS; -+ -+ /* Disable clever clock switching, to cope with fast core clocks */ -+ host->hcfg |= SDHCFG_SLOW_CARD; -+ -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ -+ mmiowb(); -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static int bcm2835_sdhost_multi_io_quirk(struct mmc_card *card, -+ unsigned int direction, -+ u32 blk_pos, int blk_size) -+{ -+ /* There is a bug in the host controller hardware that makes -+ reading the final sector of the card as part of a multiple read -+ problematic. Detect that case and shorten the read accordingly. -+ */ -+ /* csd.capacity is in weird units - convert to sectors */ -+ u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9)); -+ -+ if ((direction == MMC_DATA_READ) && -+ ((blk_pos + blk_size) == card_sectors)) -+ blk_size--; -+ -+ return blk_size; -+} -+ -+ -+static struct mmc_host_ops bcm2835_sdhost_ops = { -+ .request = bcm2835_sdhost_request, -+ .set_ios = bcm2835_sdhost_set_ios, -+ .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, -+ .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, -+}; -+ -+ -+static void bcm2835_sdhost_tasklet_finish(unsigned long param) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ struct mmc_request *mrq; -+ -+ host = (struct bcm2835_host *)param; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ /* -+ * If this tasklet gets rescheduled while running, it will -+ * be run again afterwards but without any active request. -+ */ -+ if (!host->mrq) { -+ spin_unlock_irqrestore(&host->lock, flags); -+ return; -+ } -+ -+ del_timer(&host->timer); -+ -+ mrq = host->mrq; -+ -+ /* -+ * The controller needs a reset of internal state machines -+ * upon error conditions. -+ */ -+ if (((mrq->cmd && mrq->cmd->error) || -+ (mrq->data && (mrq->data->error || -+ (mrq->data->stop && mrq->data->stop->error))))) { -+ -+ bcm2835_sdhost_reset(host); -+ } -+ -+ host->mrq = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ -+ mmiowb(); -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+ mmc_request_done(host->mmc, mrq); -+} -+ -+ -+ -+int bcm2835_sdhost_add_host(struct bcm2835_host *host) -+{ -+ struct mmc_host *mmc; -+ struct dma_slave_config cfg; -+ int ret; -+ -+ mmc = host->mmc; -+ -+ bcm2835_sdhost_reset(host); -+ -+ mmc->f_max = host->max_clk; -+ mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; -+ -+ /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ -+ host->timeout_clk = mmc->f_max / 1000; -+#ifdef CONFIG_ARCH_BCM2835 -+ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; -+#endif -+ /* host controller capabilities */ -+ mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | -+ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | -+ MMC_CAP_NEEDS_POLL | -+ (ALLOW_CMD23 * MMC_CAP_CMD23); -+ -+ spin_lock_init(&host->lock); -+ -+ if (host->allow_dma) { -+ if (!host->dma_chan_tx || !host->dma_chan_rx || -+ IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { -+ pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); -+ host->have_dma = false; -+ } else { -+ pr_info("DMA channels allocated for the SDHost driver"); -+ host->have_dma = true; -+ -+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ cfg.slave_id = 13; /* DREQ channel */ -+ -+ cfg.direction = DMA_MEM_TO_DEV; -+ cfg.src_addr = 0; -+ cfg.dst_addr = host->phys_addr + SDDATA; -+ ret = dmaengine_slave_config(host->dma_chan_tx, &cfg); -+ -+ cfg.direction = DMA_DEV_TO_MEM; -+ cfg.src_addr = host->phys_addr + SDDATA; -+ cfg.dst_addr = 0; -+ ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); -+ } -+ } else { -+ pr_info("Forcing PIO mode\n"); -+ host->have_dma = false; -+ } -+ -+ mmc->max_segs = 128; -+ mmc->max_req_size = 524288; -+ mmc->max_seg_size = mmc->max_req_size; -+ mmc->max_blk_size = 512; -+ mmc->max_blk_count = 65535; -+ -+ /* report supported voltage ranges */ -+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; -+ -+ tasklet_init(&host->finish_tasklet, -+ bcm2835_sdhost_tasklet_finish, (unsigned long)host); -+ -+ setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); -+ -+ bcm2835_sdhost_init(host, 0); -+#ifndef CONFIG_ARCH_BCM2835 -+ ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, -+ mmc_hostname(mmc), host); -+#else -+ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, -+ IRQF_SHARED, mmc_hostname(mmc), host); -+#endif -+ if (ret) { -+ pr_err("%s: Failed to request IRQ %d: %d\n", -+ mmc_hostname(mmc), host->irq, ret); -+ goto untasklet; -+ } -+ -+ mmiowb(); -+ mmc_add_host(mmc); -+ -+ pr_info("Load BCM2835 SDHost driver\n"); -+ if (host->delay_after_stop) -+ pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", -+ host->delay_after_stop); -+ -+ return 0; -+ -+untasklet: -+ tasklet_kill(&host->finish_tasklet); -+ -+ return ret; -+} -+ -+static int bcm2835_sdhost_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *node = dev->of_node; -+ struct clk *clk; -+ struct resource *iomem; -+ struct bcm2835_host *host; -+ struct mmc_host *mmc; -+ int ret; -+ -+ pr_debug("bcm2835_sdhost_probe\n"); -+ mmc = mmc_alloc_host(sizeof(*host), dev); -+ if (!mmc) -+ return -ENOMEM; -+ -+ mmc->ops = &bcm2835_sdhost_ops; -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ host->timeout = msecs_to_jiffies(1000); -+ spin_lock_init(&host->lock); -+ -+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ host->ioaddr = devm_ioremap_resource(dev, iomem); -+ if (IS_ERR(host->ioaddr)) { -+ ret = PTR_ERR(host->ioaddr); -+ goto err; -+ } -+ -+ host->phys_addr = iomem->start + BCM2835_VCMMU_SHIFT; -+ pr_debug(" - ioaddr %lx, iomem->start %lx, phys_addr %lx\n", -+ (unsigned long)host->ioaddr, -+ (unsigned long)iomem->start, -+ (unsigned long)host->phys_addr); -+ -+ host->allow_dma = ALLOW_DMA; -+ -+ if (node) { -+ /* Read any custom properties */ -+ of_property_read_u32(node, -+ "brcm,delay-after-stop", -+ &host->delay_after_stop); -+ host->allow_dma = ALLOW_DMA && -+ !of_property_read_bool(node, "brcm,force-pio"); -+ } -+ -+ if (host->allow_dma) { -+ if (node) { -+ host->dma_chan_tx = -+ dma_request_slave_channel(dev, "tx"); -+ host->dma_chan_rx = -+ dma_request_slave_channel(dev, "rx"); -+ } else { -+ dma_cap_mask_t mask; -+ -+ dma_cap_zero(mask); -+ /* we don't care about the channel, any would work */ -+ dma_cap_set(DMA_SLAVE, mask); -+ host->dma_chan_tx = -+ dma_request_channel(mask, NULL, NULL); -+ host->dma_chan_rx = -+ dma_request_channel(mask, NULL, NULL); -+ } -+ } -+ -+ clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); -+ ret = PTR_ERR(clk); -+ goto err; -+ } -+ -+ host->max_clk = clk_get_rate(clk); -+ -+ host->irq = platform_get_irq(pdev, 0); -+ if (host->irq <= 0) { -+ dev_err(dev, "get IRQ failed\n"); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ pr_debug(" - max_clk %lx, irq %d\n", -+ (unsigned long)host->max_clk, -+ (int)host->irq); -+ -+ if (node) -+ mmc_of_parse(mmc); -+ else -+ mmc->caps |= MMC_CAP_4_BIT_DATA; -+ -+ ret = bcm2835_sdhost_add_host(host); -+ if (ret) -+ goto err; -+ -+ platform_set_drvdata(pdev, host); -+ -+ pr_debug("bcm2835_sdhost_probe -> OK\n"); -+ -+ return 0; -+ -+err: -+ pr_debug("bcm2835_sdhost_probe -> err %d\n", ret); -+ mmc_free_host(mmc); -+ -+ return ret; -+} -+ -+static int bcm2835_sdhost_remove(struct platform_device *pdev) -+{ -+ struct bcm2835_host *host = platform_get_drvdata(pdev); -+ -+ pr_debug("bcm2835_sdhost_remove\n"); -+ -+ mmc_remove_host(host->mmc); -+ -+ bcm2835_sdhost_set_power(host, false); -+ -+ free_irq(host->irq, host); -+ -+ del_timer_sync(&host->timer); -+ -+ tasklet_kill(&host->finish_tasklet); -+ -+ mmc_free_host(host->mmc); -+ platform_set_drvdata(pdev, NULL); -+ -+ pr_debug("bcm2835_sdhost_remove - OK\n"); -+ return 0; -+} -+ -+ -+static const struct of_device_id bcm2835_sdhost_match[] = { -+ { .compatible = "brcm,bcm2835-sdhost" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm2835_sdhost_match); -+ -+ -+ -+static struct platform_driver bcm2835_sdhost_driver = { -+ .probe = bcm2835_sdhost_probe, -+ .remove = bcm2835_sdhost_remove, -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = bcm2835_sdhost_match, -+ }, -+}; -+module_platform_driver(bcm2835_sdhost_driver); -+ -+MODULE_ALIAS("platform:sdhost-bcm2835"); -+MODULE_DESCRIPTION("BCM2835 SDHost driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Phil Elwell"); - -From 4504d17456cfc2f8b8b987d8709adcf759c8ea2d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:24:30 +0200 -Subject: [PATCH 122/216] BCM270x: Add memory and irq resources to dmaengine - device and DT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Prepare for merging of the legacy DMA API arch driver dma.c -with bcm2708-dmaengine by adding memory and irq resources both -to platform file device and Device Tree node. -Don't use BCM_DMAMAN_DRIVER_NAME so we don't have to include mach/dma.h - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 16 +++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 65 +++++++++++++++++++++++++++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 65 +++++++++++++++++++++++++++++++++-- - 3 files changed, 142 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index ff70c58..065a424 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -10,7 +10,23 @@ - - dma: dma@7e007000 { - compatible = "brcm,bcm2835-dma"; -+ reg = <0x7e007000 0xf00>; -+ interrupts = <1 16>, -+ <1 17>, -+ <1 18>, -+ <1 19>, -+ <1 20>, -+ <1 21>, -+ <1 22>, -+ <1 23>, -+ <1 24>, -+ <1 25>, -+ <1 26>, -+ <1 27>, -+ <1 28>; -+ - #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x7f35>; - }; - - intc: interrupt-controller { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index b848e4a..703215d 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -55,7 +55,6 @@ - #include - - #include --#include - #include - #include - -@@ -257,15 +256,77 @@ static struct resource bcm2708_dmaman_resources[] = { - }; - - static struct platform_device bcm2708_dmaman_device = { -- .name = BCM_DMAMAN_DRIVER_NAME, -+ .name = "bcm2708_dma", - .id = 0, /* first bcm2708_dma */ - .resource = bcm2708_dmaman_resources, - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), - }; - -+static struct resource bcm2708_dmaengine_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_DMA0, -+ .end = IRQ_DMA0, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA1, -+ .end = IRQ_DMA1, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA2, -+ .end = IRQ_DMA2, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA3, -+ .end = IRQ_DMA3, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA4, -+ .end = IRQ_DMA4, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA5, -+ .end = IRQ_DMA5, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA6, -+ .end = IRQ_DMA6, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA7, -+ .end = IRQ_DMA7, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA8, -+ .end = IRQ_DMA8, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA9, -+ .end = IRQ_DMA9, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA10, -+ .end = IRQ_DMA10, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA11, -+ .end = IRQ_DMA11, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA12, -+ .end = IRQ_DMA12, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ - static struct platform_device bcm2708_dmaengine_device = { - .name = "bcm2708-dmaengine", - .id = -1, -+ .resource = bcm2708_dmaengine_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), - }; - - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index dcad008..97116c3 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -56,7 +56,6 @@ - #include - - #include --#include - #include - #include - -@@ -267,15 +266,77 @@ static struct resource bcm2708_dmaman_resources[] = { - }; - - static struct platform_device bcm2708_dmaman_device = { -- .name = BCM_DMAMAN_DRIVER_NAME, -+ .name = "bcm2708_dma", - .id = 0, /* first bcm2708_dma */ - .resource = bcm2708_dmaman_resources, - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), - }; - -+static struct resource bcm2708_dmaengine_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_DMA0, -+ .end = IRQ_DMA0, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA1, -+ .end = IRQ_DMA1, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA2, -+ .end = IRQ_DMA2, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA3, -+ .end = IRQ_DMA3, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA4, -+ .end = IRQ_DMA4, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA5, -+ .end = IRQ_DMA5, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA6, -+ .end = IRQ_DMA6, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA7, -+ .end = IRQ_DMA7, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA8, -+ .end = IRQ_DMA8, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA9, -+ .end = IRQ_DMA9, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA10, -+ .end = IRQ_DMA10, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA11, -+ .end = IRQ_DMA11, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA12, -+ .end = IRQ_DMA12, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ - static struct platform_device bcm2708_dmaengine_device = { - .name = "bcm2708-dmaengine", - .id = -1, -+ .resource = bcm2708_dmaengine_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), - }; - - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - -From 4111e2c08fdfcfaa72b531689e2b9bc2b8c29453 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:25:43 +0200 -Subject: [PATCH 123/216] dmaengine: bcm2708: Merge with arch dma.c driver and - disable dma.c -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Merge the legacy DMA API driver with bcm2708-dmaengine. -This is done so we can use bcm2708_fb on ARCH_BCM2835 (mailbox -driver is also needed). - -Changes to the dma.c code: -- Use BIT() macro. -- Cutdown some comments to one line. -- Add mutex to vc_dmaman and use this, since the dev lock is locked - during probing of the engine part. -- Add global g_dmaman variable since drvdata is used by the engine part. -- Restructure for readability: - vc_dmaman_chan_alloc() - vc_dmaman_chan_free() - bcm_dma_chan_free() -- Restructure bcm_dma_chan_alloc() to simplify error handling. -- Use device irq resources instead of hardcoded bcm_dma_irqs table. -- Remove dev_dmaman_register() and code it directly. -- Remove dev_dmaman_deregister() and code it directly. -- Simplify bcm_dmaman_probe() using devm_* functions. -- Get dmachans from DT if available. -- Keep 'dma.dmachans' module argument name for backwards compatibility. - -Make it available on ARCH_BCM2835 as well. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/include/mach/dma.h | 96 +-------- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/include/mach/dma.h | 96 +-------- - drivers/dma/Kconfig | 9 +- - drivers/dma/bcm2708-dmaengine.c | 333 ++++++++++++++++++++++++++++-- - include/linux/platform_data/dma-bcm2708.h | 127 ++++++++++++ - 7 files changed, 457 insertions(+), 208 deletions(-) - create mode 100644 include/linux/platform_data/dma-bcm2708.h - -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 21e3521..454408c 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index d03e7b5..d826705 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -1,94 +1,2 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/dma.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- -- --#ifndef _MACH_BCM2708_DMA_H --#define _MACH_BCM2708_DMA_H -- --#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -- --/* DMA CS Control and Status bits */ --#define BCM2708_DMA_ACTIVE (1 << 0) --#define BCM2708_DMA_INT (1 << 2) --#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ --#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ --#define BCM2708_DMA_ERR (1 << 8) --#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ --#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -- --/* DMA control block "info" field bits */ --#define BCM2708_DMA_INT_EN (1 << 0) --#define BCM2708_DMA_TDMODE (1 << 1) --#define BCM2708_DMA_WAIT_RESP (1 << 3) --#define BCM2708_DMA_D_INC (1 << 4) --#define BCM2708_DMA_D_WIDTH (1 << 5) --#define BCM2708_DMA_D_DREQ (1 << 6) --#define BCM2708_DMA_S_INC (1 << 8) --#define BCM2708_DMA_S_WIDTH (1 << 9) --#define BCM2708_DMA_S_DREQ (1 << 10) -- --#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) --#define BCM2708_DMA_PER_MAP(x) ((x) << 16) --#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -- --#define BCM2708_DMA_DREQ_EMMC 11 --#define BCM2708_DMA_DREQ_SDHOST 13 -- --#define BCM2708_DMA_CS 0x00 /* Control and Status */ --#define BCM2708_DMA_ADDR 0x04 --/* the current control block appears in the following registers - read only */ --#define BCM2708_DMA_INFO 0x08 --#define BCM2708_DMA_SOURCE_AD 0x0c --#define BCM2708_DMA_DEST_AD 0x10 --#define BCM2708_DMA_NEXTCB 0x1C --#define BCM2708_DMA_DEBUG 0x20 -- --#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) --#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -- --#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -- --struct bcm2708_dma_cb { -- unsigned long info; -- unsigned long src; -- unsigned long dst; -- unsigned long length; -- unsigned long stride; -- unsigned long next; -- unsigned long pad[2]; --}; --struct scatterlist; -- --extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); --extern void bcm_dma_start(void __iomem *dma_chan_base, -- dma_addr_t control_block); --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); --extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -- --/* When listing features we can ask for when allocating DMA channels give -- those with higher priority smaller ordinal numbers */ --#define BCM_DMA_FEATURE_FAST_ORD 0 --#define BCM_DMA_FEATURE_BULK_ORD 1 --#define BCM_DMA_FEATURE_NORMAL_ORD 2 --#define BCM_DMA_FEATURE_LITE_ORD 3 --#define BCM_DMA_FEATURE_FAST (1< -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 2a803bb..f07c38b 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -index d03e7b5..d826705 100644 ---- a/arch/arm/mach-bcm2709/include/mach/dma.h -+++ b/arch/arm/mach-bcm2709/include/mach/dma.h -@@ -1,94 +1,2 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/dma.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- -- --#ifndef _MACH_BCM2708_DMA_H --#define _MACH_BCM2708_DMA_H -- --#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -- --/* DMA CS Control and Status bits */ --#define BCM2708_DMA_ACTIVE (1 << 0) --#define BCM2708_DMA_INT (1 << 2) --#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ --#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ --#define BCM2708_DMA_ERR (1 << 8) --#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ --#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -- --/* DMA control block "info" field bits */ --#define BCM2708_DMA_INT_EN (1 << 0) --#define BCM2708_DMA_TDMODE (1 << 1) --#define BCM2708_DMA_WAIT_RESP (1 << 3) --#define BCM2708_DMA_D_INC (1 << 4) --#define BCM2708_DMA_D_WIDTH (1 << 5) --#define BCM2708_DMA_D_DREQ (1 << 6) --#define BCM2708_DMA_S_INC (1 << 8) --#define BCM2708_DMA_S_WIDTH (1 << 9) --#define BCM2708_DMA_S_DREQ (1 << 10) -- --#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) --#define BCM2708_DMA_PER_MAP(x) ((x) << 16) --#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -- --#define BCM2708_DMA_DREQ_EMMC 11 --#define BCM2708_DMA_DREQ_SDHOST 13 -- --#define BCM2708_DMA_CS 0x00 /* Control and Status */ --#define BCM2708_DMA_ADDR 0x04 --/* the current control block appears in the following registers - read only */ --#define BCM2708_DMA_INFO 0x08 --#define BCM2708_DMA_SOURCE_AD 0x0c --#define BCM2708_DMA_DEST_AD 0x10 --#define BCM2708_DMA_NEXTCB 0x1C --#define BCM2708_DMA_DEBUG 0x20 -- --#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) --#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -- --#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -- --struct bcm2708_dma_cb { -- unsigned long info; -- unsigned long src; -- unsigned long dst; -- unsigned long length; -- unsigned long stride; -- unsigned long next; -- unsigned long pad[2]; --}; --struct scatterlist; -- --extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); --extern void bcm_dma_start(void __iomem *dma_chan_base, -- dma_addr_t control_block); --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); --extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -- --/* When listing features we can ask for when allocating DMA channels give -- those with higher priority smaller ordinal numbers */ --#define BCM_DMA_FEATURE_FAST_ORD 0 --#define BCM_DMA_FEATURE_BULK_ORD 1 --#define BCM_DMA_FEATURE_NORMAL_ORD 2 --#define BCM_DMA_FEATURE_LITE_ORD 3 --#define BCM_DMA_FEATURE_FAST (1< -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 2395f63..41097c7 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -339,10 +339,15 @@ config DMA_BCM2835 - - config DMA_BCM2708 - tristate "BCM2708 DMA engine support" -- depends on MACH_BCM2708 || MACH_BCM2709 -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -+config DMA_BCM2708_LEGACY -+ bool "BCM2708 DMA legacy API support" -+ depends on DMA_BCM2708 -+ default y -+ - config TI_CPPI41 - tristate "AM33xx CPPI41 DMA support" - depends on ARCH_OMAP -@@ -381,7 +386,7 @@ config MOXART_DMA - select DMA_VIRTUAL_CHANNELS - help - Enable support for the MOXA ART SoC DMA controller. -- -+ - config FSL_EDMA - tristate "Freescale eDMA engine support" - depends on OF -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 8182b16..937fd60 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -37,26 +37,304 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include -+#include - --#ifndef CONFIG_ARCH_BCM2835 -+#include "virt-dma.h" - --/* dma manager */ --#include -+static unsigned dma_debug; - --//#define DMA_COMPLETE DMA_SUCCESS -+/* -+ * Legacy DMA API -+ */ - --#endif -+#ifdef CONFIG_DMA_BCM2708_LEGACY - --#include --#include -+#define CACHE_LINE_MASK 31 -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ - --#include "virt-dma.h" -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n) << 8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base) + BCM2708_DMA_CHAN(n))) - --static unsigned dma_debug; -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+ struct mutex lock; -+}; -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+static struct vc_dmaman *g_dmaman; /* DMA manager */ -+static int dmachans = -1; /* module parameter */ -+ -+/* DMA Auxiliary Functions */ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+EXPORT_SYMBOL_GPL(bcm_dma_wait_idle); -+ -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ /* DMA Manager Device Methods */ -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* 8 to 14 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int chan = 0; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (!chans) -+ return -ENOENT; -+ -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ -+ return chan; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ -+ if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ -+ dmaman->chan_available |= (1 << chan); -+ -+ return 0; -+} -+ -+/* DMA Manager Monitor */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ struct vc_dmaman *dmaman = g_dmaman; -+ struct platform_device *pdev = to_platform_device(dmaman_dev); -+ struct resource *r; -+ int chan; -+ -+ if (!dmaman_dev) -+ return -ENODEV; -+ -+ mutex_lock(&dmaman->lock); -+ chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (chan < 0) -+ goto out; -+ -+ r = platform_get_resource(pdev, IORESOURCE_IRQ, (unsigned int)chan); -+ if (!r) { -+ dev_err(dmaman_dev, "failed to get irq for DMA channel %d\n", -+ chan); -+ vc_dmaman_chan_free(dmaman, chan); -+ chan = -ENOENT; -+ goto out; -+ } -+ -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, chan); -+ *out_dma_irq = r->start; -+ dev_dbg(dmaman_dev, -+ "Legacy API allocated channel=%d, base=%p, irq=%i\n", -+ chan, *out_dma_base, *out_dma_irq); -+ -+out: -+ mutex_unlock(&dmaman->lock); -+ -+ return chan; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ struct vc_dmaman *dmaman = g_dmaman; -+ int rc; -+ -+ if (!dmaman_dev) -+ return -ENODEV; -+ -+ mutex_lock(&dmaman->lock); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ mutex_unlock(&dmaman->lock); -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct vc_dmaman *dmaman; -+ struct resource *r; -+ void __iomem *dma_base; -+ uint32_t val; -+ -+ if (!of_property_read_u32(dev->of_node, -+ "brcm,dma-channel-mask", &val)) -+ dmachans = val; -+ else if (dmachans == -1) -+ dmachans = DEFAULT_DMACHAN_BITMAP; -+ -+ dmaman = devm_kzalloc(dev, sizeof(*dmaman), GFP_KERNEL); -+ if (!dmaman) -+ return -ENOMEM; -+ -+ mutex_init(&dmaman->lock); -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ dma_base = devm_ioremap_resource(dev, r); -+ if (IS_ERR(dma_base)) -+ return PTR_ERR(dma_base); -+ -+ vc_dmaman_init(dmaman, dma_base, dmachans); -+ g_dmaman = dmaman; -+ dmaman_dev = dev; -+ -+ dev_info(dev, "DMA legacy API manager at %p, dmachans=0x%x\n", -+ dma_base, dmachans); -+ -+ return 0; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ dmaman_dev = NULL; -+ -+ return 0; -+} -+ -+#else /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+#endif /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+/* -+ * DMA engine -+ */ - - struct bcm2835_dmadev { - struct dma_device ddev; -@@ -709,7 +987,7 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) - return 0; - } - --#ifdef CONFIG_ARCH_BCM2835 -+#ifndef CONFIG_DMA_BCM2708_LEGACY - static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - { - struct bcm2835_chan *c; -@@ -787,7 +1065,7 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, - static int bcm2835_dma_probe(struct platform_device *pdev) - { - struct bcm2835_dmadev *od; --#ifdef CONFIG_ARCH_BCM2835 -+#ifndef CONFIG_DMA_BCM2708_LEGACY - struct resource *res; - void __iomem *base; - uint32_t chans_available; -@@ -800,10 +1078,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; - -- /* If CONFIG_ARCH_BCM2835 is selected, device tree is used */ -- /* hence the difference between probing */ -- --#ifndef CONFIG_ARCH_BCM2835 -+#ifdef CONFIG_DMA_BCM2708_LEGACY - - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) -@@ -815,6 +1090,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (!od) - return -ENOMEM; - -+ rc = bcm_dmaman_probe(pdev); -+ if (rc) -+ return rc; -+ - pdev->dev.dma_parms = &od->dma_parms; - dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); - -@@ -971,6 +1250,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); -+ bcm_dmaman_remove(pdev); - - return 0; - } -@@ -985,9 +1265,30 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --module_platform_driver(bcm2835_dma_driver); -+static int bcm2835_init(void) -+{ -+ return platform_driver_register(&bcm2835_dma_driver); -+} -+ -+static void bcm2835_exit(void) -+{ -+ platform_driver_unregister(&bcm2835_dma_driver); -+} -+ -+/* -+ * Load after serial driver (arch_initcall) so we see the messages if it fails, -+ * but before drivers (module_init) that need a DMA channel. -+ */ -+subsys_initcall(bcm2835_init); -+module_exit(bcm2835_exit); - - module_param(dma_debug, uint, 0644); -+#ifdef CONFIG_DMA_BCM2708_LEGACY -+/* Keep backward compatibility: dma.dmachans= */ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX "dma." -+module_param(dmachans, int, 0644); -+#endif - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); -diff --git a/include/linux/platform_data/dma-bcm2708.h b/include/linux/platform_data/dma-bcm2708.h -new file mode 100644 -index 0000000..2310e34 ---- /dev/null -+++ b/include/linux/platform_data/dma-bcm2708.h -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _PLAT_BCM2708_DMA_H -+#define _PLAT_BCM2708_DMA_H -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE BIT(0) -+#define BCM2708_DMA_INT BIT(2) -+#define BCM2708_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR BIT(8) -+#define BCM2708_DMA_ABORT BIT(30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET BIT(31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN BIT(0) -+#define BCM2708_DMA_TDMODE BIT(1) -+#define BCM2708_DMA_WAIT_RESP BIT(3) -+#define BCM2708_DMA_D_INC BIT(4) -+#define BCM2708_DMA_D_WIDTH BIT(5) -+#define BCM2708_DMA_D_DREQ BIT(6) -+#define BCM2708_DMA_S_INC BIT(8) -+#define BCM2708_DMA_S_WIDTH BIT(9) -+#define BCM2708_DMA_S_DREQ BIT(10) -+ -+#define BCM2708_DMA_BURST(x) (((x) & 0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x) & 0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4) + BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4) + BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 -+#define BCM_DMA_FEATURE_FAST BIT(BCM_DMA_FEATURE_FAST_ORD) -+#define BCM_DMA_FEATURE_BULK BIT(BCM_DMA_FEATURE_BULK_ORD) -+#define BCM_DMA_FEATURE_NORMAL BIT(BCM_DMA_FEATURE_NORMAL_ORD) -+#define BCM_DMA_FEATURE_LITE BIT(BCM_DMA_FEATURE_LITE_ORD) -+#define BCM_DMA_FEATURE_COUNT 4 -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+ -+struct scatterlist; -+ -+#ifdef CONFIG_DMA_BCM2708_LEGACY -+ -+int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+void bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block); -+void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+bool bcm_dma_is_busy(void __iomem *dma_chan_base); -+int bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* return channel no or -ve error */ -+int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq); -+int bcm_dma_chan_free(int channel); -+ -+#else /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+static inline int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, -+ int sg_len) -+{ -+ return 0; -+} -+ -+static inline void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block) { } -+ -+static inline void bcm_dma_wait_idle(void __iomem *dma_chan_base) { } -+ -+static inline bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ return false; -+} -+ -+static inline int bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ return -EINVAL; -+} -+ -+static inline int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, -+ int *out_dma_irq) -+{ -+ return -EINVAL; -+} -+ -+static inline int bcm_dma_chan_free(int channel) -+{ -+ return -EINVAL; -+} -+ -+#endif /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+#endif /* _PLAT_BCM2708_DMA_H */ - -From 2b9f3386a080d00da4e6335272fe3b94cc51cfef Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:26:59 +0200 -Subject: [PATCH 124/216] BCM270x: dma: Remove driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove dma.c driver which is now merged with bcm2708-dmaengine. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/dma.c | 409 -------------------------------------------- - arch/arm/mach-bcm2709/dma.c | 409 -------------------------------------------- - 2 files changed, 818 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/dma.c - delete mode 100644 arch/arm/mach-bcm2709/dma.c - -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -deleted file mode 100644 -index a5e58d1..0000000 ---- a/arch/arm/mach-bcm2708/dma.c -+++ /dev/null -@@ -1,409 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/dma.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include -- --#include --#include -- --/*****************************************************************************\ -- * * -- * Configuration * -- * * --\*****************************************************************************/ -- --#define CACHE_LINE_MASK 31 --#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME --#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -- --/* valid only for channels 0 - 14, 15 has its own base address */ --#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ --#define BCM2708_DMA_CHANIO(dma_base, n) \ -- ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -- -- --/*****************************************************************************\ -- * * -- * DMA Auxilliary Functions * -- * * --\*****************************************************************************/ -- --/* A DMA buffer on an arbitrary boundary may separate a cache line into a -- section inside the DMA buffer and another section outside it. -- Even if we flush DMA buffers from the cache there is always the chance that -- during a DMA someone will access the part of a cache line that is outside -- the DMA buffer - which will then bring in unwelcome data. -- Without being able to dictate our own buffer pools we must insist that -- DMA buffers consist of a whole number of cache lines. --*/ -- --extern int --bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) --{ -- int i; -- -- for (i = 0; i < sg_len; i++) { -- if (sg_ptr[i].offset & CACHE_LINE_MASK || -- sg_ptr[i].length & CACHE_LINE_MASK) -- return 0; -- } -- -- return 1; --} --EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -- --extern void --bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) --{ -- dsb(); /* ARM data synchronization (push) operation */ -- -- writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -- writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); --} -- --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) --{ -- dsb(); -- -- /* ugly busy wait only option for now */ -- while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -- cpu_relax(); --} -- --EXPORT_SYMBOL_GPL(bcm_dma_start); -- --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) --{ -- dsb(); -- -- return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; --} --EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -- --/* Complete an ongoing DMA (assuming its results are to be ignored) -- Does nothing if there is no DMA in progress. -- This routine waits for the current AXI transfer to complete before -- terminating the current DMA. If the current transfer is hung on a DREQ used -- by an uncooperative peripheral the AXI transfer may never complete. In this -- case the routine times out and return a non-zero error code. -- Use of this routine doesn't guarantee that the ongoing or aborted DMA -- does not produce an interrupt. --*/ --extern int --bcm_dma_abort(void __iomem *dma_chan_base) --{ -- unsigned long int cs; -- int rc = 0; -- -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (BCM2708_DMA_ACTIVE & cs) { -- long int timeout = 10000; -- -- /* write 0 to the active bit - pause the DMA */ -- writel(0, dma_chan_base + BCM2708_DMA_CS); -- -- /* wait for any current AXI transfer to complete */ -- while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -- /* we'll un-pause when we set of our next DMA */ -- rc = -ETIMEDOUT; -- -- } else if (BCM2708_DMA_ACTIVE & cs) { -- /* terminate the control block chain */ -- writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -- -- /* abort the whole DMA */ -- writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -- dma_chan_base + BCM2708_DMA_CS); -- } -- } -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_dma_abort); -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Device Methods * -- * * --\*****************************************************************************/ -- --struct vc_dmaman { -- void __iomem *dma_base; -- u32 chan_available; /* bitmap of available channels */ -- u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ --}; -- --static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -- u32 chans_available) --{ -- dmaman->dma_base = dma_base; -- dmaman->chan_available = chans_available; -- dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -- dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -- dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -- dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ --} -- --static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -- unsigned preferred_feature_set) --{ -- u32 chans; -- int feature; -- -- chans = dmaman->chan_available; -- for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -- /* select the subset of available channels with the desired -- feature so long as some of the candidate channels have that -- feature */ -- if ((preferred_feature_set & (1 << feature)) && -- (chans & dmaman->has_feature[feature])) -- chans &= dmaman->has_feature[feature]; -- -- if (chans) { -- int chan = 0; -- /* return the ordinal of the first channel in the bitmap */ -- while (chans != 0 && (chans & 1) == 0) { -- chans >>= 1; -- chan++; -- } -- /* claim the channel */ -- dmaman->chan_available &= ~(1 << chan); -- return chan; -- } else -- return -ENOMEM; --} -- --static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) --{ -- if (chan < 0) -- return -EINVAL; -- else if ((1 << chan) & dmaman->chan_available) -- return -EIDRM; -- else { -- dmaman->chan_available |= (1 << chan); -- return 0; -- } --} -- --/*****************************************************************************\ -- * * -- * DMA IRQs * -- * * --\*****************************************************************************/ -- --static unsigned char bcm_dma_irqs[] = { -- IRQ_DMA0, -- IRQ_DMA1, -- IRQ_DMA2, -- IRQ_DMA3, -- IRQ_DMA4, -- IRQ_DMA5, -- IRQ_DMA6, -- IRQ_DMA7, -- IRQ_DMA8, -- IRQ_DMA9, -- IRQ_DMA10, -- IRQ_DMA11, -- IRQ_DMA12 --}; -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Monitor * -- * * --\*****************************************************************************/ -- --static struct device *dmaman_dev; /* we assume there's only one! */ -- --extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -- void __iomem **out_dma_base, int *out_dma_irq) --{ -- if (!dmaman_dev) -- return -ENODEV; -- else { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -- if (rc >= 0) { -- *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -- rc); -- *out_dma_irq = bcm_dma_irqs[rc]; -- } -- device_unlock(dmaman_dev); -- -- return rc; -- } --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -- --extern int bcm_dma_chan_free(int channel) --{ -- if (dmaman_dev) { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_free(dmaman, channel); -- device_unlock(dmaman_dev); -- -- return rc; -- } else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -- --static int dev_dmaman_register(const char *dev_name, struct device *dev) --{ -- int rc = dmaman_dev ? -EINVAL : 0; -- dmaman_dev = dev; -- return rc; --} -- --static void dev_dmaman_deregister(const char *dev_name, struct device *dev) --{ -- dmaman_dev = NULL; --} -- --/*****************************************************************************\ -- * * -- * DMA Device * -- * * --\*****************************************************************************/ -- --static int dmachans = -1; /* module parameter */ -- --static int bcm_dmaman_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_dmaman *dmaman; -- struct resource *dma_res = NULL; -- void __iomem *dma_base = NULL; -- int have_dma_region = 0; -- -- dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -- if (NULL == dmaman) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "DMA management memory\n"); -- ret = -ENOMEM; -- } else { -- -- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (dma_res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- } else if (!request_mem_region(dma_res->start, -- resource_size(dma_res), -- DRIVER_NAME)) { -- dev_err(&pdev->dev, "cannot obtain DMA region\n"); -- ret = -EBUSY; -- } else { -- have_dma_region = 1; -- dma_base = ioremap(dma_res->start, -- resource_size(dma_res)); -- if (!dma_base) { -- dev_err(&pdev->dev, "cannot map DMA region\n"); -- ret = -ENOMEM; -- } else { -- /* use module parameter if one was provided */ -- if (dmachans > 0) -- vc_dmaman_init(dmaman, dma_base, -- dmachans); -- else -- vc_dmaman_init(dmaman, dma_base, -- DEFAULT_DMACHAN_BITMAP); -- -- platform_set_drvdata(pdev, dmaman); -- dev_dmaman_register(DRIVER_NAME, &pdev->dev); -- -- printk(KERN_INFO DRIVER_NAME ": DMA manager " -- "at %p\n", dma_base); -- } -- } -- } -- if (ret != 0) { -- if (dma_base) -- iounmap(dma_base); -- if (dma_res && have_dma_region) -- release_mem_region(dma_res->start, -- resource_size(dma_res)); -- if (dmaman) -- kfree(dmaman); -- } -- return ret; --} -- --static int bcm_dmaman_remove(struct platform_device *pdev) --{ -- struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -- kfree(dmaman); -- -- return 0; --} -- --static struct platform_driver bcm_dmaman_driver = { -- .probe = bcm_dmaman_probe, -- .remove = bcm_dmaman_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --/*****************************************************************************\ -- * * -- * Driver init/exit * -- * * --\*****************************************************************************/ -- --static int __init bcm_dmaman_drv_init(void) --{ -- int ret; -- -- ret = platform_driver_register(&bcm_dmaman_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_dmaman_drv_exit(void) --{ -- platform_driver_unregister(&bcm_dmaman_driver); --} -- --module_init(bcm_dmaman_drv_init); --module_exit(bcm_dmaman_drv_exit); -- --module_param(dmachans, int, 0644); -- --MODULE_AUTHOR("Gray Girling "); --MODULE_DESCRIPTION("DMA channel manager driver"); --MODULE_LICENSE("GPL"); -- --MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); -diff --git a/arch/arm/mach-bcm2709/dma.c b/arch/arm/mach-bcm2709/dma.c -deleted file mode 100644 -index a5e58d1..0000000 ---- a/arch/arm/mach-bcm2709/dma.c -+++ /dev/null -@@ -1,409 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/dma.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include -- --#include --#include -- --/*****************************************************************************\ -- * * -- * Configuration * -- * * --\*****************************************************************************/ -- --#define CACHE_LINE_MASK 31 --#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME --#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -- --/* valid only for channels 0 - 14, 15 has its own base address */ --#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ --#define BCM2708_DMA_CHANIO(dma_base, n) \ -- ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -- -- --/*****************************************************************************\ -- * * -- * DMA Auxilliary Functions * -- * * --\*****************************************************************************/ -- --/* A DMA buffer on an arbitrary boundary may separate a cache line into a -- section inside the DMA buffer and another section outside it. -- Even if we flush DMA buffers from the cache there is always the chance that -- during a DMA someone will access the part of a cache line that is outside -- the DMA buffer - which will then bring in unwelcome data. -- Without being able to dictate our own buffer pools we must insist that -- DMA buffers consist of a whole number of cache lines. --*/ -- --extern int --bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) --{ -- int i; -- -- for (i = 0; i < sg_len; i++) { -- if (sg_ptr[i].offset & CACHE_LINE_MASK || -- sg_ptr[i].length & CACHE_LINE_MASK) -- return 0; -- } -- -- return 1; --} --EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -- --extern void --bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) --{ -- dsb(); /* ARM data synchronization (push) operation */ -- -- writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -- writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); --} -- --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) --{ -- dsb(); -- -- /* ugly busy wait only option for now */ -- while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -- cpu_relax(); --} -- --EXPORT_SYMBOL_GPL(bcm_dma_start); -- --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) --{ -- dsb(); -- -- return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; --} --EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -- --/* Complete an ongoing DMA (assuming its results are to be ignored) -- Does nothing if there is no DMA in progress. -- This routine waits for the current AXI transfer to complete before -- terminating the current DMA. If the current transfer is hung on a DREQ used -- by an uncooperative peripheral the AXI transfer may never complete. In this -- case the routine times out and return a non-zero error code. -- Use of this routine doesn't guarantee that the ongoing or aborted DMA -- does not produce an interrupt. --*/ --extern int --bcm_dma_abort(void __iomem *dma_chan_base) --{ -- unsigned long int cs; -- int rc = 0; -- -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (BCM2708_DMA_ACTIVE & cs) { -- long int timeout = 10000; -- -- /* write 0 to the active bit - pause the DMA */ -- writel(0, dma_chan_base + BCM2708_DMA_CS); -- -- /* wait for any current AXI transfer to complete */ -- while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -- /* we'll un-pause when we set of our next DMA */ -- rc = -ETIMEDOUT; -- -- } else if (BCM2708_DMA_ACTIVE & cs) { -- /* terminate the control block chain */ -- writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -- -- /* abort the whole DMA */ -- writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -- dma_chan_base + BCM2708_DMA_CS); -- } -- } -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_dma_abort); -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Device Methods * -- * * --\*****************************************************************************/ -- --struct vc_dmaman { -- void __iomem *dma_base; -- u32 chan_available; /* bitmap of available channels */ -- u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ --}; -- --static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -- u32 chans_available) --{ -- dmaman->dma_base = dma_base; -- dmaman->chan_available = chans_available; -- dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -- dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -- dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -- dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ --} -- --static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -- unsigned preferred_feature_set) --{ -- u32 chans; -- int feature; -- -- chans = dmaman->chan_available; -- for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -- /* select the subset of available channels with the desired -- feature so long as some of the candidate channels have that -- feature */ -- if ((preferred_feature_set & (1 << feature)) && -- (chans & dmaman->has_feature[feature])) -- chans &= dmaman->has_feature[feature]; -- -- if (chans) { -- int chan = 0; -- /* return the ordinal of the first channel in the bitmap */ -- while (chans != 0 && (chans & 1) == 0) { -- chans >>= 1; -- chan++; -- } -- /* claim the channel */ -- dmaman->chan_available &= ~(1 << chan); -- return chan; -- } else -- return -ENOMEM; --} -- --static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) --{ -- if (chan < 0) -- return -EINVAL; -- else if ((1 << chan) & dmaman->chan_available) -- return -EIDRM; -- else { -- dmaman->chan_available |= (1 << chan); -- return 0; -- } --} -- --/*****************************************************************************\ -- * * -- * DMA IRQs * -- * * --\*****************************************************************************/ -- --static unsigned char bcm_dma_irqs[] = { -- IRQ_DMA0, -- IRQ_DMA1, -- IRQ_DMA2, -- IRQ_DMA3, -- IRQ_DMA4, -- IRQ_DMA5, -- IRQ_DMA6, -- IRQ_DMA7, -- IRQ_DMA8, -- IRQ_DMA9, -- IRQ_DMA10, -- IRQ_DMA11, -- IRQ_DMA12 --}; -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Monitor * -- * * --\*****************************************************************************/ -- --static struct device *dmaman_dev; /* we assume there's only one! */ -- --extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -- void __iomem **out_dma_base, int *out_dma_irq) --{ -- if (!dmaman_dev) -- return -ENODEV; -- else { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -- if (rc >= 0) { -- *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -- rc); -- *out_dma_irq = bcm_dma_irqs[rc]; -- } -- device_unlock(dmaman_dev); -- -- return rc; -- } --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -- --extern int bcm_dma_chan_free(int channel) --{ -- if (dmaman_dev) { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_free(dmaman, channel); -- device_unlock(dmaman_dev); -- -- return rc; -- } else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -- --static int dev_dmaman_register(const char *dev_name, struct device *dev) --{ -- int rc = dmaman_dev ? -EINVAL : 0; -- dmaman_dev = dev; -- return rc; --} -- --static void dev_dmaman_deregister(const char *dev_name, struct device *dev) --{ -- dmaman_dev = NULL; --} -- --/*****************************************************************************\ -- * * -- * DMA Device * -- * * --\*****************************************************************************/ -- --static int dmachans = -1; /* module parameter */ -- --static int bcm_dmaman_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_dmaman *dmaman; -- struct resource *dma_res = NULL; -- void __iomem *dma_base = NULL; -- int have_dma_region = 0; -- -- dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -- if (NULL == dmaman) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "DMA management memory\n"); -- ret = -ENOMEM; -- } else { -- -- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (dma_res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- } else if (!request_mem_region(dma_res->start, -- resource_size(dma_res), -- DRIVER_NAME)) { -- dev_err(&pdev->dev, "cannot obtain DMA region\n"); -- ret = -EBUSY; -- } else { -- have_dma_region = 1; -- dma_base = ioremap(dma_res->start, -- resource_size(dma_res)); -- if (!dma_base) { -- dev_err(&pdev->dev, "cannot map DMA region\n"); -- ret = -ENOMEM; -- } else { -- /* use module parameter if one was provided */ -- if (dmachans > 0) -- vc_dmaman_init(dmaman, dma_base, -- dmachans); -- else -- vc_dmaman_init(dmaman, dma_base, -- DEFAULT_DMACHAN_BITMAP); -- -- platform_set_drvdata(pdev, dmaman); -- dev_dmaman_register(DRIVER_NAME, &pdev->dev); -- -- printk(KERN_INFO DRIVER_NAME ": DMA manager " -- "at %p\n", dma_base); -- } -- } -- } -- if (ret != 0) { -- if (dma_base) -- iounmap(dma_base); -- if (dma_res && have_dma_region) -- release_mem_region(dma_res->start, -- resource_size(dma_res)); -- if (dmaman) -- kfree(dmaman); -- } -- return ret; --} -- --static int bcm_dmaman_remove(struct platform_device *pdev) --{ -- struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -- kfree(dmaman); -- -- return 0; --} -- --static struct platform_driver bcm_dmaman_driver = { -- .probe = bcm_dmaman_probe, -- .remove = bcm_dmaman_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --/*****************************************************************************\ -- * * -- * Driver init/exit * -- * * --\*****************************************************************************/ -- --static int __init bcm_dmaman_drv_init(void) --{ -- int ret; -- -- ret = platform_driver_register(&bcm_dmaman_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_dmaman_drv_exit(void) --{ -- platform_driver_unregister(&bcm_dmaman_driver); --} -- --module_init(bcm_dmaman_drv_init); --module_exit(bcm_dmaman_drv_exit); -- --module_param(dmachans, int, 0644); -- --MODULE_AUTHOR("Gray Girling "); --MODULE_DESCRIPTION("DMA channel manager driver"); --MODULE_LICENSE("GPL"); -- --MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); - -From d2647dd924553835bc9b8f6ec0dce6cc25662d32 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:54:17 +0200 -Subject: [PATCH 125/216] BCM270x: Remove dmaman device -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove the dmaman device since the dmaengine now handles -the legacy API manager. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 16 ---------------- - arch/arm/mach-bcm2709/bcm2709.c | 16 ---------------- - 2 files changed, 32 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 703215d..486e090 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -247,21 +247,6 @@ static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - }; - --static struct resource bcm2708_dmaman_resources[] = { -- { -- .start = DMA_BASE, -- .end = DMA_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- } --}; -- --static struct platform_device bcm2708_dmaman_device = { -- .name = "bcm2708_dma", -- .id = 0, /* first bcm2708_dma */ -- .resource = bcm2708_dmaman_resources, -- .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), --}; -- - static struct resource bcm2708_dmaengine_resources[] = { - { - .start = DMA_BASE, -@@ -919,7 +904,6 @@ void __init bcm2708_init(void) - bcm2708_init_clocks(); - bcm2708_dt_init(); - -- bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 97116c3..44bfc50 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -257,21 +257,6 @@ static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - }; - --static struct resource bcm2708_dmaman_resources[] = { -- { -- .start = DMA_BASE, -- .end = DMA_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- } --}; -- --static struct platform_device bcm2708_dmaman_device = { -- .name = "bcm2708_dma", -- .id = 0, /* first bcm2708_dma */ -- .resource = bcm2708_dmaman_resources, -- .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), --}; -- - static struct resource bcm2708_dmaengine_resources[] = { - { - .start = DMA_BASE, -@@ -940,7 +925,6 @@ void __init bcm2709_init(void) - bcm2709_init_clocks(); - bcm2709_dt_init(); - -- bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - -From 149df0acaf7510d53047e19054e3b13607f60afd Mon Sep 17 00:00:00 2001 +From d8492b31751e7eda1b9b2c92dd381b5d7df1679d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 29 Apr 2015 17:24:02 +0200 -Subject: [PATCH 126/216] bcm2835: bcm2835_defconfig +Subject: [PATCH 68/77] bcm2835: bcm2835_defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -136420,4129 +130931,1330 @@ some have changed. Update to keep functionality. No longer available: SCSI_MULTI_LUN and RESOURCE_COUNTERS. +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig enable MMC_BCM2835 + +Enable the downstream bcm2835-mmc driver and DMA support. + +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig enable BCM2708_MBOX + +Enable the mailbox driver. + +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig use FB_BCM2708 + +Enable the bcm2708 framebuffer driver. +Disable the simple framebuffer driver, which matches the +device handed over by u-boot. + +Signed-off-by: Noralf Trønnes + +bcm2835: Merge bcm2835_defconfig with bcmrpi_defconfig + +These commands where used to make this commit: + +./scripts/diffconfig -m arch/arm/configs/bcm2835_defconfig arch/arm/configs/bcmrpi_defconfig > merge.cfg + +cat << EOF > filter +CONFIG_ARCH_BCM2708 +CONFIG_BCM2708_DT +CONFIG_ARM_PATCH_PHYS_VIRT +CONFIG_PHYS_OFFSET +CONFIG_CMDLINE +CONFIG_BCM2708_WDT +CONFIG_HW_RANDOM_BCM2708 +CONFIG_I2C_BCM2708 +CONFIG_SPI_BCM2708 +CONFIG_SND_BCM2708_SOC_I2S +CONFIG_USB_DWCOTG +CONFIG_LIRC_RPI +EOF + +grep -F -v -f filter merge.cfg > filtered.cfg + +cat << EOF > added.cfg +CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y +CONFIG_MISC_FILESYSTEMS=y +CONFIG_SND_BCM2835_SOC_I2S=m +EOF + +ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2835_defconfig filtered.cfg added.cfg +ARCH=arm make oldconfig + +ARCH=arm make savedefconfig +cp defconfig arch/arm/configs/bcm2835_defconfig + +rm merge.cfg filter filtered.cfg added.cfg defconfig + +ARCH=arm make bcm2835_defconfig +ARCH=arm make oldconfig + Signed-off-by: Noralf Trønnes --- - arch/arm/configs/bcm2835_defconfig | 14 +++++--------- - 1 file changed, 5 insertions(+), 9 deletions(-) + arch/arm/configs/bcm2835_defconfig | 1132 +++++++++++++++++++++++++++++++++++- + 1 file changed, 1107 insertions(+), 25 deletions(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 31cb073..245aede 100644 +index 31cb073..2e8a95a 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig -@@ -10,7 +10,6 @@ CONFIG_CGROUP_FREEZER=y +@@ -1,105 +1,1071 @@ + # CONFIG_LOCALVERSION_AUTO is not set + CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y + CONFIG_FHANDLE=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y + CONFIG_BSD_PROCESS_ACCT=y + CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y + CONFIG_LOG_BUF_SHIFT=18 + CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y ++CONFIG_MEMCG=y CONFIG_CGROUP_PERF=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y -@@ -18,10 +17,6 @@ CONFIG_NAMESPACES=y ++CONFIG_BLK_CGROUP=y + CONFIG_NAMESPACES=y CONFIG_SCHED_AUTOGROUP=y - CONFIG_RELAY=y +-CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y - CONFIG_KALLSYMS_ALL=y +-CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -@@ -29,6 +24,7 @@ CONFIG_EMBEDDED=y + # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y - CONFIG_OPROFILE=y +-CONFIG_OPROFILE=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_ARCH_MULTI_V6=y # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_BCM=y -@@ -38,7 +34,6 @@ CONFIG_AEABI=y + CONFIG_ARCH_BCM2835=y +-CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_PREEMPT=y + CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y CONFIG_KSM=y CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y -CONFIG_CC_STACKPROTECTOR=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=m ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_VFP=y -@@ -57,7 +52,6 @@ CONFIG_DEVTMPFS_MOUNT=y + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_MISC=m + # CONFIG_SUSPEND is not set + CONFIG_NET=y + CONFIG_PACKET=y + CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m + CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_LRO=m ++CONFIG_INET_DIAG=m ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y + CONFIG_NETWORK_SECMARK=y + CONFIG_NETFILTER=y +-CONFIG_CFG80211=y +-CONFIG_MAC80211=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_NFC_PN533=m + CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m CONFIG_NETDEVICES=y -@@ -83,11 +77,15 @@ CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m + CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m + CONFIG_USB_NET_SMSC95XX=y +-CONFIG_ZD1211RW=y +-CONFIG_INPUT_EVDEV=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_AT76C50X_USB=m ++CONFIG_USB_ZD1201=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_RTL8187=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_ATH_CARDS=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8192CU=m ++CONFIG_ZD1211RW=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m ++CONFIG_RAW_DRIVER=y ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VC_SM=y + CONFIG_I2C=y +-CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_CHARDEV=m + CONFIG_I2C_BCM2835=y + CONFIG_SPI=y +-CONFIG_SPI_BCM2835=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m + CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_BATTERY_DS2760=m + # CONFIG_HWMON is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m + CONFIG_FB=y +-CONFIG_FB_SIMPLE=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_GPIO=m + CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_PRINTER=m CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m +CONFIG_USB_DWC2=y ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_LED=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_BCM2835=y -+CONFIG_NEW_LEDS=y ++CONFIG_MMC_SPI=m +CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -@@ -97,8 +95,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y - CONFIG_LEDS_TRIGGER_TRANSIENT=y - CONFIG_LEDS_TRIGGER_CAMERA=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y + CONFIG_LEDS_TRIGGER_CPU=y + CONFIG_LEDS_TRIGGER_GPIO=y + CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +-CONFIG_LEDS_TRIGGER_TRANSIENT=y +-CONFIG_LEDS_TRIGGER_CAMERA=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_ISL12057=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_DS3234=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m CONFIG_STAGING=y -CONFIG_USB_DWC2=y -CONFIG_USB_DWC2_HOST=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_R8723AU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y # CONFIG_IOMMU_SUPPORT is not set ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y - -From 40cd8a80edbedd6bef0da2bcd55e777f80ef30ae Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:24:46 +0200 -Subject: [PATCH 127/216] mmc: bcm2835-mmc: Make available on ARCH_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the bcm2835-mmc driver available for use on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/mmc/host/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 1666c6c..41d6e47 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" - - config MMC_BCM2835 - tristate "MMC support on BCM2835" -- depends on (MACH_BCM2708 || MACH_BCM2709) -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - help - This selects the MMC Interface on BCM2835. - - -From 6c0c225509561cc261c594db00d429f2c032ebfa Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:28:22 +0200 -Subject: [PATCH 128/216] bcm2835: bcm2835_defconfig enable MMC_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the downstream bcm2835-mmc driver and DMA support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 245aede..cf2e7a6 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -79,6 +79,8 @@ CONFIG_USB=y - CONFIG_USB_STORAGE=y - CONFIG_USB_DWC2=y - CONFIG_MMC=y -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2835=y -@@ -94,6 +96,8 @@ CONFIG_LEDS_TRIGGER_GPIO=y - CONFIG_LEDS_TRIGGER_DEFAULT_ON=y - CONFIG_LEDS_TRIGGER_TRANSIENT=y - CONFIG_LEDS_TRIGGER_CAMERA=y -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2708=y - CONFIG_STAGING=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT2_FS=y - -From 8bff84b0504771b895a12dcc5975b26345a3f9a1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:29:04 +0200 -Subject: [PATCH 129/216] bcm2835: Change to use bcm2835-mmc in Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use downstream bcm2835-mmc driver to get increased throughput -and DMA support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 +- - arch/arm/boot/dts/bcm2835.dtsi | 9 ++++++--- - 2 files changed, 7 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index c706448..9f4ed2f 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -45,7 +45,7 @@ - clock-frequency = <100000>; - }; - --&sdhci { -+&mmc { - status = "okay"; - bus-width = <4>; - }; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 3342cb1..f2dec21 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -122,11 +122,14 @@ - status = "disabled"; - }; - -- sdhci: sdhci@7e300000 { -- compatible = "brcm,bcm2835-sdhci"; -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; - reg = <0x7e300000 0x100>; - interrupts = <2 30>; - clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - -@@ -161,7 +164,7 @@ - reg = <0>; - #clock-cells = <0>; - clock-output-names = "mmc"; -- clock-frequency = <100000000>; -+ clock-frequency = <250000000>; - }; - - clk_i2c: clock@1 { - -From 89df9a42f6e60b3c54c4b49b1fafff7ef201ac72 Mon Sep 17 00:00:00 2001 -From: Christopher Freeman -Date: Wed, 4 Mar 2015 01:16:58 -0800 -Subject: [PATCH 130/216] dmaengine: increment privatecnt when using - dma_get_any_slave_channel - -Channels allocated via dma_get_any_slave_channel were not increasing -the counter tracking private allocations. When these channels were -released, privatecnt may erroneously fall to zero. The DMA device -would then lose its DMA_PRIVATE cap and fail to allocate future private -channels (via private_candidate) as any allocations still outstanding -would incorrectly be seen as public allocations. - -Signed-off-by: Christopher Freeman -Signed-off-by: Vinod Koul ---- - drivers/dma/dmaengine.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c -index ac336a9..bb2b914 100644 ---- a/drivers/dma/dmaengine.c -+++ b/drivers/dma/dmaengine.c -@@ -589,11 +589,15 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) - - chan = private_candidate(&mask, device, NULL, NULL); - if (chan) { -+ dma_cap_set(DMA_PRIVATE, device->cap_mask); -+ device->privatecnt++; - err = dma_chan_get(chan); - if (err) { - pr_debug("%s: failed to get %s: (%d)\n", - __func__, dma_chan_name(chan), err); - chan = NULL; -+ if (--device->privatecnt == 0) -+ dma_cap_clear(DMA_PRIVATE, device->cap_mask); - } - } - - -From 0ecdaeb739edb714add6d8ae452d12d2ce821573 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 1 May 2015 17:46:56 +0100 -Subject: [PATCH 131/216] bcm2835-mmc: Add locks when accessing sdhost - registers - ---- - drivers/mmc/host/bcm2835-mmc.c | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index eef0d351..1c34f476 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -133,17 +133,20 @@ struct bcm2835_host { - - static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) - { -+ lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); - } - - static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg) - { -+ lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - } - - static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) - { -+ lockdep_assert_held_once(&host->lock); - return readl(host->ioaddr + reg); - } - -@@ -255,7 +258,9 @@ static void bcm2835_mmc_dumpregs(struct bcm2835_host *host) - static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) - { - unsigned long timeout; -+ unsigned long flags; - -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET); - - if (mask & SDHCI_RESET_ALL) -@@ -273,19 +278,23 @@ static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) - return; - } - timeout--; -+ spin_unlock_irqrestore(&host->lock, flags); - mdelay(1); -+ spin_lock_irqsave(&host->lock, flags); - } - - if (100-timeout > 10 && 100-timeout > host->max_delay) { - host->max_delay = 100-timeout; - pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay); - } -+ spin_unlock_irqrestore(&host->lock, flags); - } - - static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); - - static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - { -+ unsigned long flags; - if (soft) - bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); - else -@@ -297,8 +306,10 @@ static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | - SDHCI_INT_RESPONSE; - -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); - bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ spin_unlock_irqrestore(&host->lock, flags); - - if (soft) { - /* force clock reconfiguration */ -@@ -497,11 +508,14 @@ static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host) - dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); - } - if (desc) { -+ unsigned long flags; -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | - SDHCI_INT_SPACE_AVAIL); - host->tx_desc = desc; - desc->callback = bcm2835_mmc_dma_complete; - desc->callback_param = host; -+ spin_unlock_irqrestore(&host->lock, flags); - dmaengine_submit(desc); - dma_async_issue_pending(dma_chan); - } -@@ -1243,8 +1257,10 @@ static void bcm2835_mmc_tasklet_finish(unsigned long param) - (mrq->data && (mrq->data->error || - (mrq->data->stop && mrq->data->stop->error))))) { - -+ spin_unlock_irqrestore(&host->lock, flags); - bcm2835_mmc_reset(host, SDHCI_RESET_CMD); - bcm2835_mmc_reset(host, SDHCI_RESET_DATA); -+ spin_lock_irqsave(&host->lock, flags); - } - - host->mrq = NULL; -@@ -1259,7 +1275,7 @@ static void bcm2835_mmc_tasklet_finish(unsigned long param) - - - --int bcm2835_mmc_add_host(struct bcm2835_host *host) -+static int bcm2835_mmc_add_host(struct bcm2835_host *host) - { - struct mmc_host *mmc = host->mmc; - struct device *dev = mmc->parent; -@@ -1287,8 +1303,6 @@ int bcm2835_mmc_add_host(struct bcm2835_host *host) - - host->flags = SDHCI_AUTO_CMD23; - -- spin_lock_init(&host->lock); -- - #ifdef FORCE_PIO - dev_info(dev, "Forcing PIO mode\n"); - host->have_dma = false; - -From d7580af2f81793fd3312608de95a9009123d8710 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 23:34:50 +0100 -Subject: [PATCH 132/216] bcm2835-mmc: Add range of debug options for slowing - things down - -bcm2835-mmc: Add option to disable some delays - -bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23 - -bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23 ---- - drivers/mmc/core/quirks.c | 2 ++ - drivers/mmc/host/bcm2835-mmc.c | 44 ++++++++++++++++++++++++++++-------------- - 2 files changed, 32 insertions(+), 14 deletions(-) - -diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c -index f472082..bc3bbad 100644 ---- a/drivers/mmc/core/quirks.c -+++ b/drivers/mmc/core/quirks.c -@@ -71,6 +71,7 @@ static const struct mmc_fixup mmc_fixup_methods[] = { - - void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - { -+ extern unsigned mmc_debug; - const struct mmc_fixup *f; - u64 rev = cid_rev_card(card); - -@@ -98,6 +99,7 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail. - * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers). - */ -+ if (mmc_debug & (1<<13)) - card->quirks |= MMC_QUIRK_BLK_NO_CMD23; - } - EXPORT_SYMBOL(mmc_fixup_device); -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index 1c34f476..68314d5 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -71,6 +71,9 @@ pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) - #define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) - - -+unsigned mmc_debug; -+unsigned mmc_debug2; -+ - struct bcm2835_host { - spinlock_t lock; - -@@ -131,17 +134,27 @@ struct bcm2835_host { - }; - - --static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) -+static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from) - { -+ unsigned delay; - lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); -+ -+ delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf); -+ if (delay && !((1<lock); - writel(val, host->ioaddr + reg); -+ -+ delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf); -+ if (delay) -+ udelay(delay); - } - - static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) -@@ -162,7 +175,7 @@ static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int re - if (reg == SDHCI_TRANSFER_MODE) - host->shadow = newval; - else -- bcm2835_mmc_writel(host, newval, reg & ~3); -+ bcm2835_mmc_writel(host, newval, reg & ~3, 0); - - } - -@@ -174,7 +187,7 @@ static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg - u32 mask = 0xff << byte_shift; - u32 newval = (oldval & ~mask) | (val << byte_shift); - -- bcm2835_mmc_writel(host, newval, reg & ~3); -+ bcm2835_mmc_writel(host, newval, reg & ~3, 1); - } - - -@@ -206,7 +219,7 @@ static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear) - ier &= ~clear; - /* change which requests generate IRQs - makes no difference to - the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ -- bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2); - } - - -@@ -307,8 +320,8 @@ static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - SDHCI_INT_RESPONSE; - - spin_lock_irqsave(&host->lock, flags); -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3); - spin_unlock_irqrestore(&host->lock, flags); - - if (soft) { -@@ -534,8 +547,8 @@ static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host) - else - host->ier = (host->ier & ~dma_irqs) | pio_irqs; - -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4); - } - - -@@ -617,7 +630,7 @@ static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host, - mode |= SDHCI_TRNS_AUTO_CMD12; - else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { - mode |= SDHCI_TRNS_AUTO_CMD23; -- bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); -+ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5); - } - } - -@@ -680,7 +693,7 @@ void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd - - bcm2835_mmc_prepare_data(host, cmd); - -- bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT); -+ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6); - - bcm2835_mmc_set_transfer_mode(host, cmd); - -@@ -837,8 +850,8 @@ static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int en - else - host->ier &= ~SDHCI_INT_CARD_INT; - -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7); - mmiowb(); - } - } -@@ -985,7 +998,7 @@ static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id) - /* Clear selected interrupts. */ - mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | - SDHCI_INT_BUS_POWER); -- bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS); -+ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8); - - - if (intmask & SDHCI_INT_CMD_MASK) -@@ -1015,7 +1028,7 @@ static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id) - - if (intmask) { - unexpected |= intmask; -- bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS); -+ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9); - } - - if (result == IRQ_NONE) -@@ -1303,6 +1316,7 @@ static int bcm2835_mmc_add_host(struct bcm2835_host *host) - - host->flags = SDHCI_AUTO_CMD23; - -+ dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2); - #ifdef FORCE_PIO - dev_info(dev, "Forcing PIO mode\n"); - host->have_dma = false; -@@ -1514,6 +1528,8 @@ static struct platform_driver bcm2835_mmc_driver = { - }; - module_platform_driver(bcm2835_mmc_driver); - -+module_param(mmc_debug, uint, 0644); -+module_param(mmc_debug2, uint, 0644); - MODULE_ALIAS("platform:mmc-bcm2835"); - MODULE_DESCRIPTION("BCM2835 SDHCI driver"); - MODULE_LICENSE("GPL v2"); - -From e34578092803603a960a2a7bcccde5d0c8240b9a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 19:08:54 +0200 -Subject: [PATCH 133/216] BCM270x: Correct vcio device memory resource and add - irq resource -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The vcio driver hardcodes these resources, so this is the first -step in correcting this. Spell out the device name so we don't -have to include mach/vcio.h, since this header file will eventually -go away when the driver is later moved to drivers/mailbox. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 17 ++++++++++------- - arch/arm/mach-bcm2708/include/mach/platform.h | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 17 ++++++++++------- - arch/arm/mach-bcm2709/include/mach/platform.h | 1 + - 4 files changed, 22 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 486e090..51f8efa 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -55,7 +55,6 @@ - #include - - #include --#include - #include - - #include -@@ -414,17 +413,21 @@ static struct platform_device bcm2708_usb_device = { - }; - - static struct resource bcm2708_vcio_resources[] = { -- [0] = { /* mailbox/semaphore/doorbell access */ -- .start = MCORE_BASE, -- .end = MCORE_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -+ { -+ .start = ARMCTRL_0_MAIL0_BASE, -+ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_MAILBOX, -+ .end = IRQ_ARM_MAILBOX, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_vcio_device = { -- .name = BCM_VCIO_DRIVER_NAME, -+ .name = "bcm2708_vcio", - .id = -1, /* only one VideoCore I/O area */ - .resource = bcm2708_vcio_resources, - .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index 2e7e1bb..bef3e5a 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - /* -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 44bfc50..8ed88b4 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -56,7 +56,6 @@ - #include - - #include --#include - #include - - #include -@@ -433,17 +432,21 @@ static struct platform_device bcm2708_usb_device = { - }; - - static struct resource bcm2708_vcio_resources[] = { -- [0] = { /* mailbox/semaphore/doorbell access */ -- .start = MCORE_BASE, -- .end = MCORE_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -+ { -+ .start = ARMCTRL_0_MAIL0_BASE, -+ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_MAILBOX, -+ .end = IRQ_ARM_MAILBOX, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_vcio_device = { -- .name = BCM_VCIO_DRIVER_NAME, -+ .name = "bcm2708_vcio", - .id = -1, /* only one VideoCore I/O area */ - .resource = bcm2708_vcio_resources, - .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 7157f38..5574bb5 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - /* - -From 4b03fd4291b9ed1cd100b359967f1b1fdc39984a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:55:53 +0200 -Subject: [PATCH 134/216] video: fbdev: bcm2708_fb: Don't panic on error -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to panic the kernel if the video driver fails. -Just print a message and return an error. - -Signed-off-by: Noralf Trønnes ---- - drivers/video/fbdev/bcm2708_fb.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 9179291..52e655a 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -325,8 +325,8 @@ static int bcm2708_fb_set_par(struct fb_info *info) - /* the console may currently be locked */ - console_trylock(); - console_unlock(); -- -- BUG(); /* what can we do here */ -+ pr_err("bcm2708_fb_set_par: Failed to set screen_base\n"); -+ return -EIO; - } - } - print_debug -@@ -677,7 +677,9 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) - */ - - fb_set_var(&fb->fb, &fb->fb.var); -- bcm2708_fb_set_par(&fb->fb); -+ ret = bcm2708_fb_set_par(&fb->fb); -+ if (ret) -+ return ret; - - print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth, - fbheight, fbdepth, fbswap); - -From 1965f1d8dcc748e1f9ba3ff28c8fb5191e081a4d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 20:49:04 +0200 -Subject: [PATCH 135/216] BCM2708: vcio: Fix checkpatch issues -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -checkpatch.pl errors and warnings: -Many whitespace related issues in some form or another. -Consider using instead of . -braces {} are not necessary for single statement blocks. -Use pr_* instead of printk. -Do not initialise statics to 0 or NULL. -Avoid CamelCase. -sizeof size should be sizeof(size). -break is not useful after a goto or return. -struct file_operations should normally be const -Possible unnecessary 'out of memory' message -Comparison to NULL could be written "!res" -quoted string split across lines. - -This has not been adressed: -WARNING: consider using a completion - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 12 ++- - arch/arm/mach-bcm2708/vcio.c | 123 ++++++++++++++---------------- - 2 files changed, 62 insertions(+), 73 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -index 8e11d67e..58188b74 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -12,10 +12,6 @@ - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - #ifndef _MACH_BCM2708_VCIO_H - #define _MACH_BCM2708_VCIO_H -@@ -34,12 +30,14 @@ - #define MBOX_CHAN_COUNT 9 - - enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 -+ VCMSG_PROCESS_REQUEST = 0x00000000 - }; -+ - enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 - }; -+ - /* Mailbox property tags */ - enum { - VCMSG_PROPERTY_END = 0x00000000, -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 700bff4..5e9e777 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -37,8 +37,7 @@ - #include - #include - --#include -- -+#include - - #define DRIVER_NAME BCM_VCIO_DRIVER_NAME - -@@ -61,7 +60,9 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de --static struct class *vcio_class = NULL; -+ -+static struct class *vcio_class; -+ - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -102,9 +103,9 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - { - int rc; - -- if (mbox->magic != MBOX_MAGIC) -+ if (mbox->magic != MBOX_MAGIC) { - rc = -EINVAL; -- else { -+ } else { - /* wait for the mailbox FIFO to have some space in it */ - while (0 != (readl(mbox->status) & ARM_MS_FULL)) - cpu_relax(); -@@ -119,9 +120,9 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - { - int rc; - -- if (mbox->magic != MBOX_MAGIC) -+ if (mbox->magic != MBOX_MAGIC) { - rc = -EINVAL; -- else { -+ } else { - down(&mbox->sema[chan]); - *data28 = MBOX_DATA28(mbox->msg[chan]); - mbox->msg[chan] = 0; -@@ -133,17 +134,18 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - static irqreturn_t mbox_irq(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; - int status = readl(mbox->status); - int ret = IRQ_NONE; - - while (!(status & ARM_MS_EMPTY)) { - uint32_t msg = readl(mbox->read); - int chan = MBOX_CHAN(msg); -+ - if (chan < MBOX_CHAN_COUNT) { - if (mbox->msg[chan]) { - /* Overflow */ -- printk(KERN_ERR DRIVER_NAME -+ pr_err(DRIVER_NAME - ": mbox chan %d overflow - drop %08x\n", - chan, msg); - } else { -@@ -151,7 +153,7 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - up(&mbox->sema[chan]); - } - } else { -- printk(KERN_ERR DRIVER_NAME -+ pr_err(DRIVER_NAME - ": invalid channel selector (msg %08x)\n", msg); - } - ret = IRQ_HANDLED; -@@ -174,9 +176,9 @@ static struct device *mbox_dev; /* we assume there's only one! */ - - static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) - { -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); - int rc; - -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); - device_lock(dev); - rc = mbox_write(mailbox, chan, data28); - device_unlock(dev); -@@ -186,9 +188,9 @@ static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) - - static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) - { -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); - int rc; - -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); - device_lock(dev); - rc = mbox_read(mailbox, chan, data28); - device_unlock(dev); -@@ -221,41 +223,36 @@ static void dev_mbox_register(const char *dev_name, struct device *dev) - - static int mbox_copy_from_user(void *dst, const void *src, int size) - { -- if ( (uint32_t)src < TASK_SIZE) -- { -+ if ((uint32_t)src < TASK_SIZE) - return copy_from_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } -+ -+ memcpy(dst, src, size); -+ -+ return 0; - } - - static int mbox_copy_to_user(void *dst, const void *src, int size) - { -- if ( (uint32_t)dst < TASK_SIZE) -- { -+ if ((uint32_t)dst < TASK_SIZE) - return copy_to_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } -+ -+ memcpy(dst, src, size); -+ -+ return 0; - } - - static DEFINE_MUTEX(mailbox_lock); - extern int bcm_mailbox_property(void *data, int size) - { - uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ - int s = 0; - -- mutex_lock(&mailbox_lock); -+ mutex_lock(&mailbox_lock); - /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -+ GFP_ATOMIC); - if (mem_kern) { - /* create the message */ - mbox_copy_from_user(mem_kern, data, size); -@@ -263,9 +260,8 @@ extern int bcm_mailbox_property(void *data, int size) - /* send the message */ - wmb(); - s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) { -+ if (s == 0) - s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- } - if (s == 0) { - /* copy the response */ - rmb(); -@@ -276,9 +272,9 @@ extern int bcm_mailbox_property(void *data, int size) - s = -ENOMEM; - } - if (s != 0) -- printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); - -- mutex_unlock(&mailbox_lock); -+ mutex_unlock(&mailbox_lock); - return s; - } - EXPORT_SYMBOL_GPL(bcm_mailbox_property); -@@ -291,7 +287,7 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); - * Is the device open right now? Used to prevent - * concurent access into the same device - */ --static int Device_Open = 0; -+static bool device_is_open; - - /* - * This is called whenever a process attempts to open the device file -@@ -301,10 +297,10 @@ static int device_open(struct inode *inode, struct file *file) - /* - * We don't want to talk to two processes at the same time - */ -- if (Device_Open) -+ if (device_is_open) - return -EBUSY; - -- Device_Open++; -+ device_is_open = true; - /* - * Initialize the message - */ -@@ -317,7 +313,7 @@ static int device_release(struct inode *inode, struct file *file) - /* - * We're now ready for our next caller - */ -- Device_Open--; -+ device_is_open = false; - - module_put(THIS_MODULE); - return 0; -@@ -333,9 +329,8 @@ static int device_release(struct inode *inode, struct file *file) - * calling process), the ioctl call returns the output of this function. - * - */ --static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -- unsigned int ioctl_num, /* number and param for ioctl */ -- unsigned long ioctl_param) -+static long device_ioctl(struct file *file, unsigned int ioctl_num, -+ unsigned long ioctl_param) - { - unsigned size; - /* -@@ -348,11 +343,10 @@ static long device_ioctl(struct file *file, /* see include/linux/fs.h */ - * to be the device's message. Get the parameter given to - * ioctl by the process. - */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); - return bcm_mailbox_property((void *)ioctl_param, size); -- break; - default: -- printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); - return -EINVAL; - } - -@@ -368,7 +362,7 @@ static long device_ioctl(struct file *file, /* see include/linux/fs.h */ - * the devices table, it can't be local to - * init_module. NULL is for unimplemented functios. - */ --struct file_operations fops = { -+const struct file_operations fops = { - .unlocked_ioctl = device_ioctl, - .open = device_open, - .release = device_release, /* a.k.a. close */ -@@ -380,17 +374,15 @@ static int bcm_vcio_probe(struct platform_device *pdev) - struct vc_mailbox *mailbox; - - mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (NULL == mailbox) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "mailbox memory\n"); -+ if (!mailbox) { - ret = -ENOMEM; - } else { - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -+ if (!res) { -+ pr_err(DRIVER_NAME -+ ": failed to obtain memory resource\n"); - ret = -ENODEV; - kfree(mailbox); - } else { -@@ -402,8 +394,8 @@ static int bcm_vcio_probe(struct platform_device *pdev) - - mbox_irqaction.dev_id = mailbox; - setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -+ dev_info(&pdev->dev, "mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); - } - } - -@@ -417,17 +409,18 @@ static int bcm_vcio_probe(struct platform_device *pdev) - * Negative values signify an error - */ - if (ret < 0) { -- printk(KERN_ERR DRIVER_NAME -- "Failed registering the character device %d\n", ret); -+ pr_err(DRIVER_NAME -+ "Failed registering the character device %d\n", -+ ret); - return ret; - } - vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); - if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret ; -+ ret = PTR_ERR(vcio_class); -+ return ret; - } - device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -+ "vcio"); - } - return ret; - } -@@ -456,20 +449,18 @@ static int __init bcm_mbox_init(void) - { - int ret; - -- printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ pr_info("mailbox: Broadcom VideoCore Mailbox driver\n"); - - ret = platform_driver_register(&bcm_mbox_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -+ if (ret) -+ pr_err(DRIVER_NAME ": failed to register on platform\n"); - - return ret; - } - - static void __exit bcm_mbox_exit(void) - { -- device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); - class_destroy(vcio_class); - unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - -From f7567a97143abdc87b5dc258b3b628ba115ce0b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:02:44 +0200 -Subject: [PATCH 136/216] BCM2708: vcio: Remove unused code and compact - comments -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The config reference SERIAL_BCM_MBOX_CONSOLE does not exist, -so remove the whole clause as it will always be false. - -Remove includes that are not needed. -Add . -Also sort include headers alphabetically, since this -is now the preferred coding style. - -Remove vc_mailbox->dev since it is not used. - -Compact some comments to one line. -Remove superfluous comments. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 68 ++++++++++---------------------------------- - 1 file changed, 15 insertions(+), 53 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 5e9e777..270f126 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -12,39 +12,24 @@ - * VideoCore processor - */ - --#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) --#define SUPPORT_SYSRQ --#endif -- -+#include -+#include - #include --#include --#include --#include - #include --#include -+#include - #include --#include --#include --#include --#include --#include --#include - #include --#include -- - #include -+#include -+#include -+#include -+#include - - #include - #include - --#include -- - #define DRIVER_NAME BCM_VCIO_DRIVER_NAME - --/* ---------------------------------------------------------------------- -- * Mailbox -- * -------------------------------------------------------------------- */ -- - /* offsets from a mail box base address */ - #define MAIL_WRT 0x00 /* write - and next 4 words */ - #define MAIL_RD 0x00 /* read - and next 4 words */ -@@ -64,7 +49,6 @@ - static struct class *vcio_class; - - struct vc_mailbox { -- struct device *dev; /* parent device */ - void __iomem *status; - void __iomem *config; - void __iomem *read; -@@ -79,7 +63,6 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - { - int i; - -- mbox_out->dev = dev; - mbox_out->status = __io_address(addr_mbox + MAIL_STA); - mbox_out->config = __io_address(addr_mbox + MAIL_CNF); - mbox_out->read = __io_address(addr_mbox + MAIL_RD); -@@ -144,7 +127,6 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - - if (chan < MBOX_CHAN_COUNT) { - if (mbox->msg[chan]) { -- /* Overflow */ - pr_err(DRIVER_NAME - ": mbox chan %d overflow - drop %08x\n", - chan, msg); -@@ -168,9 +150,7 @@ static struct irqaction mbox_irqaction = { - .handler = mbox_irq, - }; - --/* ---------------------------------------------------------------------- -- * Mailbox Methods -- * -------------------------------------------------------------------- */ -+/* Mailbox Methods */ - - static struct device *mbox_dev; /* we assume there's only one! */ - -@@ -279,9 +259,7 @@ extern int bcm_mailbox_property(void *data, int size) - } - EXPORT_SYMBOL_GPL(bcm_mailbox_property); - --/* ---------------------------------------------------------------------- -- * Platform Device for Mailbox -- * -------------------------------------------------------------------- */ -+/* Platform Device for Mailbox */ - - /* - * Is the device open right now? Used to prevent -@@ -289,33 +267,26 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); - */ - static bool device_is_open; - --/* -- * This is called whenever a process attempts to open the device file -- */ -+/* This is called whenever a process attempts to open the device file */ - static int device_open(struct inode *inode, struct file *file) - { -- /* -- * We don't want to talk to two processes at the same time -- */ -+ /* We don't want to talk to two processes at the same time */ - if (device_is_open) - return -EBUSY; - - device_is_open = true; -- /* -- * Initialize the message -- */ - try_module_get(THIS_MODULE); -+ - return 0; - } - - static int device_release(struct inode *inode, struct file *file) - { -- /* -- * We're now ready for our next caller -- */ -+ /* We're now ready for our next caller */ - device_is_open = false; - - module_put(THIS_MODULE); -+ - return 0; - } - -@@ -333,9 +304,7 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, - unsigned long ioctl_param) - { - unsigned size; -- /* -- * Switch according to the ioctl called -- */ -+ - switch (ioctl_num) { - case IOCTL_MBOX_PROPERTY: - /* -@@ -400,14 +369,7 @@ static int bcm_vcio_probe(struct platform_device *pdev) - } - - if (ret == 0) { -- /* -- * Register the character device -- */ - ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- -- /* -- * Negative values signify an error -- */ - if (ret < 0) { - pr_err(DRIVER_NAME - "Failed registering the character device %d\n", - -From 406f0f628a2f978a1da4d25dda3b5eafb94cefd0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:10:18 +0200 -Subject: [PATCH 137/216] BCM2708: vcio: Move character device teardown to - driver remove -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -chrdev is created in the probe function, but teared down in module exit. -Move chrdev teardown to happen on device removal. -Also add missing mbox_dev disabling. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 270f126..cac8dd7 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -391,8 +391,12 @@ static int bcm_vcio_remove(struct platform_device *pdev) - { - struct vc_mailbox *mailbox = platform_get_drvdata(pdev); - -+ mbox_dev = NULL; - platform_set_drvdata(pdev, NULL); - kfree(mailbox); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - - return 0; - } -@@ -422,9 +426,6 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -- device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - - -From fa189cd5d18e5cda8438873181a329fc489a6649 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:20:46 +0200 -Subject: [PATCH 138/216] BCM2708: vcio: Restructure error paths -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to use if/else clauses on error when return can be used directly. -Also test for errors first if possible. -This is done to enhance readability. -bcm_vcio_probe() is not touched, it will be reworked later. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 48 +++++++++++++++++++------------------------- - 1 file changed, 21 insertions(+), 27 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index cac8dd7..36e0f1e 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -84,34 +84,28 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - - static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - { -- int rc; -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; - -- if (mbox->magic != MBOX_MAGIC) { -- rc = -EINVAL; -- } else { -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -- cpu_relax(); -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); - -- writel(MBOX_MSG(chan, data28), mbox->write); -- rc = 0; -- } -- return rc; -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ -+ return 0; - } - - static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - { -- int rc; -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; - -- if (mbox->magic != MBOX_MAGIC) { -- rc = -EINVAL; -- } else { -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- rc = 0; -- } -- return rc; -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ -+ return 0; - } - - static irqreturn_t mbox_irq(int irq, void *dev_id) -@@ -180,19 +174,19 @@ static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) - - extern int bcm_mailbox_write(unsigned chan, uint32_t data28) - { -- if (mbox_dev) -- return dev_mbox_write(mbox_dev, chan, data28); -- else -+ if (!mbox_dev) - return -ENODEV; -+ -+ return dev_mbox_write(mbox_dev, chan, data28); - } - EXPORT_SYMBOL_GPL(bcm_mailbox_write); - - extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) - { -- if (mbox_dev) -- return dev_mbox_read(mbox_dev, chan, data28); -- else -+ if (!mbox_dev) - return -ENODEV; -+ -+ return dev_mbox_read(mbox_dev, chan, data28); - } - EXPORT_SYMBOL_GPL(bcm_mailbox_read); - - -From ce2c991a11f0a94679423655dceed9bb80604892 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:28:31 +0200 -Subject: [PATCH 139/216] BCM2708: vcio: Move some macros from header to driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Move some macros that are only used by the driver: -MAJOR_NUM -IOCTL_MBOX_PROPERTY -DEVICE_FILE_NAME - -This one becomes superfluous: BCM_VCIO_DRIVER_NAME - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 35 ------------------------------- - arch/arm/mach-bcm2708/vcio.c | 9 ++++++-- - 2 files changed, 7 insertions(+), 37 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -index 58188b74..95ad121 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -20,8 +20,6 @@ - * (semaphores, doorbells, mailboxes) - */ - --#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -- - /* Constants shared with the ARM identifying separate mailbox channels */ - #define MBOX_CHAN_POWER 0 /* for use by the power management interface */ - #define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -@@ -127,37 +125,4 @@ extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); - extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); - extern int /*rc*/ bcm_mailbox_property(void *data, int size); - --#include -- --/* -- * The major device number. We can't rely on dynamic -- * registration any more, because ioctls need to know -- * it. -- */ --#define MAJOR_NUM 100 -- --/* -- * Set the message of the device driver -- */ --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) --/* -- * _IOWR means that we're creating an ioctl command -- * number for passing information from a user process -- * to the kernel module and from the kernel module to user process -- * -- * The first arguments, MAJOR_NUM, is the major device -- * number we're using. -- * -- * The second argument is the number of the command -- * (there could be several with different meanings). -- * -- * The third argument is the type we want to get from -- * the process to the kernel. -- */ -- --/* -- * The name of the device file -- */ --#define DEVICE_FILE_NAME "vcio" -- - #endif -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 36e0f1e..75cf955 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -28,7 +29,8 @@ - #include - #include - --#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+#define DRIVER_NAME "bcm2708_vcio" -+#define DEVICE_FILE_NAME "vcio" - - /* offsets from a mail box base address */ - #define MAIL_WRT 0x00 /* write - and next 4 words */ -@@ -46,6 +48,9 @@ - - #define MBOX_MAGIC 0xd0d0c0de - -+#define MAJOR_NUM 100 -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+ - static struct class *vcio_class; - - struct vc_mailbox { -@@ -370,7 +375,7 @@ static int bcm_vcio_probe(struct platform_device *pdev) - ret); - return ret; - } -- vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); - if (IS_ERR(vcio_class)) { - ret = PTR_ERR(vcio_class); - return ret; - -From 71c6a7270af56930e1e31ff243048c1ac12ebc1f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:40:03 +0200 -Subject: [PATCH 140/216] BCM2708: vcio: Only store the register base address -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to keep pointers to the sub registers. Only -store the base address. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 37 ++++++++++++++----------------------- - 1 file changed, 14 insertions(+), 23 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 75cf955..e67fa3e 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -33,12 +33,12 @@ - #define DEVICE_FILE_NAME "vcio" - - /* offsets from a mail box base address */ --#define MAIL_WRT 0x00 /* write - and next 4 words */ --#define MAIL_RD 0x00 /* read - and next 4 words */ --#define MAIL_POL 0x10 /* read without popping the fifo */ --#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL_STA 0x18 /* status */ --#define MAIL_CNF 0x1C /* configuration */ -+#define MAIL0_RD 0x00 /* read - and next 4 words */ -+#define MAIL0_POL 0x10 /* read without popping the fifo */ -+#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL0_STA 0x18 /* status */ -+#define MAIL0_CNF 0x1C /* configuration */ -+#define MAIL1_WRT 0x20 /* write - and next 4 words */ - - #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) - #define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -@@ -54,10 +54,7 @@ - static struct class *vcio_class; - - struct vc_mailbox { -- void __iomem *status; -- void __iomem *config; -- void __iomem *read; -- void __iomem *write; -+ void __iomem *regs; - uint32_t msg[MBOX_CHAN_COUNT]; - struct semaphore sema[MBOX_CHAN_COUNT]; - uint32_t magic; -@@ -68,13 +65,7 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - { - int i; - -- mbox_out->status = __io_address(addr_mbox + MAIL_STA); -- mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -- mbox_out->read = __io_address(addr_mbox + MAIL_RD); -- /* Write to the other mailbox */ -- mbox_out->write = -- __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -- MAIL_WRT); -+ mbox_out->regs = __io_address(addr_mbox); - - for (i = 0; i < MBOX_CHAN_COUNT; i++) { - mbox_out->msg[i] = 0; -@@ -82,7 +73,7 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - } - - /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); - - mbox_out->magic = MBOX_MAGIC; - } -@@ -93,10 +84,10 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - return -EINVAL; - - /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) - cpu_relax(); - -- writel(MBOX_MSG(chan, data28), mbox->write); -+ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); - - return 0; - } -@@ -117,11 +108,11 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ - struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -- int status = readl(mbox->status); -+ int status = readl(mbox->regs + MAIL0_STA); - int ret = IRQ_NONE; - - while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->read); -+ uint32_t msg = readl(mbox->regs + MAIL0_RD); - int chan = MBOX_CHAN(msg); - - if (chan < MBOX_CHAN_COUNT) { -@@ -138,7 +129,7 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - ": invalid channel selector (msg %08x)\n", msg); - } - ret = IRQ_HANDLED; -- status = readl(mbox->status); -+ status = readl(mbox->regs + MAIL0_STA); - } - return ret; - } - -From 30e7622ceffd50a31b6544e3a3e05bb0743c3bc2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:44:39 +0200 -Subject: [PATCH 141/216] BCM2708: vcio: Do not print messages in module init -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It is not common practice to print messages from a -module init function that only register a driver. -Remove obsolete module alias. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 11 +---------- - 1 file changed, 1 insertion(+), 10 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index e67fa3e..ff50ebd 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -403,15 +403,7 @@ static struct platform_driver bcm_mbox_driver = { - - static int __init bcm_mbox_init(void) - { -- int ret; -- -- pr_info("mailbox: Broadcom VideoCore Mailbox driver\n"); -- -- ret = platform_driver_register(&bcm_mbox_driver); -- if (ret) -- pr_err(DRIVER_NAME ": failed to register on platform\n"); -- -- return ret; -+ return platform_driver_register(&bcm_mbox_driver); - } - - static void __exit bcm_mbox_exit(void) -@@ -425,4 +417,3 @@ module_exit(bcm_mbox_exit); - MODULE_AUTHOR("Gray Girling"); - MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); - MODULE_LICENSE("GPL"); --MODULE_ALIAS("platform:bcm-mbox"); - -From 7a9128973d51200625a3d3f8ff72a4580cb9f14b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 23:33:43 +0200 -Subject: [PATCH 142/216] BCM2708: vcio: Use device resources -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use device resources instead of hardcoding them. -Use devm_* functions where possible. -Merge dev_mbox_register() with probe function. -Add Device Tree support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 122 +++++++++++++++++++++---------------------- - 1 file changed, 61 insertions(+), 61 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index ff50ebd..c4c2bcd 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -21,13 +21,10 @@ - #include - #include - #include --#include - #include --#include - #include - - #include --#include - - #define DRIVER_NAME "bcm2708_vcio" - #define DEVICE_FILE_NAME "vcio" -@@ -60,13 +57,10 @@ struct vc_mailbox { - uint32_t magic; - }; - --static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -- uint32_t addr_mbox) -+static void mbox_init(struct vc_mailbox *mbox_out) - { - int i; - -- mbox_out->regs = __io_address(addr_mbox); -- - for (i = 0; i < MBOX_CHAN_COUNT; i++) { - mbox_out->msg[i] = 0; - sema_init(&mbox_out->sema[i], 0); -@@ -104,7 +98,7 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - return 0; - } - --static irqreturn_t mbox_irq(int irq, void *dev_id) -+static irqreturn_t mbox_irq_handler(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ - struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -@@ -134,12 +128,6 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - return ret; - } - --static struct irqaction mbox_irqaction = { -- .name = "ARM Mailbox IRQ", -- .flags = IRQF_DISABLED | IRQF_IRQPOLL, -- .handler = mbox_irq, --}; -- - /* Mailbox Methods */ - - static struct device *mbox_dev; /* we assume there's only one! */ -@@ -186,11 +174,6 @@ extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) - } - EXPORT_SYMBOL_GPL(bcm_mailbox_read); - --static void dev_mbox_register(const char *dev_name, struct device *dev) --{ -- mbox_dev = dev; --} -- - static int mbox_copy_from_user(void *dst, const void *src, int size) - { - if ((uint32_t)src < TASK_SIZE) -@@ -329,61 +312,71 @@ const struct file_operations fops = { - - static int bcm_vcio_probe(struct platform_device *pdev) - { -- int ret = 0; -+ struct device *dev = &pdev->dev; -+ struct device *vdev; - struct vc_mailbox *mailbox; -+ struct resource *res; -+ int irq, ret; -+ -+ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -+ if (!mailbox) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mailbox->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(mailbox->regs)) -+ return PTR_ERR(mailbox->regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ ret = devm_request_irq(dev, irq, mbox_irq_handler, -+ IRQF_DISABLED | IRQF_IRQPOLL, -+ dev_name(dev), mailbox); -+ if (ret) { -+ dev_err(dev, "Interrupt request failed %d\n", ret); -+ return ret; -+ } - -- mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (!mailbox) { -- ret = -ENOMEM; -- } else { -- struct resource *res; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!res) { -- pr_err(DRIVER_NAME -- ": failed to obtain memory resource\n"); -- ret = -ENODEV; -- kfree(mailbox); -- } else { -- /* should be based on the registers from res really */ -- mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -- -- platform_set_drvdata(pdev, mailbox); -- dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ if (ret < 0) { -+ pr_err("Character device registration failed %d\n", ret); -+ return ret; -+ } - -- mbox_irqaction.dev_id = mailbox; -- setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- dev_info(&pdev->dev, "mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -- } -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ pr_err("Class creation failed %d\n", ret); -+ goto err_class; - } - -- if (ret == 0) { -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- if (ret < 0) { -- pr_err(DRIVER_NAME -- "Failed registering the character device %d\n", -- ret); -- return ret; -- } -- vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret; -- } -- device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -+ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); -+ if (IS_ERR(vdev)) { -+ ret = PTR_ERR(vdev); -+ pr_err("Device creation failed %d\n", ret); -+ goto err_dev; - } -+ -+ mbox_init(mailbox); -+ platform_set_drvdata(pdev, mailbox); -+ mbox_dev = dev; -+ -+ dev_info(dev, "mailbox at %p\n", mailbox->regs); -+ -+ return 0; -+ -+err_dev: -+ class_destroy(vcio_class); -+err_class: -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ - return ret; - } - - static int bcm_vcio_remove(struct platform_device *pdev) - { -- struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -- - mbox_dev = NULL; - platform_set_drvdata(pdev, NULL); -- kfree(mailbox); - device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); - class_destroy(vcio_class); - unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -@@ -391,6 +384,12 @@ static int bcm_vcio_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm_vcio_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-vcio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -+ - static struct platform_driver bcm_mbox_driver = { - .probe = bcm_vcio_probe, - .remove = bcm_vcio_remove, -@@ -398,6 +397,7 @@ static struct platform_driver bcm_mbox_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm_vcio_of_match_table, - }, - }; - - -From bb294088d80bcba531bc3d58b4a6c08b8cdcb0b0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 19:11:03 +0200 -Subject: [PATCH 143/216] mailbox: bcm2708: Add bcm2708-vcio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Copy the arch vcio.c driver to drivers/mailbox. -This is done to make it available on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/Kconfig | 6 + - drivers/mailbox/Makefile | 2 + - drivers/mailbox/bcm2708-vcio.c | 426 ++++++++++++++++++++++++++ - include/linux/platform_data/mailbox-bcm2708.h | 126 ++++++++ - 4 files changed, 560 insertions(+) - create mode 100644 drivers/mailbox/bcm2708-vcio.c - create mode 100644 include/linux/platform_data/mailbox-bcm2708.h - -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index 84325f2..fdcb206 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -6,6 +6,12 @@ menuconfig MAILBOX - signals. Say Y if your platform supports hardware mailboxes. - - if MAILBOX -+config BCM2708_MBOX -+ bool "Broadcom BCM2708 Mailbox (vcio)" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ help -+ Broadcom BCM2708 Mailbox (vcio) -+ - config PL320_MBOX - bool "ARM PL320 Mailbox" - depends on ARM_AMBA -diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile -index 2e79231..c2d2bed 100644 ---- a/drivers/mailbox/Makefile -+++ b/drivers/mailbox/Makefile -@@ -2,6 +2,8 @@ - - obj-$(CONFIG_MAILBOX) += mailbox.o - -+obj-$(CONFIG_BCM2708_MBOX) += bcm2708-vcio.o -+ - obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o - - obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -new file mode 100644 -index 0000000..ee3e778 ---- /dev/null -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -0,0 +1,426 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_vcio" -+#define DEVICE_FILE_NAME "vcio" -+ -+/* offsets from a mail box base address */ -+#define MAIL0_RD 0x00 /* read - and next 4 words */ -+#define MAIL0_POL 0x10 /* read without popping the fifo */ -+#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL0_STA 0x18 /* status */ -+#define MAIL0_CNF 0x1C /* configuration */ -+#define MAIL1_WRT 0x20 /* write - and next 4 words */ -+ -+/* On MACH_BCM270x these come through (arm_control.h ) */ -+#ifndef ARM_MS_EMPTY -+#define ARM_MS_EMPTY BIT(30) -+#define ARM_MS_FULL BIT(31) -+ -+#define ARM_MC_IHAVEDATAIRQEN BIT(0) -+#endif -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+#define MAJOR_NUM 100 -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+ -+static struct class *vcio_class; -+ -+struct vc_mailbox { -+ void __iomem *regs; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out) -+{ -+ int i; -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; -+ -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); -+ -+ return 0; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; -+ -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ -+ return 0; -+} -+ -+static irqreturn_t mbox_irq_handler(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -+ int status = readl(mbox->regs + MAIL0_STA); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->regs + MAIL0_RD); -+ int chan = MBOX_CHAN(msg); -+ -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ pr_err(DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ pr_err(DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->regs + MAIL0_STA); -+ } -+ return ret; -+} -+ -+/* Mailbox Methods */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ int rc; -+ -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ int rc; -+ -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (!mbox_dev) -+ return -ENODEV; -+ -+ return dev_mbox_write(mbox_dev, chan, data28); -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (!mbox_dev) -+ return -ENODEV; -+ -+ return dev_mbox_read(mbox_dev, chan, data28); -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)src < TASK_SIZE) -+ return copy_from_user(dst, src, size); -+ -+ memcpy(dst, src, size); -+ -+ return 0; -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)dst < TASK_SIZE) -+ return copy_to_user(dst, src, size); -+ -+ memcpy(dst, src, size); -+ -+ return 0; -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -+ GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* Platform Device for Mailbox */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static bool device_is_open; -+ -+/* This is called whenever a process attempts to open the device file */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* We don't want to talk to two processes at the same time */ -+ if (device_is_open) -+ return -EBUSY; -+ -+ device_is_open = true; -+ try_module_get(THIS_MODULE); -+ -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* We're now ready for our next caller */ -+ device_is_open = false; -+ -+ module_put(THIS_MODULE); -+ -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, unsigned int ioctl_num, -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ default: -+ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+const struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device *vdev; -+ struct vc_mailbox *mailbox; -+ struct resource *res; -+ int irq, ret; -+ -+ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -+ if (!mailbox) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mailbox->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(mailbox->regs)) -+ return PTR_ERR(mailbox->regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ ret = devm_request_irq(dev, irq, mbox_irq_handler, -+ IRQF_DISABLED | IRQF_IRQPOLL, -+ dev_name(dev), mailbox); -+ if (ret) { -+ dev_err(dev, "Interrupt request failed %d\n", ret); -+ return ret; -+ } -+ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ if (ret < 0) { -+ pr_err("Character device registration failed %d\n", ret); -+ return ret; -+ } -+ -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ pr_err("Class creation failed %d\n", ret); -+ goto err_class; -+ } -+ -+ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); -+ if (IS_ERR(vdev)) { -+ ret = PTR_ERR(vdev); -+ pr_err("Device creation failed %d\n", ret); -+ goto err_dev; -+ } -+ -+ mbox_init(mailbox); -+ platform_set_drvdata(pdev, mailbox); -+ mbox_dev = dev; -+ -+ dev_info(dev, "mailbox at %p\n", mailbox->regs); -+ -+ return 0; -+ -+err_dev: -+ class_destroy(vcio_class); -+err_class: -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ mbox_dev = NULL; -+ platform_set_drvdata(pdev, NULL); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm_vcio_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-vcio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = bcm_vcio_of_match_table, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ return platform_driver_register(&bcm_mbox_driver); -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -diff --git a/include/linux/platform_data/mailbox-bcm2708.h b/include/linux/platform_data/mailbox-bcm2708.h -new file mode 100644 -index 0000000..cc284ed ---- /dev/null -+++ b/include/linux/platform_data/mailbox-bcm2708.h -@@ -0,0 +1,126 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#ifndef _PLAT_MAILBOX_BCM2708_H -+#define _PLAT_MAILBOX_BCM2708_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+ -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+ -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+int bcm_mailbox_read(unsigned chan, uint32_t *data28); -+int bcm_mailbox_write(unsigned chan, uint32_t data28); -+int bcm_mailbox_property(void *data, int size); -+ -+#endif - -From 1e5c7135fc145addcf195d02759a45e162f2daac Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 19:11:58 +0200 -Subject: [PATCH 144/216] BCM270x: power: Change initcall level to subsys -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Load ordering of modules are determined by the initcall used. -If it's the same initcall level, makefile ordering decides. -Now that the mailbox driver is being moved, it's no longer -placed before the power driver by the linker. -So use a later initcall level to let the mailbox driver -load first. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/power.c | 6 +++++- - arch/arm/mach-bcm2709/power.c | 6 +++++- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -index 2696be9..0db355d 100644 ---- a/arch/arm/mach-bcm2708/power.c -+++ b/arch/arm/mach-bcm2708/power.c -@@ -189,7 +189,11 @@ static void __exit bcm_power_exit(void) - bcm_mailbox_write(MBOX_CHAN_POWER, 0); - } - --arch_initcall(bcm_power_init); /* Initialize early */ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); - module_exit(bcm_power_exit); - - MODULE_AUTHOR("Phil Elwell"); -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -index 3421057..88c1e28 100644 ---- a/arch/arm/mach-bcm2709/power.c -+++ b/arch/arm/mach-bcm2709/power.c -@@ -187,7 +187,11 @@ static void __exit bcm_power_exit(void) - bcm_mailbox_write(MBOX_CHAN_POWER, 0); - } - --arch_initcall(bcm_power_init); /* Initialize early */ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); - module_exit(bcm_power_exit); - - MODULE_AUTHOR("Phil Elwell"); - -From 41e80f86dc78015856087cccd8e4f9a251042f9d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:34:26 +0200 -Subject: [PATCH 145/216] BCM270x: Use bcm2708-vcio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use bcm2708-vcio instead of the arch version. -Change affected drivers to use linux/platform_data/mailbox-bcm2708.h - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/power.c | 2 +- - arch/arm/mach-bcm2708/vc_mem.c | 2 +- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/power.c | 2 +- - arch/arm/mach-bcm2709/vc_mem.c | 2 +- - arch/arm/mach-bcm2709/vc_support.c | 2 +- - drivers/cpufreq/bcm2835-cpufreq.c | 2 +- - drivers/hwmon/bcm2835-hwmon.c | 2 +- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- - drivers/thermal/bcm2835-thermal.c | 2 +- - drivers/video/fbdev/bcm2708_fb.c | 2 +- - 14 files changed, 16 insertions(+), 12 deletions(-) - mode change 100755 => 100644 arch/arm/mach-bcm2709/vc_support.c - mode change 100755 => 100644 drivers/cpufreq/bcm2835-cpufreq.c - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 367a04a..ff87581 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1052,6 +1052,8 @@ CONFIG_FB_TFT_UPD161704=m - CONFIG_FB_TFT_WATTEROTT=m - CONFIG_FB_FLEX=m - CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXTCON=m - CONFIG_EXTCON_ARIZONA=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index db287f3..e339979 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1045,6 +1045,8 @@ CONFIG_FB_TFT_UPD161704=m - CONFIG_FB_TFT_WATTEROTT=m - CONFIG_FB_FLEX=m - CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXTCON=m - CONFIG_EXTCON_ARIZONA=m -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 454408c..c1e7d41 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -index 0db355d..796837f 100644 ---- a/arch/arm/mach-bcm2708/power.c -+++ b/arch/arm/mach-bcm2708/power.c -@@ -14,8 +14,8 @@ - #include - #include - #include -+#include - #include --#include - #include - - #define DRIVER_NAME "bcm2708_power" -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index 2982af7..226b737 100644 ---- a/arch/arm/mach-bcm2708/vc_mem.c -+++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_ARCH_KONA - #include -@@ -31,7 +32,6 @@ - #endif - - #include "mach/vc_mem.h" --#include - - #define DRIVER_NAME "vc-mem" - -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index f07c38b..77b8429 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -index 88c1e28..960e472 100644 ---- a/arch/arm/mach-bcm2709/power.c -+++ b/arch/arm/mach-bcm2709/power.c -@@ -14,8 +14,8 @@ - #include - #include - #include -+#include - #include --#include - #include - - #define DRIVER_NAME "bcm2708_power" -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -index ac578db..d2adfd1 100644 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ b/arch/arm/mach-bcm2709/vc_mem.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_ARCH_KONA - #include -@@ -31,7 +32,6 @@ - #endif - - #include "mach/vc_mem.h" --#include - - #define DRIVER_NAME "vc-mem" - -diff --git a/arch/arm/mach-bcm2709/vc_support.c b/arch/arm/mach-bcm2709/vc_support.c -old mode 100755 -new mode 100644 -index 0bc41c4..c4dc7d6 ---- a/arch/arm/mach-bcm2709/vc_support.c -+++ b/arch/arm/mach-bcm2709/vc_support.c -@@ -6,7 +6,7 @@ - */ - - #include --#include -+#include - - #ifdef ECLIPSE_IGNORE - -diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -old mode 100755 -new mode 100644 -index 447ca09..6735da9 ---- a/drivers/cpufreq/bcm2835-cpufreq.c -+++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -26,7 +26,7 @@ - #include - #include - #include --#include -+#include - - /* ---------- DEFINES ---------- */ - /*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */ -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -index 5bbed45..d14502c 100644 ---- a/drivers/hwmon/bcm2835-hwmon.c -+++ b/drivers/hwmon/bcm2835-hwmon.c -@@ -17,9 +17,9 @@ - #include - #include - #include -+#include - #include - #include --#include - #include - #include - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 8ec88bb..70e5086 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -40,13 +40,13 @@ - #include - #include - #include -+#include - #include - #include - - #include - - #include --#include - - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - -diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c -index 85fceb5..0c556d1 100644 ---- a/drivers/thermal/bcm2835-thermal.c -+++ b/drivers/thermal/bcm2835-thermal.c -@@ -15,10 +15,10 @@ - #include - #include - #include -+#include - #include - #include - #include --#include - #include - - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 52e655a..345c15e 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,7 +33,6 @@ - - #include - #include --#include - - #include - #include - -From 5bb0a0c80fc46ae0edea87f97244f28fb167dfe0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:35:07 +0200 -Subject: [PATCH 146/216] BCM270x: Remove arch driver vcio.c -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove the arch vcio.c driver and header file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 128 -------- - arch/arm/mach-bcm2708/vcio.c | 419 -------------------------- - arch/arm/mach-bcm2709/include/mach/vcio.h | 165 ---------- - arch/arm/mach-bcm2709/vcio.c | 484 ------------------------------ - 4 files changed, 1196 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h - delete mode 100644 arch/arm/mach-bcm2708/vcio.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vcio.h - delete mode 100644 arch/arm/mach-bcm2709/vcio.c - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -deleted file mode 100644 -index 95ad121..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ /dev/null -@@ -1,128 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vcio.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- */ --#ifndef _MACH_BCM2708_VCIO_H --#define _MACH_BCM2708_VCIO_H -- --/* Routines to handle I/O via the VideoCore "ARM control" registers -- * (semaphores, doorbells, mailboxes) -- */ -- --/* Constants shared with the ARM identifying separate mailbox channels */ --#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ --#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ --#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ --#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ --#define MBOX_CHAN_COUNT 9 -- --enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 --}; -- --enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 --}; -- --/* Mailbox property tags */ --enum { -- VCMSG_PROPERTY_END = 0x00000000, -- VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -- VCMSG_GET_BOARD_MODEL = 0x00010001, -- VCMSG_GET_BOARD_REVISION = 0x00010002, -- VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -- VCMSG_GET_BOARD_SERIAL = 0x00010004, -- VCMSG_GET_ARM_MEMORY = 0x00010005, -- VCMSG_GET_VC_MEMORY = 0x00010006, -- VCMSG_GET_CLOCKS = 0x00010007, -- VCMSG_GET_COMMAND_LINE = 0x00050001, -- VCMSG_GET_DMA_CHANNELS = 0x00060001, -- VCMSG_GET_POWER_STATE = 0x00020001, -- VCMSG_GET_TIMING = 0x00020002, -- VCMSG_SET_POWER_STATE = 0x00028001, -- VCMSG_GET_CLOCK_STATE = 0x00030001, -- VCMSG_SET_CLOCK_STATE = 0x00038001, -- VCMSG_GET_CLOCK_RATE = 0x00030002, -- VCMSG_SET_CLOCK_RATE = 0x00038002, -- VCMSG_GET_VOLTAGE = 0x00030003, -- VCMSG_SET_VOLTAGE = 0x00038003, -- VCMSG_GET_MAX_CLOCK = 0x00030004, -- VCMSG_GET_MAX_VOLTAGE = 0x00030005, -- VCMSG_GET_TEMPERATURE = 0x00030006, -- VCMSG_GET_MIN_CLOCK = 0x00030007, -- VCMSG_GET_MIN_VOLTAGE = 0x00030008, -- VCMSG_GET_TURBO = 0x00030009, -- VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -- VCMSG_GET_STC = 0x0003000b, -- VCMSG_SET_TURBO = 0x00038009, -- VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -- VCMSG_SET_LOCK_MEM = 0x0003000d, -- VCMSG_SET_UNLOCK_MEM = 0x0003000e, -- VCMSG_SET_RELEASE_MEM = 0x0003000f, -- VCMSG_SET_EXECUTE_CODE = 0x00030010, -- VCMSG_SET_EXECUTE_QPU = 0x00030011, -- VCMSG_SET_ENABLE_QPU = 0x00030012, -- VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -- VCMSG_GET_EDID_BLOCK = 0x00030020, -- VCMSG_GET_CUSTOMER_OTP = 0x00030021, -- VCMSG_SET_CUSTOMER_OTP = 0x00038021, -- VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -- VCMSG_SET_RELEASE_BUFFER = 0x00048001, -- VCMSG_SET_BLANK_SCREEN = 0x00040002, -- VCMSG_TST_BLANK_SCREEN = 0x00044002, -- VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -- VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -- VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -- VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -- VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -- VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -- VCMSG_GET_DEPTH = 0x00040005, -- VCMSG_TST_DEPTH = 0x00044005, -- VCMSG_SET_DEPTH = 0x00048005, -- VCMSG_GET_PIXEL_ORDER = 0x00040006, -- VCMSG_TST_PIXEL_ORDER = 0x00044006, -- VCMSG_SET_PIXEL_ORDER = 0x00048006, -- VCMSG_GET_ALPHA_MODE = 0x00040007, -- VCMSG_TST_ALPHA_MODE = 0x00044007, -- VCMSG_SET_ALPHA_MODE = 0x00048007, -- VCMSG_GET_PITCH = 0x00040008, -- VCMSG_TST_PITCH = 0x00044008, -- VCMSG_SET_PITCH = 0x00048008, -- VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -- VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -- VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -- VCMSG_GET_OVERSCAN = 0x0004000a, -- VCMSG_TST_OVERSCAN = 0x0004400a, -- VCMSG_SET_OVERSCAN = 0x0004800a, -- VCMSG_GET_PALETTE = 0x0004000b, -- VCMSG_TST_PALETTE = 0x0004400b, -- VCMSG_SET_PALETTE = 0x0004800b, -- VCMSG_GET_LAYER = 0x0004000c, -- VCMSG_TST_LAYER = 0x0004400c, -- VCMSG_SET_LAYER = 0x0004800c, -- VCMSG_GET_TRANSFORM = 0x0004000d, -- VCMSG_TST_TRANSFORM = 0x0004400d, -- VCMSG_SET_TRANSFORM = 0x0004800d, -- VCMSG_TST_VSYNC = 0x0004400e, -- VCMSG_SET_VSYNC = 0x0004800e, -- VCMSG_SET_CURSOR_INFO = 0x00008010, -- VCMSG_SET_CURSOR_STATE = 0x00008011, --}; -- --extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); --extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); --extern int /*rc*/ bcm_mailbox_property(void *data, int size); -- --#endif -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -deleted file mode 100644 -index c4c2bcd..0000000 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ /dev/null -@@ -1,419 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/vcio.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for writing to the mailboxes, -- * semaphores, doorbells etc. that are shared between the ARM and the -- * VideoCore processor -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#define DRIVER_NAME "bcm2708_vcio" --#define DEVICE_FILE_NAME "vcio" -- --/* offsets from a mail box base address */ --#define MAIL0_RD 0x00 /* read - and next 4 words */ --#define MAIL0_POL 0x10 /* read without popping the fifo */ --#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL0_STA 0x18 /* status */ --#define MAIL0_CNF 0x1C /* configuration */ --#define MAIL1_WRT 0x20 /* write - and next 4 words */ -- --#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) --#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) --#define MBOX_CHAN(msg) ((msg) & 0xf) --#define MBOX_DATA28(msg) ((msg) & ~0xf) --#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -- --#define MBOX_MAGIC 0xd0d0c0de -- --#define MAJOR_NUM 100 --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -- --static struct class *vcio_class; -- --struct vc_mailbox { -- void __iomem *regs; -- uint32_t msg[MBOX_CHAN_COUNT]; -- struct semaphore sema[MBOX_CHAN_COUNT]; -- uint32_t magic; --}; -- --static void mbox_init(struct vc_mailbox *mbox_out) --{ -- int i; -- -- for (i = 0; i < MBOX_CHAN_COUNT; i++) { -- mbox_out->msg[i] = 0; -- sema_init(&mbox_out->sema[i], 0); -- } -- -- /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); -- -- mbox_out->magic = MBOX_MAGIC; --} -- --static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) --{ -- if (mbox->magic != MBOX_MAGIC) -- return -EINVAL; -- -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -- cpu_relax(); -- -- writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); -- -- return 0; --} -- --static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) --{ -- if (mbox->magic != MBOX_MAGIC) -- return -EINVAL; -- -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- -- return 0; --} -- --static irqreturn_t mbox_irq_handler(int irq, void *dev_id) --{ -- /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -- int status = readl(mbox->regs + MAIL0_STA); -- int ret = IRQ_NONE; -- -- while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->regs + MAIL0_RD); -- int chan = MBOX_CHAN(msg); -- -- if (chan < MBOX_CHAN_COUNT) { -- if (mbox->msg[chan]) { -- pr_err(DRIVER_NAME -- ": mbox chan %d overflow - drop %08x\n", -- chan, msg); -- } else { -- mbox->msg[chan] = (msg | 0xf); -- up(&mbox->sema[chan]); -- } -- } else { -- pr_err(DRIVER_NAME -- ": invalid channel selector (msg %08x)\n", msg); -- } -- ret = IRQ_HANDLED; -- status = readl(mbox->regs + MAIL0_STA); -- } -- return ret; --} -- --/* Mailbox Methods */ -- --static struct device *mbox_dev; /* we assume there's only one! */ -- --static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) --{ -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- int rc; -- -- device_lock(dev); -- rc = mbox_write(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) --{ -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- int rc; -- -- device_lock(dev); -- rc = mbox_read(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --extern int bcm_mailbox_write(unsigned chan, uint32_t data28) --{ -- if (!mbox_dev) -- return -ENODEV; -- -- return dev_mbox_write(mbox_dev, chan, data28); --} --EXPORT_SYMBOL_GPL(bcm_mailbox_write); -- --extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) --{ -- if (!mbox_dev) -- return -ENODEV; -- -- return dev_mbox_read(mbox_dev, chan, data28); --} --EXPORT_SYMBOL_GPL(bcm_mailbox_read); -- --static int mbox_copy_from_user(void *dst, const void *src, int size) --{ -- if ((uint32_t)src < TASK_SIZE) -- return copy_from_user(dst, src, size); -- -- memcpy(dst, src, size); -- -- return 0; --} -- --static int mbox_copy_to_user(void *dst, const void *src, int size) --{ -- if ((uint32_t)dst < TASK_SIZE) -- return copy_to_user(dst, src, size); -- -- memcpy(dst, src, size); -- -- return 0; --} -- --static DEFINE_MUTEX(mailbox_lock); --extern int bcm_mailbox_property(void *data, int size) --{ -- uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -- int s = 0; -- -- mutex_lock(&mailbox_lock); -- /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -- GFP_ATOMIC); -- if (mem_kern) { -- /* create the message */ -- mbox_copy_from_user(mem_kern, data, size); -- -- /* send the message */ -- wmb(); -- s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) -- s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- if (s == 0) { -- /* copy the response */ -- rmb(); -- mbox_copy_to_user(data, mem_kern, size); -- } -- dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -- } else { -- s = -ENOMEM; -- } -- if (s != 0) -- pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); -- -- mutex_unlock(&mailbox_lock); -- return s; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_property); -- --/* Platform Device for Mailbox */ -- --/* -- * Is the device open right now? Used to prevent -- * concurent access into the same device -- */ --static bool device_is_open; -- --/* This is called whenever a process attempts to open the device file */ --static int device_open(struct inode *inode, struct file *file) --{ -- /* We don't want to talk to two processes at the same time */ -- if (device_is_open) -- return -EBUSY; -- -- device_is_open = true; -- try_module_get(THIS_MODULE); -- -- return 0; --} -- --static int device_release(struct inode *inode, struct file *file) --{ -- /* We're now ready for our next caller */ -- device_is_open = false; -- -- module_put(THIS_MODULE); -- -- return 0; --} -- --/* -- * This function is called whenever a process tries to do an ioctl on our -- * device file. We get two extra parameters (additional to the inode and file -- * structures, which all device functions get): the number of the ioctl called -- * and the parameter given to the ioctl function. -- * -- * If the ioctl is write or read/write (meaning output is returned to the -- * calling process), the ioctl call returns the output of this function. -- * -- */ --static long device_ioctl(struct file *file, unsigned int ioctl_num, -- unsigned long ioctl_param) --{ -- unsigned size; -- -- switch (ioctl_num) { -- case IOCTL_MBOX_PROPERTY: -- /* -- * Receive a pointer to a message (in user space) and set that -- * to be the device's message. Get the parameter given to -- * ioctl by the process. -- */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); -- return bcm_mailbox_property((void *)ioctl_param, size); -- default: -- pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -- return -EINVAL; -- } -- -- return 0; --} -- --/* Module Declarations */ -- --/* -- * This structure will hold the functions to be called -- * when a process does something to the device we -- * created. Since a pointer to this structure is kept in -- * the devices table, it can't be local to -- * init_module. NULL is for unimplemented functios. -- */ --const struct file_operations fops = { -- .unlocked_ioctl = device_ioctl, -- .open = device_open, -- .release = device_release, /* a.k.a. close */ --}; -- --static int bcm_vcio_probe(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- struct device *vdev; -- struct vc_mailbox *mailbox; -- struct resource *res; -- int irq, ret; -- -- mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -- if (!mailbox) -- return -ENOMEM; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- mailbox->regs = devm_ioremap_resource(dev, res); -- if (IS_ERR(mailbox->regs)) -- return PTR_ERR(mailbox->regs); -- -- irq = platform_get_irq(pdev, 0); -- ret = devm_request_irq(dev, irq, mbox_irq_handler, -- IRQF_DISABLED | IRQF_IRQPOLL, -- dev_name(dev), mailbox); -- if (ret) { -- dev_err(dev, "Interrupt request failed %d\n", ret); -- return ret; -- } -- -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- if (ret < 0) { -- pr_err("Character device registration failed %d\n", ret); -- return ret; -- } -- -- vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- pr_err("Class creation failed %d\n", ret); -- goto err_class; -- } -- -- vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -- if (IS_ERR(vdev)) { -- ret = PTR_ERR(vdev); -- pr_err("Device creation failed %d\n", ret); -- goto err_dev; -- } -- -- mbox_init(mailbox); -- platform_set_drvdata(pdev, mailbox); -- mbox_dev = dev; -- -- dev_info(dev, "mailbox at %p\n", mailbox->regs); -- -- return 0; -- --err_dev: -- class_destroy(vcio_class); --err_class: -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- -- return ret; --} -- --static int bcm_vcio_remove(struct platform_device *pdev) --{ -- mbox_dev = NULL; -- platform_set_drvdata(pdev, NULL); -- device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- -- return 0; --} -- --static const struct of_device_id bcm_vcio_of_match_table[] = { -- { .compatible = "brcm,bcm2708-vcio", }, -- {}, --}; --MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -- --static struct platform_driver bcm_mbox_driver = { -- .probe = bcm_vcio_probe, -- .remove = bcm_vcio_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- .of_match_table = bcm_vcio_of_match_table, -- }, --}; -- --static int __init bcm_mbox_init(void) --{ -- return platform_driver_register(&bcm_mbox_driver); --} -- --static void __exit bcm_mbox_exit(void) --{ -- platform_driver_unregister(&bcm_mbox_driver); --} -- --arch_initcall(bcm_mbox_init); /* Initialize early */ --module_exit(bcm_mbox_exit); -- --MODULE_AUTHOR("Gray Girling"); --MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); --MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2709/include/mach/vcio.h b/arch/arm/mach-bcm2709/include/mach/vcio.h -deleted file mode 100644 -index 8e11d67e..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/vcio.h -+++ /dev/null -@@ -1,165 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vcio.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef _MACH_BCM2708_VCIO_H --#define _MACH_BCM2708_VCIO_H -- --/* Routines to handle I/O via the VideoCore "ARM control" registers -- * (semaphores, doorbells, mailboxes) -- */ -- --#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -- --/* Constants shared with the ARM identifying separate mailbox channels */ --#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ --#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ --#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ --#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ --#define MBOX_CHAN_COUNT 9 -- --enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 --}; --enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 --}; --/* Mailbox property tags */ --enum { -- VCMSG_PROPERTY_END = 0x00000000, -- VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -- VCMSG_GET_BOARD_MODEL = 0x00010001, -- VCMSG_GET_BOARD_REVISION = 0x00010002, -- VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -- VCMSG_GET_BOARD_SERIAL = 0x00010004, -- VCMSG_GET_ARM_MEMORY = 0x00010005, -- VCMSG_GET_VC_MEMORY = 0x00010006, -- VCMSG_GET_CLOCKS = 0x00010007, -- VCMSG_GET_COMMAND_LINE = 0x00050001, -- VCMSG_GET_DMA_CHANNELS = 0x00060001, -- VCMSG_GET_POWER_STATE = 0x00020001, -- VCMSG_GET_TIMING = 0x00020002, -- VCMSG_SET_POWER_STATE = 0x00028001, -- VCMSG_GET_CLOCK_STATE = 0x00030001, -- VCMSG_SET_CLOCK_STATE = 0x00038001, -- VCMSG_GET_CLOCK_RATE = 0x00030002, -- VCMSG_SET_CLOCK_RATE = 0x00038002, -- VCMSG_GET_VOLTAGE = 0x00030003, -- VCMSG_SET_VOLTAGE = 0x00038003, -- VCMSG_GET_MAX_CLOCK = 0x00030004, -- VCMSG_GET_MAX_VOLTAGE = 0x00030005, -- VCMSG_GET_TEMPERATURE = 0x00030006, -- VCMSG_GET_MIN_CLOCK = 0x00030007, -- VCMSG_GET_MIN_VOLTAGE = 0x00030008, -- VCMSG_GET_TURBO = 0x00030009, -- VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -- VCMSG_GET_STC = 0x0003000b, -- VCMSG_SET_TURBO = 0x00038009, -- VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -- VCMSG_SET_LOCK_MEM = 0x0003000d, -- VCMSG_SET_UNLOCK_MEM = 0x0003000e, -- VCMSG_SET_RELEASE_MEM = 0x0003000f, -- VCMSG_SET_EXECUTE_CODE = 0x00030010, -- VCMSG_SET_EXECUTE_QPU = 0x00030011, -- VCMSG_SET_ENABLE_QPU = 0x00030012, -- VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -- VCMSG_GET_EDID_BLOCK = 0x00030020, -- VCMSG_GET_CUSTOMER_OTP = 0x00030021, -- VCMSG_SET_CUSTOMER_OTP = 0x00038021, -- VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -- VCMSG_SET_RELEASE_BUFFER = 0x00048001, -- VCMSG_SET_BLANK_SCREEN = 0x00040002, -- VCMSG_TST_BLANK_SCREEN = 0x00044002, -- VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -- VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -- VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -- VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -- VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -- VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -- VCMSG_GET_DEPTH = 0x00040005, -- VCMSG_TST_DEPTH = 0x00044005, -- VCMSG_SET_DEPTH = 0x00048005, -- VCMSG_GET_PIXEL_ORDER = 0x00040006, -- VCMSG_TST_PIXEL_ORDER = 0x00044006, -- VCMSG_SET_PIXEL_ORDER = 0x00048006, -- VCMSG_GET_ALPHA_MODE = 0x00040007, -- VCMSG_TST_ALPHA_MODE = 0x00044007, -- VCMSG_SET_ALPHA_MODE = 0x00048007, -- VCMSG_GET_PITCH = 0x00040008, -- VCMSG_TST_PITCH = 0x00044008, -- VCMSG_SET_PITCH = 0x00048008, -- VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -- VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -- VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -- VCMSG_GET_OVERSCAN = 0x0004000a, -- VCMSG_TST_OVERSCAN = 0x0004400a, -- VCMSG_SET_OVERSCAN = 0x0004800a, -- VCMSG_GET_PALETTE = 0x0004000b, -- VCMSG_TST_PALETTE = 0x0004400b, -- VCMSG_SET_PALETTE = 0x0004800b, -- VCMSG_GET_LAYER = 0x0004000c, -- VCMSG_TST_LAYER = 0x0004400c, -- VCMSG_SET_LAYER = 0x0004800c, -- VCMSG_GET_TRANSFORM = 0x0004000d, -- VCMSG_TST_TRANSFORM = 0x0004400d, -- VCMSG_SET_TRANSFORM = 0x0004800d, -- VCMSG_TST_VSYNC = 0x0004400e, -- VCMSG_SET_VSYNC = 0x0004800e, -- VCMSG_SET_CURSOR_INFO = 0x00008010, -- VCMSG_SET_CURSOR_STATE = 0x00008011, --}; -- --extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); --extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); --extern int /*rc*/ bcm_mailbox_property(void *data, int size); -- --#include -- --/* -- * The major device number. We can't rely on dynamic -- * registration any more, because ioctls need to know -- * it. -- */ --#define MAJOR_NUM 100 -- --/* -- * Set the message of the device driver -- */ --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) --/* -- * _IOWR means that we're creating an ioctl command -- * number for passing information from a user process -- * to the kernel module and from the kernel module to user process -- * -- * The first arguments, MAJOR_NUM, is the major device -- * number we're using. -- * -- * The second argument is the number of the command -- * (there could be several with different meanings). -- * -- * The third argument is the type we want to get from -- * the process to the kernel. -- */ -- --/* -- * The name of the device file -- */ --#define DEVICE_FILE_NAME "vcio" -- --#endif -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -deleted file mode 100644 -index 700bff4..0000000 ---- a/arch/arm/mach-bcm2709/vcio.c -+++ /dev/null -@@ -1,484 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/vcio.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for writing to the mailboxes, -- * semaphores, doorbells etc. that are shared between the ARM and the -- * VideoCore processor -- */ -- --#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) --#define SUPPORT_SYSRQ --#endif -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include --#include -- --#include -- -- --#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -- --/* ---------------------------------------------------------------------- -- * Mailbox -- * -------------------------------------------------------------------- */ -- --/* offsets from a mail box base address */ --#define MAIL_WRT 0x00 /* write - and next 4 words */ --#define MAIL_RD 0x00 /* read - and next 4 words */ --#define MAIL_POL 0x10 /* read without popping the fifo */ --#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL_STA 0x18 /* status */ --#define MAIL_CNF 0x1C /* configuration */ -- --#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) --#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) --#define MBOX_CHAN(msg) ((msg) & 0xf) --#define MBOX_DATA28(msg) ((msg) & ~0xf) --#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -- --#define MBOX_MAGIC 0xd0d0c0de --static struct class *vcio_class = NULL; --struct vc_mailbox { -- struct device *dev; /* parent device */ -- void __iomem *status; -- void __iomem *config; -- void __iomem *read; -- void __iomem *write; -- uint32_t msg[MBOX_CHAN_COUNT]; -- struct semaphore sema[MBOX_CHAN_COUNT]; -- uint32_t magic; --}; -- --static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -- uint32_t addr_mbox) --{ -- int i; -- -- mbox_out->dev = dev; -- mbox_out->status = __io_address(addr_mbox + MAIL_STA); -- mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -- mbox_out->read = __io_address(addr_mbox + MAIL_RD); -- /* Write to the other mailbox */ -- mbox_out->write = -- __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -- MAIL_WRT); -- -- for (i = 0; i < MBOX_CHAN_COUNT; i++) { -- mbox_out->msg[i] = 0; -- sema_init(&mbox_out->sema[i], 0); -- } -- -- /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -- -- mbox_out->magic = MBOX_MAGIC; --} -- --static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) --{ -- int rc; -- -- if (mbox->magic != MBOX_MAGIC) -- rc = -EINVAL; -- else { -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -- cpu_relax(); -- -- writel(MBOX_MSG(chan, data28), mbox->write); -- rc = 0; -- } -- return rc; --} -- --static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) --{ -- int rc; -- -- if (mbox->magic != MBOX_MAGIC) -- rc = -EINVAL; -- else { -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- rc = 0; -- } -- return rc; --} -- --static irqreturn_t mbox_irq(int irq, void *dev_id) --{ -- /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -- int status = readl(mbox->status); -- int ret = IRQ_NONE; -- -- while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->read); -- int chan = MBOX_CHAN(msg); -- if (chan < MBOX_CHAN_COUNT) { -- if (mbox->msg[chan]) { -- /* Overflow */ -- printk(KERN_ERR DRIVER_NAME -- ": mbox chan %d overflow - drop %08x\n", -- chan, msg); -- } else { -- mbox->msg[chan] = (msg | 0xf); -- up(&mbox->sema[chan]); -- } -- } else { -- printk(KERN_ERR DRIVER_NAME -- ": invalid channel selector (msg %08x)\n", msg); -- } -- ret = IRQ_HANDLED; -- status = readl(mbox->status); -- } -- return ret; --} -- --static struct irqaction mbox_irqaction = { -- .name = "ARM Mailbox IRQ", -- .flags = IRQF_DISABLED | IRQF_IRQPOLL, -- .handler = mbox_irq, --}; -- --/* ---------------------------------------------------------------------- -- * Mailbox Methods -- * -------------------------------------------------------------------- */ -- --static struct device *mbox_dev; /* we assume there's only one! */ -- --static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) --{ -- int rc; -- -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- device_lock(dev); -- rc = mbox_write(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) --{ -- int rc; -- -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- device_lock(dev); -- rc = mbox_read(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --extern int bcm_mailbox_write(unsigned chan, uint32_t data28) --{ -- if (mbox_dev) -- return dev_mbox_write(mbox_dev, chan, data28); -- else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_write); -- --extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) --{ -- if (mbox_dev) -- return dev_mbox_read(mbox_dev, chan, data28); -- else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_read); -- --static void dev_mbox_register(const char *dev_name, struct device *dev) --{ -- mbox_dev = dev; --} -- --static int mbox_copy_from_user(void *dst, const void *src, int size) --{ -- if ( (uint32_t)src < TASK_SIZE) -- { -- return copy_from_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } --} -- --static int mbox_copy_to_user(void *dst, const void *src, int size) --{ -- if ( (uint32_t)dst < TASK_SIZE) -- { -- return copy_to_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } --} -- --static DEFINE_MUTEX(mailbox_lock); --extern int bcm_mailbox_property(void *data, int size) --{ -- uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -- int s = 0; -- -- mutex_lock(&mailbox_lock); -- /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -- if (mem_kern) { -- /* create the message */ -- mbox_copy_from_user(mem_kern, data, size); -- -- /* send the message */ -- wmb(); -- s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) { -- s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- } -- if (s == 0) { -- /* copy the response */ -- rmb(); -- mbox_copy_to_user(data, mem_kern, size); -- } -- dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -- } else { -- s = -ENOMEM; -- } -- if (s != 0) -- printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -- -- mutex_unlock(&mailbox_lock); -- return s; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_property); -- --/* ---------------------------------------------------------------------- -- * Platform Device for Mailbox -- * -------------------------------------------------------------------- */ -- --/* -- * Is the device open right now? Used to prevent -- * concurent access into the same device -- */ --static int Device_Open = 0; -- --/* -- * This is called whenever a process attempts to open the device file -- */ --static int device_open(struct inode *inode, struct file *file) --{ -- /* -- * We don't want to talk to two processes at the same time -- */ -- if (Device_Open) -- return -EBUSY; -- -- Device_Open++; -- /* -- * Initialize the message -- */ -- try_module_get(THIS_MODULE); -- return 0; --} -- --static int device_release(struct inode *inode, struct file *file) --{ -- /* -- * We're now ready for our next caller -- */ -- Device_Open--; -- -- module_put(THIS_MODULE); -- return 0; --} -- --/* -- * This function is called whenever a process tries to do an ioctl on our -- * device file. We get two extra parameters (additional to the inode and file -- * structures, which all device functions get): the number of the ioctl called -- * and the parameter given to the ioctl function. -- * -- * If the ioctl is write or read/write (meaning output is returned to the -- * calling process), the ioctl call returns the output of this function. -- * -- */ --static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -- unsigned int ioctl_num, /* number and param for ioctl */ -- unsigned long ioctl_param) --{ -- unsigned size; -- /* -- * Switch according to the ioctl called -- */ -- switch (ioctl_num) { -- case IOCTL_MBOX_PROPERTY: -- /* -- * Receive a pointer to a message (in user space) and set that -- * to be the device's message. Get the parameter given to -- * ioctl by the process. -- */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -- return bcm_mailbox_property((void *)ioctl_param, size); -- break; -- default: -- printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -- return -EINVAL; -- } -- -- return 0; --} -- --/* Module Declarations */ -- --/* -- * This structure will hold the functions to be called -- * when a process does something to the device we -- * created. Since a pointer to this structure is kept in -- * the devices table, it can't be local to -- * init_module. NULL is for unimplemented functios. -- */ --struct file_operations fops = { -- .unlocked_ioctl = device_ioctl, -- .open = device_open, -- .release = device_release, /* a.k.a. close */ --}; -- --static int bcm_vcio_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_mailbox *mailbox; -- -- mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (NULL == mailbox) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "mailbox memory\n"); -- ret = -ENOMEM; -- } else { -- struct resource *res; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- kfree(mailbox); -- } else { -- /* should be based on the registers from res really */ -- mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -- -- platform_set_drvdata(pdev, mailbox); -- dev_mbox_register(DRIVER_NAME, &pdev->dev); -- -- mbox_irqaction.dev_id = mailbox; -- setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -- } -- } -- -- if (ret == 0) { -- /* -- * Register the character device -- */ -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- -- /* -- * Negative values signify an error -- */ -- if (ret < 0) { -- printk(KERN_ERR DRIVER_NAME -- "Failed registering the character device %d\n", ret); -- return ret; -- } -- vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret ; -- } -- device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -- } -- return ret; --} -- --static int bcm_vcio_remove(struct platform_device *pdev) --{ -- struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- kfree(mailbox); -- -- return 0; --} -- --static struct platform_driver bcm_mbox_driver = { -- .probe = bcm_vcio_probe, -- .remove = bcm_vcio_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --static int __init bcm_mbox_init(void) --{ -- int ret; -- -- printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -- -- ret = platform_driver_register(&bcm_mbox_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_mbox_exit(void) --{ -- device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- platform_driver_unregister(&bcm_mbox_driver); --} -- --arch_initcall(bcm_mbox_init); /* Initialize early */ --module_exit(bcm_mbox_exit); -- --MODULE_AUTHOR("Gray Girling"); --MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); --MODULE_LICENSE("GPL"); --MODULE_ALIAS("platform:bcm-mbox"); - -From ca452e4734877d6b36d1a836d473b81f3d561c3f Mon Sep 17 00:00:00 2001 + CONFIG_EXT2_FS_POSIX_ACL=y +@@ -107,18 +1073,110 @@ CONFIG_EXT3_FS=y + CONFIG_EXT3_FS_POSIX_ACL=y + CONFIG_EXT4_FS=y + CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m + CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m + CONFIG_MSDOS_FS=y + CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y + CONFIG_TMPFS=y + CONFIG_TMPFS_POSIX_ACL=y +-# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_CONFIGFS_FS=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_F2FS_FS=y + CONFIG_NFS_FS=y +-CONFIG_NFSD=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" + CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m + CONFIG_NLS_ASCII=y +-CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m + CONFIG_NLS_UTF8=y ++CONFIG_DLM=m + CONFIG_PRINTK_TIME=y + CONFIG_BOOT_PRINTK_DELAY=y + CONFIG_DYNAMIC_DEBUG=y +@@ -128,14 +1186,38 @@ CONFIG_DEBUG_INFO=y + CONFIG_UNUSED_SYMBOLS=y + CONFIG_DEBUG_MEMORY_INIT=y + CONFIG_LOCKUP_DETECTOR=y ++CONFIG_TIMER_STATS=y ++# CONFIG_DEBUG_PREEMPT is not set ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y + CONFIG_SCHED_TRACER=y + CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set + CONFIG_FUNCTION_PROFILER=y + CONFIG_TEST_KSTRTOX=y + CONFIG_KGDB=y + CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y + CONFIG_STRICT_DEVMEM=y + CONFIG_DEBUG_LL=y + CONFIG_EARLY_PRINTK=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CRYPTD=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y + # CONFIG_XZ_DEC_ARM is not set + # CONFIG_XZ_DEC_ARMTHUMB is not set + +From 4e2ed4a7a7971ea763017bc6234d30cdc5bfb984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 23:00:15 +0200 -Subject: [PATCH 147/216] BCM270x_DT: Add mailbox bcm2708-vcio +Subject: [PATCH 69/77] BCM270x_DT: Add mailbox bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -140552,193 +132264,41 @@ platform device when booting in DT mode. Signed-off-by: Noralf Trønnes --- - arch/arm/boot/dts/bcm2708_common.dtsi | 6 ++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 3 files changed, 8 insertions(+), 2 deletions(-) + arch/arm/mach-bcm2708/bcm2708.c | 2 +- + arch/arm/mach-bcm2709/bcm2709.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 065a424..1c8c1af 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -36,6 +36,12 @@ - #interrupt-cells = <2>; - }; - -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2708-vcio"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ }; -+ - gpio: gpio { - compatible = "brcm,bcm2835-gpio"; - reg = <0x7e200000 0xb4>; diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 51f8efa..7cc47c1 100644 +index e42f5a5..de2f93a 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -908,7 +908,7 @@ void __init bcm2708_init(void) +@@ -870,7 +870,7 @@ void __init bcm2708_init(void) bcm2708_dt_init(); bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); - #endif diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8ed88b4..2c0a664 100644 +index 95223ff..350647a 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -929,7 +929,7 @@ void __init bcm2709_init(void) +@@ -890,7 +890,7 @@ void __init bcm2709_init(void) bcm2709_dt_init(); bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); - #endif -From 8cb40db6e93540a4cf0d45ee23eb9b0441050543 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 23:00:45 +0200 -Subject: [PATCH 148/216] bcm2835: bcm2835_defconfig enable BCM2708_MBOX -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the mailbox driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index cf2e7a6..26b4c75 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -99,6 +99,8 @@ CONFIG_LEDS_TRIGGER_CAMERA=y - CONFIG_DMADEVICES=y - CONFIG_DMA_BCM2708=y - CONFIG_STAGING=y -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT2_FS=y - CONFIG_EXT2_FS_XATTR=y - -From c03f517d41d6da89f70794d6bf20974e81ac72f1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 23:02:46 +0200 -Subject: [PATCH 149/216] bcm2835: Add mailbox bcm2708-vcio to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add mailbox to Device Tree. There are no kernel users yet, -but it's available to userspace. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f2dec21..06cba29 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -60,6 +60,12 @@ - reg = <0x7e104000 0x10>; - }; - -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2708-vcio"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ }; -+ - gpio: gpio@7e200000 { - compatible = "brcm,bcm2835-gpio"; - reg = <0x7e200000 0xb4>; - -From 2010049aa53c210156598c979fd38dc893baa049 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 12 May 2015 11:48:18 +0200 -Subject: [PATCH 150/216] mailbox: bcm2708-vcio: Allocation does not need to be - atomic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to do atomic allocation in a context that can sleep. - -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/bcm2708-vcio.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -index ee3e778..74a7fcb 100644 ---- a/drivers/mailbox/bcm2708-vcio.c -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -212,7 +212,7 @@ extern int bcm_mailbox_property(void *data, int size) - mutex_lock(&mailbox_lock); - /* allocate some memory for the messages communicating with GPU */ - mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -- GFP_ATOMIC); -+ GFP_KERNEL); - if (mem_kern) { - /* create the message */ - mbox_copy_from_user(mem_kern, data, size); - -From f86559819816a393e05426b6dac30d84582fa13d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 12 May 2015 13:45:32 +0200 -Subject: [PATCH 151/216] mailbox: bcm2708-vcio: Check the correct status - register before writing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With the VC reader blocked and the ARM writing, MAIL0_STA reads -empty permanently while MAIL1_STA goes from empty (0x40000000) -to non-empty (0x00000001-0x00000007) to full (0x80000008). - -Suggested-by: Phil Elwell -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/bcm2708-vcio.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -index 74a7fcb..19ecfe8 100644 ---- a/drivers/mailbox/bcm2708-vcio.c -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -35,6 +35,7 @@ - #define MAIL0_STA 0x18 /* status */ - #define MAIL0_CNF 0x1C /* configuration */ - #define MAIL1_WRT 0x20 /* write - and next 4 words */ -+#define MAIL1_STA 0x38 /* status */ - - /* On MACH_BCM270x these come through (arm_control.h ) */ - #ifndef ARM_MS_EMPTY -@@ -85,7 +86,7 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - return -EINVAL; - - /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -+ while (0 != (readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL)) - cpu_relax(); - - writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); - -From 94bbfc4066df94c006edec5a48fe4df6547a1b01 Mon Sep 17 00:00:00 2001 +From 2867da0a54803e6eb8e748b63a474877e16899b0 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 152/216] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 70/77] rpi-ft5406: Add touchscreen driver for pi LCD display --- drivers/input/touchscreen/Kconfig | 7 + @@ -140749,10 +132309,10 @@ Subject: [PATCH 152/216] rpi-ft5406: Add touchscreen driver for pi LCD display create mode 100644 drivers/input/touchscreen/rpi-ft5406.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 6261fd6..e7e9416 100644 +index 80f6386..5848562 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig -@@ -557,6 +557,13 @@ config TOUCHSCREEN_EDT_FT5X06 +@@ -583,6 +583,13 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. @@ -140767,10 +132327,10 @@ index 6261fd6..e7e9416 100644 tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index 0242fea..e0268f0 100644 +index 44deea7..a1be09f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o +@@ -29,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o @@ -141055,1985 +132615,10 @@ index cc284ed..d3ea839 100644 VCMSG_SET_CURSOR_STATE = 0x00008011, }; -From 7a6f093876247b186c1465ef0f45132b0c804af2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 7 May 2015 09:22:23 +0100 -Subject: [PATCH 153/216] bcm2835-sdhost: Error handling fix, and code - clarification - ---- - drivers/mmc/host/bcm2835-sdhost.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 0c311b5..542ae12 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -1041,13 +1041,14 @@ static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) - host->cmd->error = -EILSEQ; - - /* Use the block interrupt for writes after the first block */ -- if (!(host->data->flags & MMC_DATA_READ)) { -+ if (host->data->flags & MMC_DATA_WRITE) { - host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); - host->hcfg |= SDHCFG_BLOCK_IRPT_EN; - bcm2835_sdhost_write(host, host->hcfg, SDHCFG); - if (host->data->error) - bcm2835_sdhost_finish_data(host); -- bcm2835_sdhost_transfer_pio(host); -+ else -+ bcm2835_sdhost_transfer_pio(host); - } else { - if (!host->data->error) { - bcm2835_sdhost_transfer_pio(host); -@@ -1132,12 +1133,12 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) - bcm2835_sdhost_dumpregs(host); - } - -- if (loops) -- early |= handled; -- - if (!handled) - break; - -+ if (loops) -+ early |= handled; -+ - result = IRQ_HANDLED; - - /* Clear all interrupts and notifications */ - -From d502512774e7121bd6787008f5956daefa3ac138 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 14 May 2015 11:48:40 +0100 -Subject: [PATCH 154/216] bcm2835-sdhost: Adding overclocking option - -Allow a different clock speed to be substitued for a requested 50MHz. -This option is exposed using the "overclock_50" DT parameter. -Note that the sdhost interface is restricted to integer divisions of -core_freq, and the highest sensible option for a core_freq of 250MHz -is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too -high. - -Use at your own risk. ---- - arch/arm/boot/dts/sdhost-overlay.dts | 6 ++++-- - drivers/mmc/host/bcm2835-sdhost.c | 17 +++++++++++++++-- - 2 files changed, 19 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -index 33db96e..b2653e9 100644 ---- a/arch/arm/boot/dts/sdhost-overlay.dts -+++ b/arch/arm/boot/dts/sdhost-overlay.dts -@@ -13,14 +13,15 @@ - sdhost: sdhost@7e202000 { - compatible = "brcm,bcm2835-sdhost"; - reg = <0x7e202000 0x100>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; - interrupts = <2 24>; - clocks = <&clk_sdhost>; - dmas = <&dma 13>, - <&dma 13>; - dma-names = "tx", "rx"; - brcm,delay-after-stop = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&sdhost_pins>; -+ brcm,overclock-50 = <0>; - status = "okay"; - }; - -@@ -67,6 +68,7 @@ - - __overrides__ { - delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; - force_pio = <&sdhost>,"brcm,force-pio?"; - sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; - }; -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 542ae12..2a9eb9f 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -184,6 +184,7 @@ struct bcm2835_host { - int max_delay; /* maximum length of time spent waiting */ - struct timeval stop_time; /* when the last stop was issued */ - u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ -+ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ - }; - - -@@ -1223,6 +1224,10 @@ static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) - void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - { - int div = 0; /* Initialized for compiler warning */ -+ unsigned int input_clock = clock; -+ -+ if (host->overclock_50 && (clock == 50000000)) -+ clock = host->overclock_50 * 1000000; - - /* The SDCDIV register has 11 bits, and holds (div - 2). - But in data mode the max is 50MHz wihout a minimum, and only the -@@ -1266,13 +1271,18 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - if (div > SDCDIV_MAX_CDIV) - div = SDCDIV_MAX_CDIV; - -- host->mmc->actual_clock = host->max_clk / (div + 2); -+ clock = host->max_clk / (div + 2); -+ host->mmc->actual_clock = clock; -+ -+ if (clock > input_clock) -+ pr_warn("%s: Overclocking to %dHz\n", -+ mmc_hostname(host->mmc), clock); - - host->cdiv = div; - bcm2835_sdhost_write(host, host->cdiv, SDCDIV); - - pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", -- clock, host->max_clk, host->cdiv, host->mmc->actual_clock); -+ input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); - } - - static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) -@@ -1572,6 +1582,9 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - of_property_read_u32(node, - "brcm,delay-after-stop", - &host->delay_after_stop); -+ of_property_read_u32(node, -+ "brcm,overclock-50", -+ &host->overclock_50); - host->allow_dma = ALLOW_DMA && - !of_property_read_bool(node, "brcm,force-pio"); - } - -From ae7169ee054f60e3db61f1a5bb6eb1f52913886a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 14 May 2015 11:55:57 +0100 -Subject: [PATCH 155/216] bcm2835-mmc: Adding overclocking option - -Allow a different clock speed to be substitued for a requested 50MHz. -This option is exposed using the "overclock_50" DT parameter. -Note that the mmc interface is restricted to EVEN integer divisions of -250MHz, and the highest sensible option is 63 (250/4 = 62.5), the -next being 125 (250/2) which is much too high. - -Use at your own risk. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/mmc-overlay.dts | 19 +++++++++++++++++++ - drivers/mmc/host/bcm2835-mmc.c | 25 ++++++++++++++++++++++--- - 3 files changed, 42 insertions(+), 3 deletions(-) - create mode 100644 arch/arm/boot/dts/mmc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 9cb5a2d..a21afc5 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -27,6 +27,7 @@ dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb -diff --git a/arch/arm/boot/dts/mmc-overlay.dts b/arch/arm/boot/dts/mmc-overlay.dts -new file mode 100644 -index 0000000..0a37cf4 ---- /dev/null -+++ b/arch/arm/boot/dts/mmc-overlay.dts -@@ -0,0 +1,19 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ -+ __overlay__ { -+ brcm,overclock-50 = <0>; -+ }; -+ }; -+ -+ __overrides__ { -+ overclock_50 = <&mmc>,"brcm,overclock-50:0"; -+ force_pio = <&mmc>,"brcm,force-pio?"; -+ }; -+}; -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index 68314d5..c7c2ca1 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -131,6 +131,8 @@ struct bcm2835_host { - #define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ - #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ - #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ -+ -+ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ - }; - - -@@ -1086,7 +1088,10 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - int real_div = div, clk_mul = 1; - u16 clk = 0; - unsigned long timeout; -+ unsigned int input_clock = clock; - -+ if (host->overclock_50 && (clock == 50000000)) -+ clock = host->overclock_50 * 1000000; - - host->mmc->actual_clock = 0; - -@@ -1110,7 +1115,12 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - div >>= 1; - - if (real_div) -- host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; -+ clock = (host->max_clk * clk_mul) / real_div; -+ host->mmc->actual_clock = clock; -+ -+ if (clock > input_clock) -+ pr_warn("%s: Overclocking to %dHz\n", -+ mmc_hostname(host->mmc), clock); - - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; - clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) -@@ -1177,6 +1187,9 @@ static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) - u8 ctrl; - u16 clk, ctrl_2; - -+ pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", -+ ios->clock, ios->power_mode, ios->bus_width, -+ ios->timing, ios->signal_voltage, ios->drv_type); - - spin_lock_irqsave(&host->lock, flags); - -@@ -1444,10 +1457,16 @@ static int bcm2835_mmc_probe(struct platform_device *pdev) - goto err; - } - -- if (node) -+ if (node) { - mmc_of_parse(mmc); -- else -+ -+ /* Read any custom properties */ -+ of_property_read_u32(node, -+ "brcm,overclock-50", -+ &host->overclock_50); -+ } else { - mmc->caps |= MMC_CAP_4_BIT_DATA; -+ } - - ret = bcm2835_mmc_add_host(host); - if (ret) - -From 4b4b9568bc6fbfc222d59a28b2727ae5c725a92a Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Fri, 15 May 2015 14:21:32 +0200 -Subject: [PATCH 156/216] dmaengine: bcm2708: set residue_granularity field - -bcm2708-dmaengine supports residue reporting at burst level -but didn't report this via the residue_granularity field. - -Without this field set properly we get playback issues with I2S cards. ---- - drivers/dma/bcm2708-dmaengine.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 937fd60..987ed53 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -1112,6 +1112,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); -@@ -1180,6 +1181,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); - -From 1ddcc631437e913995361718209077d8247c10b0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 12 May 2015 17:26:35 +0100 -Subject: [PATCH 157/216] BCM2708_DT: Adding starter Compute Module DTS files - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+) - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index a21afc5..f3558df 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -3,6 +3,7 @@ ifeq ($(CONFIG_OF),y) - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb - dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb - - # Raspberry Pi - ifeq ($(CONFIG_BCM2708_DT),y) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -new file mode 100755 -index 0000000..45f8244 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,7 @@ -+/dts-v1/; -+ -+/include/ "bcm2708-rpi-cm.dtsi" -+ -+/ { -+ model = "Raspberry Pi Compute Module"; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -new file mode 100755 -index 0000000..d0a6fb8 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -0,0 +1,30 @@ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ aliases { -+ soc = &soc; -+ gpio = &gpio; -+ intc = &intc; -+ leds = &leds; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ }; -+}; - -From 210157c8363fc0ac4c99273d3ed8f54ed9929b0f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 11:57:29 +0100 -Subject: [PATCH 158/216] bcm2835-sdhost: Round up the overclock, so 62 works - for 62.5Mhz - -Also only warn once for each overclock setting. ---- - drivers/mmc/host/bcm2835-sdhost.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 2a9eb9f..eef8a24 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -185,6 +185,7 @@ struct bcm2835_host { - struct timeval stop_time; /* when the last stop was issued */ - u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ - u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ -+ u32 max_overclock; /* Highest reported */ - }; - - -@@ -1227,7 +1228,7 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - unsigned int input_clock = clock; - - if (host->overclock_50 && (clock == 50000000)) -- clock = host->overclock_50 * 1000000; -+ clock = host->overclock_50 * 1000000 + 999999; - - /* The SDCDIV register has 11 bits, and holds (div - 2). - But in data mode the max is 50MHz wihout a minimum, and only the -@@ -1274,9 +1275,11 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - clock = host->max_clk / (div + 2); - host->mmc->actual_clock = clock; - -- if (clock > input_clock) -+ if ((clock > input_clock) && (clock > host->max_overclock)) { - pr_warn("%s: Overclocking to %dHz\n", - mmc_hostname(host->mmc), clock); -+ host->max_overclock = clock; -+ } - - host->cdiv = div; - bcm2835_sdhost_write(host, host->cdiv, SDCDIV); - -From a946e70fd45a1f24f99816f72f5bbb0a7de0c1f3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 12:29:42 +0100 -Subject: [PATCH 159/216] bcm2835-mmc: Round up the overclock, so 62 works for - 62.5Mhz - -Also only warn once for each overclock setting. ---- - drivers/mmc/host/bcm2835-mmc.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index c7c2ca1..b7c4883 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -133,6 +133,7 @@ struct bcm2835_host { - #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ - - u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ -+ u32 max_overclock; /* Highest reported */ - }; - - -@@ -1091,7 +1092,7 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - unsigned int input_clock = clock; - - if (host->overclock_50 && (clock == 50000000)) -- clock = host->overclock_50 * 1000000; -+ clock = host->overclock_50 * 1000000 + 999999; - - host->mmc->actual_clock = 0; - -@@ -1118,9 +1119,11 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - clock = (host->max_clk * clk_mul) / real_div; - host->mmc->actual_clock = clock; - -- if (clock > input_clock) -+ if ((clock > input_clock) && (clock > host->max_overclock)) { - pr_warn("%s: Overclocking to %dHz\n", - mmc_hostname(host->mmc), clock); -+ host->max_overclock = clock; -+ } - - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; - clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) - -From f80dd3188715edaa5c23e3d99793170aa7dbd877 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 13:05:27 +0100 -Subject: [PATCH 160/216] BCM2708_DT: Add missing CM aliases - ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index d0a6fb8..8340c1e 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -3,6 +3,10 @@ - / { - aliases { - soc = &soc; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; - gpio = &gpio; - intc = &intc; - leds = &leds; - -From 90c3a2ff9838fdf619c6f391c27ce2fe02f083cf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 15 May 2015 20:20:09 +0200 -Subject: [PATCH 161/216] usb: dwc_otg: Don't use dma_to_virt() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit 6ce0d20 changes dma_to_virt() which breaks this driver. -Open code the old dma_to_virt() implementation to work around this. - -Limit the use of __bus_to_virt() to cases where transfer_buffer_length -is set and transfer_buffer is not set. This is done to increase the -chance that this driver will also work on ARCH_BCM2835. - -transfer_buffer should not be NULL if the length is set, but the -comment in the code indicates that there are situations where this -might happen. drivers/usb/isp1760/isp1760-hcd.c also has a similar -comment pointing to a possible: 'usb storage / SCSI bug'. - -Signed-off-by: Noralf Trønnes ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 1d28459..6aad9c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -766,16 +766,17 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, - !(usb_pipein(urb->pipe)))); - - buf = urb->transfer_buffer; -- if (hcd->self.uses_dma) { -+ if (hcd->self.uses_dma && !buf && urb->transfer_buffer_length) { - /* - * Calculate virtual address from physical address, - * because some class driver may not fill transfer_buffer. - * In Buffer DMA mode virual address is used, - * when handling non DWORD aligned buffers. - */ -- //buf = phys_to_virt(urb->transfer_dma); -- // DMA addresses are bus addresses not physical addresses! -- buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); -+ buf = (void *)__bus_to_virt((unsigned long)urb->transfer_dma); -+ dev_warn_once(&urb->dev->dev, -+ "USB transfer_buffer was NULL, will use __bus_to_virt(%pad)=%p\n", -+ &urb->transfer_dma, buf); - } - - if (!(urb->transfer_flags & URB_NO_INTERRUPT)) - -From 785584eaa255550270eb4496bdc31f241561b26c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 15 May 2015 20:20:26 +0200 -Subject: [PATCH 162/216] fixup: restore dma-mapping.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -dwc_otg has been fixed, so no need to revert 6ce0d20: -ARM: dma: Use dma_pfn_offset for dma address translation - -The pfn_to_dma/dma_to_pfn changes that came with that commit -is needed to use the 'dma-ranges' DT property on ARCH_BCM2835. -dma-ranges is needed by bcm2708_fb and vchiq on ARCH_BCM2835. -If not the mailbox call fails to hand over the correct -bus address to videocore. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/include/asm/dma-mapping.h | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h -index f5572d9..b52101d3 100644 ---- a/arch/arm/include/asm/dma-mapping.h -+++ b/arch/arm/include/asm/dma-mapping.h -@@ -58,21 +58,37 @@ static inline int dma_set_mask(struct device *dev, u64 mask) - #ifndef __arch_pfn_to_dma - static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) - { -+ if (dev) -+ pfn -= dev->dma_pfn_offset; - return (dma_addr_t)__pfn_to_bus(pfn); - } - - static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) - { -- return __bus_to_pfn(addr); -+ unsigned long pfn = __bus_to_pfn(addr); -+ -+ if (dev) -+ pfn += dev->dma_pfn_offset; -+ -+ return pfn; - } - - static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) - { -+ if (dev) { -+ unsigned long pfn = dma_to_pfn(dev, addr); -+ -+ return phys_to_virt(__pfn_to_phys(pfn)); -+ } -+ - return (void *)__bus_to_virt((unsigned long)addr); - } - - static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) - { -+ if (dev) -+ return pfn_to_dma(dev, virt_to_pfn(addr)); -+ - return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); - } - - -From 1b1de68277ff97f836021328e6ac6fbb24494c73 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:18:28 +0200 -Subject: [PATCH 163/216] fbdev: bcm2708_fb: Add ARCH_BCM2835 support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support. -Pass the device to dma_alloc_coherent() in order to get the -correct bus address on ARCH_BCM2835. -Use the new DMA legacy API header file. -Including is not necessary. - -Signed-off-by: Noralf Trønnes ---- - drivers/video/fbdev/bcm2708_fb.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 345c15e..f6ac7da 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -24,16 +24,13 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -- --#include --#include -- - #include - #include - #include -@@ -628,7 +625,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) - void *mem; - - mem = -- dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma, -+ dma_alloc_coherent(&fb->dev->dev, PAGE_ALIGN(sizeof(*fb->info)), &dma, - GFP_KERNEL); - - if (NULL == mem) { -@@ -783,12 +780,19 @@ static int bcm2708_fb_remove(struct platform_device *dev) - return 0; - } - -+static const struct of_device_id bcm2708_fb_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-fb", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_fb_of_match_table); -+ - static struct platform_driver bcm2708_fb_driver = { - .probe = bcm2708_fb_probe, - .remove = bcm2708_fb_remove, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_fb_of_match_table, - }, - }; - - -From e6d3d3d4102639777a7261d9eb6f195176fc50bb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:20:00 +0200 -Subject: [PATCH 164/216] BCM270x: Remove header file mach/dma.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This header file can be removed since there are no more users. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/dma.h | 2 -- - arch/arm/mach-bcm2709/include/mach/dma.h | 2 -- - 2 files changed, 4 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/dma.h - -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -deleted file mode 100644 -index d826705..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ /dev/null -@@ -1,2 +0,0 @@ --/* This file can be removed when all the drivers have been updated */ --#include -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -deleted file mode 100644 -index d826705..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/dma.h -+++ /dev/null -@@ -1,2 +0,0 @@ --/* This file can be removed when all the drivers have been updated */ --#include - -From 11e908510cac293a92b124f36476ae7fe4c581ec Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:21:31 +0200 -Subject: [PATCH 165/216] BCM270x_DT: Add bcm2708-fb device -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add bcm2708-fb to Device Tree and don't add the -platform device when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ++++ - arch/arm/boot/dts/bcm2708_common.dtsi | 5 +++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 6 files changed, 19 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index f25563a..9a8fed0 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 17b4b8c..cf67ec9 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 1c8c1af..c5ed34b 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -109,6 +109,11 @@ - leds: leds { - compatible = "gpio-leds"; - }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ status = "disabled"; -+ }; - }; - - clocks { -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index c73249b..1c865de 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7cc47c1..cde2124 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -928,7 +928,7 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&w1_device); - #endif - bcm_register_device(&bcm2708_systemtimer_device); -- bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 2c0a664..95db41ff 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -951,7 +951,7 @@ void __init bcm2709_init(void) - #ifdef SYSTEM_TIMER - bcm_register_device(&bcm2708_systemtimer_device); - #endif -- bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -From 0abe9b6fa045617f9fb0f8afe64b69072821d241 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 5 May 2015 13:10:11 -0700 -Subject: [PATCH 166/216] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to - SDRAM. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There exists a tiny MMU, configurable only by the VC (running the -closed firmware), which maps from the ARM's physical addresses to bus -addresses. These bus addresses determine the caching behavior in the -VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top -2 bits. The bits in the bus address mean: - -From the VideoCore processor: -0x0... L1 and L2 cache allocating and coherent -0x4... L1 non-allocating, but coherent. L2 allocating and coherent -0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent -0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent - -From the GPU peripherals (note: all peripherals bypass the L1 -cache. The ARM will see this view once through the VC MMU): -0x0... Do not use -0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. -0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent -0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent - -The 2835 firmware always configures the MMU to turn ARM physical -addresses with 0x0 top bits to 0x4, meaning present in L2 but -incoherent with L1. However, any bus addresses we were generating in -the kernel to be passed to a device had 0x0 bits. That would be a -reserved (possibly totally incoherent) value if sent to a GPU -peripheral like USB, or L1 allocating if sent to the VC (like a -firmware property request). By setting dma-ranges, all of the devices -below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and -friends return addresses with 0x4 bits and avoid cache incoherency. - -This matches the behavior in the downstream 2708 kernel (see -BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). - -Signed-off-by: Eric Anholt -Tested-by: Noralf Trønnes -Acked-by: Stephen Warren -Cc: popcornmix@gmail.com ---- - arch/arm/boot/dts/bcm2835.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 06cba29..f91db90 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -14,6 +14,7 @@ - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x7e000000 0x20000000 0x02000000>; -+ dma-ranges = <0x40000000 0x00000000 0x20000000>; - - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; - -From fabd2cdba17ab122a41957bced0c06e993b559a8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:24:13 +0200 -Subject: [PATCH 167/216] bcm2835: Add bcm2708-fb to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add framebuffer device to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 ++++ - arch/arm/boot/dts/bcm2835.dtsi | 5 +++++ - 2 files changed, 9 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index 9f4ed2f..f2ce803 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -49,3 +49,7 @@ - status = "okay"; - bus-width = <4>; - }; -+ -+&fb { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f91db90..f3ab9b3 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -159,6 +159,11 @@ - arm-pmu { - compatible = "arm,arm1176-pmu"; - }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ status = "disabled"; -+ }; - }; - - clocks { - -From 81530cfc1eb8c2069f7083fa2cc56b3b7470eb29 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:24:35 +0200 -Subject: [PATCH 168/216] bcm2835: bcm2835_defconfig use FB_BCM2708 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the bcm2708 framebuffer driver. -Disable the simple framebuffer driver, which matches the -device handed over by u-boot. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 26b4c75..1af6069 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -72,7 +72,7 @@ CONFIG_SPI_BCM2835=y - CONFIG_GPIO_SYSFS=y - # CONFIG_HWMON is not set - CONFIG_FB=y --CONFIG_FB_SIMPLE=y -+CONFIG_FB_BCM2708=y - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y - CONFIG_USB=y - -From 9e0da80c0836b21773e84b699f2e94e50680b485 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 19 May 2015 11:41:11 +0100 -Subject: [PATCH 169/216] BCM2708_DT: Enable mmc and fb in the CM dtsi - ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 8340c1e..815a3a4 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -25,6 +25,15 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ -+&fb { -+ status = "okay"; -+}; -+ - / { - __overrides__ { - act_led_gpio = <&act_led>,"gpios:4"; - -From c95de8db34841f61ef2cb38afb8b84973bd9aa6c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:31:50 +0200 -Subject: [PATCH 170/216] BCM270x: Add vchiq device to platform file and Device - Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Prepare to turn the vchiq module into a driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 6 ++++++ - arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ - arch/arm/mach-bcm2708/include/mach/platform.h | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 26 ++++++++++++++++++++++++++ - arch/arm/mach-bcm2709/include/mach/platform.h | 1 + - 5 files changed, 60 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index c5ed34b..2d9bcd8 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -114,6 +114,12 @@ - compatible = "brcm,bcm2708-fb"; - status = "disabled"; - }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ }; - }; - - clocks { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cde2124..81cc988 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -437,6 +437,31 @@ static struct platform_device bcm2708_vcio_device = { - }, - }; - -+static struct resource bcm2708_vchiq_resources[] = { -+ { -+ .start = ARMCTRL_0_BELL_BASE, -+ .end = ARMCTRL_0_BELL_BASE + 16, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_DOORBELL_0, -+ .end = IRQ_ARM_DOORBELL_0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_vchiq_device = { -+ .name = "bcm2835_vchiq", -+ .id = -1, -+ .resource = bcm2708_vchiq_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), -+ .dev = { -+ .dma_mask = &vchiq_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ - #ifdef CONFIG_BCM2708_GPIO - #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" - -@@ -909,6 +934,7 @@ void __init bcm2708_init(void) - - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device_dt(&bcm2708_vcio_device); -+ bcm_register_device_dt(&bcm2708_vchiq_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index bef3e5a..69674e9 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ - #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 95db41ff..528bf6e 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -456,6 +456,31 @@ static struct platform_device bcm2708_vcio_device = { - }, - }; - -+static struct resource bcm2708_vchiq_resources[] = { -+ { -+ .start = ARMCTRL_0_BELL_BASE, -+ .end = ARMCTRL_0_BELL_BASE + 16, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_DOORBELL_0, -+ .end = IRQ_ARM_DOORBELL_0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_vchiq_device = { -+ .name = "bcm2835_vchiq", -+ .id = -1, -+ .resource = bcm2708_vchiq_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), -+ .dev = { -+ .dma_mask = &vchiq_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ - #ifdef CONFIG_BCM2708_GPIO - #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" - -@@ -930,6 +955,7 @@ void __init bcm2709_init(void) - - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device_dt(&bcm2708_vcio_device); -+ bcm_register_device_dt(&bcm2708_vchiq_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 5574bb5..be99733 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ - #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - -From b723b4395acda96c805d6cd382d5732efa6e449c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:32:34 +0200 -Subject: [PATCH 171/216] bcm2708: vchiq: Add Device Tree support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Turn vchiq into a driver and stop hardcoding resources. -Use devm_* functions in probe path to simplify cleanup. -A global variable is used to hold the register address. This is done -to keep this patch as small as possible. -Also make available on ARCH_BCM2835. -Based on work by Lubomir Rintel. - -Signed-off-by: Noralf Trønnes ---- - drivers/misc/vc04_services/Kconfig | 2 +- - .../interface/vchiq_arm/vchiq_2835_arm.c | 124 +++++++++------------ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 44 ++++---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 7 +- - 4 files changed, 79 insertions(+), 98 deletions(-) - -diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig -index b94e6cd..b4198c2 100644 ---- a/drivers/misc/vc04_services/Kconfig -+++ b/drivers/misc/vc04_services/Kconfig -@@ -1,6 +1,6 @@ - config BCM2708_VCHIQ - tristate "Videocore VCHIQ" -- depends on MACH_BCM2708 || MACH_BCM2709 -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - default y - help - Kernel to VideoCore communication interface for the -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 70e5086..660aad2 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -35,22 +35,17 @@ - #include - #include - #include --#include - #include - #include - #include - #include - #include -+#include - #include - #include - --#include -- --#include -- - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - --#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0 - #define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) - - #include "vchiq_arm.h" -@@ -60,14 +55,15 @@ - - #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) - -+#define BELL0 0x00 -+#define BELL2 0x08 -+ - typedef struct vchiq_2835_state_struct { - int inited; - VCHIQ_ARM_STATE_T arm_state; - } VCHIQ_2835_ARM_STATE_T; - --static char *g_slot_mem; --static int g_slot_mem_size; --dma_addr_t g_slot_phys; -+static void __iomem *g_regs; - static FRAGMENTS_T *g_fragments_base; - static FRAGMENTS_T *g_free_fragments; - struct semaphore g_free_fragments_sema; -@@ -86,43 +82,40 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, - static void - free_pagelist(PAGELIST_T *pagelist, int actual); - --int __init --vchiq_platform_init(VCHIQ_STATE_T *state) -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) - { -+ struct device *dev = &pdev->dev; - VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -- int frag_mem_size; -- int err; -- int i; -+ struct resource *res; -+ void *slot_mem; -+ dma_addr_t slot_phys; -+ int slot_mem_size, frag_mem_size; -+ int err, irq, i; - - /* Allocate space for the channels in coherent memory */ -- g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); -+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); - frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); - -- g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size, -- &g_slot_phys, GFP_KERNEL); -- -- if (!g_slot_mem) { -- vchiq_log_error(vchiq_arm_log_level, -- "Unable to allocate channel memory"); -- err = -ENOMEM; -- goto failed_alloc; -+ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, -+ &slot_phys, GFP_KERNEL); -+ if (!slot_mem) { -+ dev_err(dev, "could not allocate DMA memory\n"); -+ return -ENOMEM; - } - -- WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0); -+ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); - -- vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size); -- if (!vchiq_slot_zero) { -- err = -EINVAL; -- goto failed_init_slots; -- } -+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); -+ if (!vchiq_slot_zero) -+ return -EINVAL; - - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -- (int)g_slot_phys + g_slot_mem_size; -+ (int)slot_phys + slot_mem_size; - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = - MAX_FRAGMENTS; - -- g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size); -- g_slot_mem_size += frag_mem_size; -+ g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); -+ slot_mem_size += frag_mem_size; - - g_free_fragments = g_fragments_base; - for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { -@@ -132,54 +125,46 @@ vchiq_platform_init(VCHIQ_STATE_T *state) - *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; - sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); - -- if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) != -- VCHIQ_SUCCESS) { -- err = -EINVAL; -- goto failed_vchiq_init; -+ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ g_regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(g_regs)) -+ return PTR_ERR(g_regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "failed to get IRQ\n"); -+ return irq; - } - -- err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq, -- IRQF_IRQPOLL, "VCHIQ doorbell", -- state); -- if (err < 0) { -- vchiq_log_error(vchiq_arm_log_level, "%s: failed to register " -- "irq=%d err=%d", __func__, -- VCHIQ_DOORBELL_IRQ, err); -- goto failed_request_irq; -+ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, -+ "VCHIQ doorbell", state); -+ if (err) { -+ dev_err(dev, "failed to register irq=%d\n", irq); -+ return err; - } - - /* Send the base address of the slots to VideoCore */ - - dsb(); /* Ensure all writes have completed */ - -- bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys); -+ err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); -+ if (err) { -+ dev_err(dev, "mailbox write failed\n"); -+ return err; -+ } - - vchiq_log_info(vchiq_arm_log_level, -- "vchiq_init - done (slots %x, phys %x)", -- (unsigned int)vchiq_slot_zero, g_slot_phys); -+ "vchiq_init - done (slots %x, phys %pad)", -+ (unsigned int)vchiq_slot_zero, &slot_phys); - -- vchiq_call_connected_callbacks(); -+ vchiq_call_connected_callbacks(); - - return 0; -- --failed_request_irq: --failed_vchiq_init: --failed_init_slots: -- dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys); -- --failed_alloc: -- return err; --} -- --void __exit --vchiq_platform_exit(VCHIQ_STATE_T *state) --{ -- free_irq(VCHIQ_DOORBELL_IRQ, state); -- dma_free_coherent(NULL, g_slot_mem_size, -- g_slot_mem, g_slot_phys); - } - -- - VCHIQ_STATUS_T - vchiq_platform_init_state(VCHIQ_STATE_T *state) - { -@@ -213,11 +198,8 @@ remote_event_signal(REMOTE_EVENT_T *event) - - dsb(); /* data barrier operation */ - -- if (event->armed) { -- /* trigger vc interrupt */ -- -- writel(0, __io_address(ARM_0_BELL2)); -- } -+ if (event->armed) -+ writel(0, g_regs + BELL2); /* trigger vc interrupt */ - } - - int -@@ -341,7 +323,7 @@ vchiq_doorbell_irq(int irq, void *dev_id) - unsigned int status; - - /* Read (and clear) the doorbell */ -- status = readl(__io_address(ARM_0_BELL0)); -+ status = readl(g_regs + BELL0); - - if (status & 0x4) { /* Was the doorbell rung? */ - remote_event_pollall(state); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 0ad9656..31e2cba 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - #include "vchiq_core.h" - #include "vchiq_ioctl.h" -@@ -2790,15 +2791,7 @@ void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, - } - } - -- --/**************************************************************************** --* --* vchiq_init - called when the module is loaded. --* --***************************************************************************/ -- --static int __init --vchiq_init(void) -+static int vchiq_probe(struct platform_device *pdev) - { - int err; - void *ptr_err; -@@ -2835,7 +2828,7 @@ vchiq_init(void) - if (IS_ERR(ptr_err)) - goto failed_device_create; - -- err = vchiq_platform_init(&g_state); -+ err = vchiq_platform_init(pdev, &g_state); - if (err != 0) - goto failed_platform_init; - -@@ -2862,23 +2855,32 @@ vchiq_init(void) - return err; - } - --/**************************************************************************** --* --* vchiq_exit - called when the module is unloaded. --* --***************************************************************************/ -- --static void __exit --vchiq_exit(void) -+static int vchiq_remove(struct platform_device *pdev) - { -- vchiq_platform_exit(&g_state); - device_destroy(vchiq_class, vchiq_devid); - class_destroy(vchiq_class); - cdev_del(&vchiq_cdev); - unregister_chrdev_region(vchiq_devid, 1); -+ -+ return 0; - } - --module_init(vchiq_init); --module_exit(vchiq_exit); -+static const struct of_device_id vchiq_of_match[] = { -+ { .compatible = "brcm,bcm2835-vchiq", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, vchiq_of_match); -+ -+static struct platform_driver vchiq_driver = { -+ .driver = { -+ .name = "bcm2835_vchiq", -+ .owner = THIS_MODULE, -+ .of_match_table = vchiq_of_match, -+ }, -+ .probe = vchiq_probe, -+ .remove = vchiq_remove, -+}; -+module_platform_driver(vchiq_driver); -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Broadcom Corporation"); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -index d1e2741..9740e1a 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -36,6 +36,7 @@ - #define VCHIQ_ARM_H - - #include -+#include - #include - #include - #include "vchiq_core.h" -@@ -128,11 +129,7 @@ typedef struct vchiq_arm_state_struct { - extern int vchiq_arm_log_level; - extern int vchiq_susp_log_level; - --extern int __init --vchiq_platform_init(VCHIQ_STATE_T *state); -- --extern void __exit --vchiq_platform_exit(VCHIQ_STATE_T *state); -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); - - extern VCHIQ_STATE_T * - vchiq_get_state(void); - -From a368d9389c5c346a4e5b6ee63a5b28c45184aa20 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:32:50 +0200 -Subject: [PATCH 172/216] bcm2835: Add bcm2835-vchiq to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add vchiq to Device Tree. There are no kernel users yet, -but it's available to userspace (vcgencmd). - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f3ab9b3..72d0354 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -164,6 +164,12 @@ - compatible = "brcm,bcm2708-fb"; - status = "disabled"; - }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ }; - }; - - clocks { - -From 0bf6760b3d81238fcfac05e88f66252192c5745d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 20 May 2015 09:29:46 +0100 -Subject: [PATCH 173/216] i2c-bcm2708: When using DT, leave the GPIO setup to - pinctrl - ---- - drivers/i2c/busses/i2c-bcm2708.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 81e9374..8773203 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -382,7 +382,8 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - goto out_clk_put; - } - -- bcm2708_i2c_init_pinmode(pdev->id); -+ if (!pdev->dev.of_node) -+ bcm2708_i2c_init_pinmode(pdev->id); - - bi = kzalloc(sizeof(*bi), GFP_KERNEL); - if (!bi) - -From aa0aca81361683205b07ecc895256795ea771528 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 May 2015 11:36:31 +0100 -Subject: [PATCH 174/216] vchiq: Change logging level for inbound data - ---- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -index 835688b..2c98da4 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -1782,7 +1782,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) - service->remoteport); - break; - case VCHIQ_MSG_DATA: -- vchiq_log_trace(vchiq_core_log_level, -+ vchiq_log_info(vchiq_core_log_level, - "%d: prs DATA@%x,%x (%d->%d)", - state->id, (unsigned int)header, size, - remoteport, localport); - -From 32477cf579fd64092395855bfacf907c7da8e3d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 21 May 2015 13:24:35 +0200 -Subject: [PATCH 175/216] BCM270x: Add onboard sound device to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to alsa driver. -Add device to Device Tree. -Don't add platform devices when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 4 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 7 +++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - sound/arm/Kconfig | 3 +- - sound/arm/bcm2835.c | 91 ++++++++++++++++++++++++++++++++ - 9 files changed, 118 insertions(+), 3 deletions(-) - mode change 100755 => 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi - mode change 100755 => 100644 sound/arm/bcm2835.c - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 9a8fed0..6323c5b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index cf67ec9..e1fe6a4 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -old mode 100755 -new mode 100644 -index 815a3a4..1c2cfcf ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -34,6 +34,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - / { - __overrides__ { - act_led_gpio = <&act_led>,"gpios:4"; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 2d9bcd8..4bf6960 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -3,6 +3,13 @@ - / { - interrupt-parent = <&intc>; - -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ - soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 1c865de..921add1 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 81cc988..e451187 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -964,7 +964,7 @@ void __init bcm2708_init(void) - #endif - bcm2708_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -- bcm_register_device(&bcm2708_alsa_devices[i]); -+ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 528bf6e..06c2c74 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -987,7 +987,7 @@ void __init bcm2709_init(void) - #endif - bcm2709_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -- bcm_register_device(&bcm2708_alsa_devices[i]); -+ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); - -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index ada7ba2..fcbe9d7 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -41,7 +41,8 @@ config SND_PXA2XX_AC97 - - config SND_BCM2835 - tristate "BCM2835 ALSA driver" -- depends on (ARCH_BCM2708 || ARCH_BCM2709) && BCM2708_VCHIQ && SND -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -+ && BCM2708_VCHIQ && SND - select SND_PCM - help - Say Y or M if you want to support BCM2835 Alsa pcm card driver -diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c -old mode 100755 -new mode 100644 -index 7ed5079..6b545e7 ---- a/sound/arm/bcm2835.c -+++ b/sound/arm/bcm2835.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "bcm2835.h" - -@@ -81,6 +82,86 @@ static int snd_bcm2835_create(struct snd_card *card, - return 0; - } - -+static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ bcm2835_chip_t *chip; -+ struct snd_card *card; -+ u32 numchans; -+ int err, i; -+ -+ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", -+ &numchans); -+ if (err) { -+ dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); -+ return err; -+ } -+ -+ if (numchans == 0 || numchans > MAX_SUBSTREAMS) { -+ numchans = MAX_SUBSTREAMS; -+ dev_warn(dev, "Illegal 'brcm,pwm-channels' value, will use %u\n", -+ numchans); -+ } -+ -+ err = snd_card_new(NULL, -1, NULL, THIS_MODULE, 0, &card); -+ if (err) { -+ dev_err(dev, "Failed to create soundcard structure\n"); -+ return err; -+ } -+ -+ snd_card_set_dev(card, dev); -+ strcpy(card->driver, "bcm2835"); -+ strcpy(card->shortname, "bcm2835 ALSA"); -+ sprintf(card->longname, "%s", card->shortname); -+ -+ err = snd_bcm2835_create(card, pdev, &chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create bcm2835 chip\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_spdif_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 spdif pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_ctl(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 ctl\n"); -+ goto err_free; -+ } -+ -+ for (i = 0; i < numchans; i++) { -+ chip->avail_substreams |= (1 << i); -+ chip->pdev[i] = pdev; -+ } -+ -+ err = snd_card_register(card); -+ if (err) { -+ dev_err(dev, "Failed to register bcm2835 ALSA card \n"); -+ goto err_free; -+ } -+ -+ g_card = card; -+ g_chip = chip; -+ platform_set_drvdata(pdev, card); -+ audio_info("bcm2835 ALSA card created with %u channels\n", numchans); -+ -+ return 0; -+ -+err_free: -+ snd_card_free(card); -+ -+ return err; -+} -+ - static int snd_bcm2835_alsa_probe(struct platform_device *pdev) - { - static int dev; -@@ -88,6 +169,9 @@ static int snd_bcm2835_alsa_probe(struct platform_device *pdev) - struct snd_card *card; - int err; - -+ if (pdev->dev.of_node) -+ return snd_bcm2835_alsa_probe_dt(pdev); -+ - if (dev >= MAX_SUBSTREAMS) - return -ENODEV; - -@@ -224,6 +308,12 @@ static int snd_bcm2835_alsa_resume(struct platform_device *pdev) - - #endif - -+static const struct of_device_id snd_bcm2835_of_match_table[] = { -+ { .compatible = "brcm,bcm2835-audio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); -+ - static struct platform_driver bcm2835_alsa0_driver = { - .probe = snd_bcm2835_alsa_probe, - .remove = snd_bcm2835_alsa_remove, -@@ -234,6 +324,7 @@ static struct platform_driver bcm2835_alsa0_driver = { - .driver = { - .name = "bcm2835_AUD0", - .owner = THIS_MODULE, -+ .of_match_table = snd_bcm2835_of_match_table, - }, - }; - - -From a8d9f167700bc9fd113a303b4944272519fc40f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 21 May 2015 13:25:32 +0200 -Subject: [PATCH 176/216] bcm2835: Add bcm2835-audio to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add onboard sound device to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index f2ce803..f23835e 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -14,6 +14,12 @@ - linux,default-trigger = "heartbeat"; - }; - }; -+ -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ }; - }; - - &gpio { - -From ead779a26fcab730a6d4be4c7b48c62b22afd8a5 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 18 May 2015 16:59:02 +0100 -Subject: [PATCH 177/216] config: Add CONFIG_CIFS_UPCALL - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index ff87581..6fdd9bb 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1118,6 +1118,7 @@ CONFIG_NFSD_V3_ACL=y - CONFIG_NFSD_V4=y - CONFIG_CIFS=m - CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y - CONFIG_CIFS_XATTR=y - CONFIG_CIFS_POSIX=y - CONFIG_9P_FS=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e339979..93b3de1 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1111,6 +1111,7 @@ CONFIG_NFSD_V3_ACL=y - CONFIG_NFSD_V4=y - CONFIG_CIFS=m - CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y - CONFIG_CIFS_XATTR=y - CONFIG_CIFS_POSIX=y - CONFIG_9P_FS=m - -From 2728618d457e238f4f95d96ad9303a1d816109a9 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 18 May 2015 16:59:13 +0100 -Subject: [PATCH 178/216] config: Add CONFIG_FB_SSD1307=m - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 6fdd9bb..9daaeb7 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -769,6 +769,7 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m - # CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 93b3de1..dc27aeb 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -762,6 +762,7 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m - # CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y - -From 25b5c8e286f3a2b1779c63754b8993107bb416b0 Mon Sep 17 00:00:00 2001 +From f794a0549b3a54cbe6dcfef3b37c421dda92d13a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 179/216] Improve __copy_to_user and __copy_from_user - performance +Subject: [PATCH 71/77] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use optimised memcpy/memmove/memcmp/memset implementations. @@ -143076,7 +132661,7 @@ index cf4f3aa..9fe7780 100644 #define memset(p,v,n) \ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index ce0786e..b85b93d 100644 +index 74b17d0..f4ad0a1 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -475,6 +475,7 @@ do { \ @@ -144557,356 +134142,28 @@ index 3e58d71..0622891 100644 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From ee5567b6efdbf9cbdf4cacaabc7623c5f6d45064 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 19 May 2015 18:49:06 +0100 -Subject: [PATCH 180/216] vcsm: Add ioctl for custom cache flushing - ---- - arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 15 +++++++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 49 ++++++++++++++++++++++ - 2 files changed, 64 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -index 42d0eb0..334f36d 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -+++ b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -@@ -61,6 +61,8 @@ enum vmcs_sm_cmd_e { - VMCS_SM_CMD_HOST_WALK_PID_ALLOC, - VMCS_SM_CMD_HOST_WALK_PID_MAP, - -+ VMCS_SM_CMD_CLEAN_INVALID, -+ - VMCS_SM_CMD_LAST /* Do no delete */ - }; - -@@ -163,6 +165,16 @@ struct vmcs_sm_ioctl_cache { - unsigned int size; - }; - -+struct vmcs_sm_ioctl_clean_invalid { -+ /* user -> kernel */ -+ struct { -+ unsigned int cmd; -+ unsigned int handle; -+ unsigned int addr; -+ unsigned int size; -+ } s[8]; -+}; -+ - /* IOCTL numbers */ - #define VMCS_SM_IOCTL_MEM_ALLOC\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\ -@@ -191,6 +203,9 @@ struct vmcs_sm_ioctl_cache { - #define VMCS_SM_IOCTL_MEM_INVALID\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\ - struct vmcs_sm_ioctl_cache) -+#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\ -+ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\ -+ struct vmcs_sm_ioctl_clean_invalid) - - #define VMCS_SM_IOCTL_SIZE_USR_HDL\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\ -diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c -index da1c523..39a8971 100644 ---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c -+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -2732,6 +2732,55 @@ static long vc_sm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - } - break; - -+ /* Flush/Invalidate the cache for a given mapping. */ -+ case VMCS_SM_CMD_CLEAN_INVALID: -+ { -+ int i; -+ struct vmcs_sm_ioctl_clean_invalid ioparam; -+ -+ /* Get parameter data. */ -+ if (copy_from_user(&ioparam, -+ (void *)arg, sizeof(ioparam)) != 0) { -+ pr_err("[%s]: failed to copy-from-user for cmd %x\n", -+ __func__, cmdnr); -+ ret = -EFAULT; -+ goto out; -+ } -+ for (i=0; ires_cached) { -+ unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1); -+ unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1); -+ resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++; -+ -+ /* L1/L2 cache flush */ -+ down_read(¤t->mm->mmap_sem); -+ vcsm_vma_cache_clean_page_range(base, end); -+ up_read(¤t->mm->mmap_sem); -+ } else if (resource == NULL) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (resource) -+ vmcs_sm_release_resource(resource, 0); -+ } -+ break; -+ } -+ } -+ } -+ break; -+ - default: - { - ret = -EINVAL; - -From 6f9e2f739661f49e2375be580025549b367444b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 17 Mar 2015 16:07:48 +0100 -Subject: [PATCH 181/216] dts: overlay: add generic support for ads7846 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add generic support for the ADS7846 touch controller. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/ads7846-overlay.dts | 83 +++++++++++++++++++++++++++++++++++ - 2 files changed, 84 insertions(+) - create mode 100644 arch/arm/boot/dts/ads7846-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index f3558df..0e77296 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -13,6 +13,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb -diff --git a/arch/arm/boot/dts/ads7846-overlay.dts b/arch/arm/boot/dts/ads7846-overlay.dts -new file mode 100644 -index 0000000..6a92cd1 ---- /dev/null -+++ b/arch/arm/boot/dts/ads7846-overlay.dts -@@ -0,0 +1,83 @@ -+/* -+ * Generic Device Tree overlay for the ADS7846 touch controller -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ ads7846_pins: ads7846_pins { -+ brcm,pins = <255>; /* illegal default value */ -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ads7846: ads7846@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ads7846_pins>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <255 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 255 0>; -+ -+ /* driver defaults */ -+ ti,x-min = /bits/ 16 <0>; -+ ti,y-min = /bits/ 16 <0>; -+ ti,x-max = /bits/ 16 <0x0FFF>; -+ ti,y-max = /bits/ 16 <0x0FFF>; -+ ti,pressure-min = /bits/ 16 <0>; -+ ti,pressure-max = /bits/ 16 <0xFFFF>; -+ ti,x-plate-ohms = /bits/ 16 <400>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ cs = <&ads7846>,"reg:0"; -+ speed = <&ads7846>,"spi-max-frequency:0"; -+ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -+ <&ads7846>,"interrupts:0", -+ <&ads7846>,"pendown-gpio:4"; -+ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -+ swapxy = <&ads7846>,"ti,swap-xy?"; -+ xmin = <&ads7846>,"ti,x-min;0"; -+ ymin = <&ads7846>,"ti,y-min;0"; -+ xmax = <&ads7846>,"ti,x-max;0"; -+ ymax = <&ads7846>,"ti,y-max;0"; -+ pmin = <&ads7846>,"ti,pressure-min;0"; -+ pmax = <&ads7846>,"ti,pressure-max;0"; -+ xohms = <&ads7846>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From beda21eb0afb05805e46419c37f1127bf35fa775 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 24 May 2015 19:12:01 +0200 -Subject: [PATCH 182/216] bcm270x: add dtparam for audio node - -The audio node is enabled by default and can be disabled -with dtparam=audio=off in config.txt ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 3 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6323c5b..609d004 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -126,5 +126,7 @@ - pwr_led_gpio = <&pwr_led>,"gpios:4"; - pwr_led_activelow = <&pwr_led>,"gpios:8"; - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e1fe6a4..e601194 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -116,5 +116,7 @@ - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 921add1..fe282e4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -126,5 +126,7 @@ - pwr_led_gpio = <&pwr_led>,"gpios:4"; - pwr_led_activelow = <&pwr_led>,"gpios:8"; - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; - -From c40ce86818e2ccd1521b5072cfa0bc102893ca7a Mon Sep 17 00:00:00 2001 +From 5787d557e062cdac5f3e19ccd60394dc6df38aab Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 27 May 2015 17:22:15 +0100 -Subject: [PATCH 183/216] bcm2835-audio: Create the platform device if the DT +Subject: [PATCH 72/77] bcm2835-audio: Create the platform device if the DT node is disabled For backwards compatibility, allow the built-in ALSA driver to be enabled either by loading the module from /etc/modules or by enabling the "/audio" node in DT. --- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ---- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ---- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ---- - arch/arm/mach-bcm2708/bcm2708.c | 10 ++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 10 ++++++++-- - 5 files changed, 16 insertions(+), 16 deletions(-) + arch/arm/mach-bcm2708/bcm2708.c | 10 ++++++++-- + arch/arm/mach-bcm2709/bcm2709.c | 10 ++++++++-- + 2 files changed, 16 insertions(+), 4 deletions(-) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 609d004..75df21c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e601194..df12b7d 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index fe282e4..78bc756 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e451187..06438df 100644 +index de2f93a..cfc4f13 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -963,8 +963,14 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2835_emmc_device); +@@ -898,8 +898,14 @@ void __init bcm2708_init(void) #endif bcm2708_init_led(); + bcm2708_init_uart1(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device_dt(&bcm2708_alsa_devices[i]); + @@ -144921,13 +134178,13 @@ index e451187..06438df 100644 bcm_register_device_dt(&bcm2708_spi_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 06c2c74..ce06b7d 100644 +index 350647a..507ff52 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -986,8 +986,14 @@ void __init bcm2709_init(void) - bcm_register_device_dt(&bcm2835_emmc_device); +@@ -918,8 +918,14 @@ void __init bcm2709_init(void) #endif bcm2709_init_led(); + bcm2709_init_uart1(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device_dt(&bcm2708_alsa_devices[i]); + @@ -144942,8640 +134199,10 @@ index 06c2c74..ce06b7d 100644 bcm_register_device_dt(&bcm2708_spi_device); -From 9f10489e52092f350c72745c2ac3d0afbbf4cd44 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 27 May 2015 14:39:55 +0000 -Subject: [PATCH 184/216] device-tree: spi: make spi-bcm2835 the default spi - driver and prepare for dma - -* make spi-bcm2835 the default driver for spi -* add a fallback spi-bcm2708 overlay -* add dma entries to device tree for future updates -* add default cs-gpios entry showing how to extend the number of chip-selects. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 10 +++++++++- - arch/arm/boot/dts/spi-bcm2708-overlay.dts | 18 ++++++++++++++++++ - 3 files changed, 28 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/spi-bcm2708-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0e77296..9124dfb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -41,6 +41,7 @@ dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 4bf6960..3f8af85 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -84,13 +84,21 @@ - }; - - spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -+ compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; - interrupts = <2 22>; - clocks = <&clk_spi>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -+ /* the dma channels */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ /* the chipselects used - <0> means native GPIO -+ * add more gpios if necessary as <&gpio 6 1> -+ * (but do not forget to make them output!) -+ */ -+ cs-gpios = <0>, <0>; - }; - - i2c0: i2c@7e205000 { -diff --git a/arch/arm/boot/dts/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -new file mode 100644 -index 0000000..e378ef1 ---- /dev/null -+++ b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2708-spi"; -+ }; -+ }; -+}; - -From 8c5dd3fb2ef21f3dc20a7c999fd2659354afa975 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 23 May 2015 23:30:36 +0200 -Subject: [PATCH 185/216] BCM270x: Move power module -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the power module available on ARCH_BCM2835 by moving it. -The module turns on USB power making it possible to boot -ARCH_BCM2835 directly with the VC bootloader. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/include/mach/arm_power.h | 62 -------- - arch/arm/mach-bcm2708/include/mach/power.h | 26 ---- - arch/arm/mach-bcm2708/power.c | 201 ------------------------- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/include/mach/arm_power.h | 62 -------- - arch/arm/mach-bcm2709/include/mach/power.h | 26 ---- - arch/arm/mach-bcm2709/power.c | 199 ------------------------ - drivers/soc/Kconfig | 1 + - drivers/soc/Makefile | 1 + - drivers/soc/bcm2835/Kconfig | 9 ++ - drivers/soc/bcm2835/Makefile | 1 + - drivers/soc/bcm2835/bcm2708-power.c | 200 ++++++++++++++++++++++++ - include/soc/bcm2835/power.h | 61 ++++++++ - 14 files changed, 275 insertions(+), 578 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/power.h - delete mode 100644 arch/arm/mach-bcm2708/power.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/arm_power.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/power.h - delete mode 100644 arch/arm/mach-bcm2709/power.c - create mode 100644 drivers/soc/bcm2835/Kconfig - create mode 100644 drivers/soc/bcm2835/Makefile - create mode 100644 drivers/soc/bcm2835/bcm2708-power.c - create mode 100644 include/soc/bcm2835/power.h - -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index c1e7d41..5552ae8 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o power.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h -deleted file mode 100644 -index d3bf245..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/arm_power.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _ARM_POWER_H --#define _ARM_POWER_H -- --/* Use meaningful names on each side */ --#ifdef __VIDEOCORE__ --#define PREFIX(x) ARM_##x --#else --#define PREFIX(x) BCM_##x --#endif -- --enum { -- PREFIX(POWER_SDCARD_BIT), -- PREFIX(POWER_UART_BIT), -- PREFIX(POWER_MINIUART_BIT), -- PREFIX(POWER_USB_BIT), -- PREFIX(POWER_I2C0_BIT), -- PREFIX(POWER_I2C1_BIT), -- PREFIX(POWER_I2C2_BIT), -- PREFIX(POWER_SPI_BIT), -- PREFIX(POWER_CCP2TX_BIT), -- PREFIX(POWER_DSI_BIT), -- -- PREFIX(POWER_MAX) --}; -- --enum { -- PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -- PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -- PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -- PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -- PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -- PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -- PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -- PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -- PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -- PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -- -- PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -- PREFIX(POWER_NONE) = 0 --}; -- --#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/power.h b/arch/arm/mach-bcm2708/include/mach/power.h -deleted file mode 100644 -index 52b3b02..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/power.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#ifndef _MACH_BCM2708_POWER_H --#define _MACH_BCM2708_POWER_H -- --#include --#include -- --typedef unsigned int BCM_POWER_HANDLE_T; -- --extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); --extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); --extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -- --#endif -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -deleted file mode 100644 -index 796837f..0000000 ---- a/arch/arm/mach-bcm2708/power.c -+++ /dev/null -@@ -1,201 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#include --#include --#include --#include --#include --#include -- --#define DRIVER_NAME "bcm2708_power" -- --#define BCM_POWER_MAXCLIENTS 4 --#define BCM_POWER_NOCLIENT (1<<31) -- --/* Some drivers expect there devices to be permanently powered */ -- --#ifdef CONFIG_USB --#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) --#endif -- --#if 1 --#define DPRINTK printk --#else --#define DPRINTK if (0) printk --#endif -- --struct state_struct { -- uint32_t global_request; -- uint32_t client_request[BCM_POWER_MAXCLIENTS]; -- struct semaphore client_mutex; -- struct semaphore mutex; --} g_state; -- --int bcm_power_open(BCM_POWER_HANDLE_T *handle) --{ -- BCM_POWER_HANDLE_T i; -- int ret = -EBUSY; -- -- down(&g_state.client_mutex); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -- g_state.client_request[i] = BCM_POWER_NONE; -- *handle = i; -- ret = 0; -- break; -- } -- } -- -- up(&g_state.client_mutex); -- -- DPRINTK("bcm_power_open() -> %d\n", *handle); -- -- return ret; --} --EXPORT_SYMBOL_GPL(bcm_power_open); -- --int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) --{ -- int rc = 0; -- -- DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -- -- if ((handle < BCM_POWER_MAXCLIENTS) && -- (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -- if (down_interruptible(&g_state.mutex) != 0) { -- DPRINTK("bcm_power_request -> interrupted\n"); -- return -EINTR; -- } -- -- if (request != g_state.client_request[handle]) { -- uint32_t others_request = 0; -- uint32_t global_request; -- BCM_POWER_HANDLE_T i; -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (i != handle) -- others_request |= -- g_state.client_request[i]; -- } -- others_request &= ~BCM_POWER_NOCLIENT; -- -- global_request = request | others_request; -- if (global_request != g_state.global_request) { -- uint32_t actual; -- -- /* Send a request to VideoCore */ -- bcm_mailbox_write(MBOX_CHAN_POWER, -- global_request << 4); -- -- /* Wait for a response during power-up */ -- if (global_request & ~g_state.global_request) { -- rc = bcm_mailbox_read(MBOX_CHAN_POWER, -- &actual); -- DPRINTK -- ("bcm_mailbox_read -> %08x, %d\n", -- actual, rc); -- actual >>= 4; -- } else { -- rc = 0; -- actual = global_request; -- } -- -- if (rc == 0) { -- if (actual != global_request) { -- printk(KERN_ERR -- "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -- __func__, -- g_state.global_request, -- global_request, actual, request, others_request); -- /* A failure */ -- BUG_ON((others_request & actual) -- != others_request); -- request &= actual; -- rc = -EIO; -- } -- -- g_state.global_request = actual; -- g_state.client_request[handle] = -- request; -- } -- } -- } -- up(&g_state.mutex); -- } else { -- rc = -EINVAL; -- } -- DPRINTK("bcm_power_request -> %d\n", rc); -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_request); -- --int bcm_power_close(BCM_POWER_HANDLE_T handle) --{ -- int rc; -- -- DPRINTK("bcm_power_close(%d)\n", handle); -- -- rc = bcm_power_request(handle, BCM_POWER_NONE); -- if (rc == 0) -- g_state.client_request[handle] = BCM_POWER_NOCLIENT; -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_close); -- --static int __init bcm_power_init(void) --{ --#if defined(BCM_POWER_ALWAYS_ON) -- BCM_POWER_HANDLE_T always_on_handle; --#endif -- int rc = 0; -- int i; -- -- printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -- g_state.client_request[i] = BCM_POWER_NOCLIENT; -- -- sema_init(&g_state.client_mutex, 1); -- sema_init(&g_state.mutex, 1); -- -- g_state.global_request = 0; -- --#if defined(BCM_POWER_ALWAYS_ON) -- if (BCM_POWER_ALWAYS_ON) { -- bcm_power_open(&always_on_handle); -- bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -- } --#endif -- -- return rc; --} -- --static void __exit bcm_power_exit(void) --{ -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); --} -- --/* -- * Load after the mailbox driver is initialized (arch_initcall), -- * but before depending drivers (module_init). -- */ --subsys_initcall(bcm_power_init); --module_exit(bcm_power_exit); -- --MODULE_AUTHOR("Phil Elwell"); --MODULE_DESCRIPTION("Interface to BCM2708 power management"); --MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 77b8429..706116f 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o power.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/arm_power.h b/arch/arm/mach-bcm2709/include/mach/arm_power.h -deleted file mode 100644 -index d3bf245..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/arm_power.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _ARM_POWER_H --#define _ARM_POWER_H -- --/* Use meaningful names on each side */ --#ifdef __VIDEOCORE__ --#define PREFIX(x) ARM_##x --#else --#define PREFIX(x) BCM_##x --#endif -- --enum { -- PREFIX(POWER_SDCARD_BIT), -- PREFIX(POWER_UART_BIT), -- PREFIX(POWER_MINIUART_BIT), -- PREFIX(POWER_USB_BIT), -- PREFIX(POWER_I2C0_BIT), -- PREFIX(POWER_I2C1_BIT), -- PREFIX(POWER_I2C2_BIT), -- PREFIX(POWER_SPI_BIT), -- PREFIX(POWER_CCP2TX_BIT), -- PREFIX(POWER_DSI_BIT), -- -- PREFIX(POWER_MAX) --}; -- --enum { -- PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -- PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -- PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -- PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -- PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -- PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -- PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -- PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -- PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -- PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -- -- PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -- PREFIX(POWER_NONE) = 0 --}; -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/power.h b/arch/arm/mach-bcm2709/include/mach/power.h -deleted file mode 100644 -index 52b3b02..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/power.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#ifndef _MACH_BCM2708_POWER_H --#define _MACH_BCM2708_POWER_H -- --#include --#include -- --typedef unsigned int BCM_POWER_HANDLE_T; -- --extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); --extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); --extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -- --#endif -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -deleted file mode 100644 -index 960e472..0000000 ---- a/arch/arm/mach-bcm2709/power.c -+++ /dev/null -@@ -1,199 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#include --#include --#include --#include --#include --#include -- --#define DRIVER_NAME "bcm2708_power" -- --#define BCM_POWER_MAXCLIENTS 4 --#define BCM_POWER_NOCLIENT (1<<31) -- --/* Some drivers expect there devices to be permanently powered */ --#ifdef CONFIG_USB --#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) --#endif -- --#if 1 --#define DPRINTK printk --#else --#define DPRINTK if (0) printk --#endif -- --struct state_struct { -- uint32_t global_request; -- uint32_t client_request[BCM_POWER_MAXCLIENTS]; -- struct semaphore client_mutex; -- struct semaphore mutex; --} g_state; -- --int bcm_power_open(BCM_POWER_HANDLE_T *handle) --{ -- BCM_POWER_HANDLE_T i; -- int ret = -EBUSY; -- -- down(&g_state.client_mutex); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -- g_state.client_request[i] = BCM_POWER_NONE; -- *handle = i; -- ret = 0; -- break; -- } -- } -- -- up(&g_state.client_mutex); -- -- DPRINTK("bcm_power_open() -> %d\n", *handle); -- -- return ret; --} --EXPORT_SYMBOL_GPL(bcm_power_open); -- --int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) --{ -- int rc = 0; -- -- DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -- -- if ((handle < BCM_POWER_MAXCLIENTS) && -- (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -- if (down_interruptible(&g_state.mutex) != 0) { -- DPRINTK("bcm_power_request -> interrupted\n"); -- return -EINTR; -- } -- -- if (request != g_state.client_request[handle]) { -- uint32_t others_request = 0; -- uint32_t global_request; -- BCM_POWER_HANDLE_T i; -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (i != handle) -- others_request |= -- g_state.client_request[i]; -- } -- others_request &= ~BCM_POWER_NOCLIENT; -- -- global_request = request | others_request; -- if (global_request != g_state.global_request) { -- uint32_t actual; -- -- /* Send a request to VideoCore */ -- bcm_mailbox_write(MBOX_CHAN_POWER, -- global_request << 4); -- -- /* Wait for a response during power-up */ -- if (global_request & ~g_state.global_request) { -- rc = bcm_mailbox_read(MBOX_CHAN_POWER, -- &actual); -- DPRINTK -- ("bcm_mailbox_read -> %08x, %d\n", -- actual, rc); -- actual >>= 4; -- } else { -- rc = 0; -- actual = global_request; -- } -- -- if (rc == 0) { -- if (actual != global_request) { -- printk(KERN_ERR -- "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -- __func__, -- g_state.global_request, -- global_request, actual, request, others_request); -- /* A failure */ -- BUG_ON((others_request & actual) -- != others_request); -- request &= actual; -- rc = -EIO; -- } -- -- g_state.global_request = actual; -- g_state.client_request[handle] = -- request; -- } -- } -- } -- up(&g_state.mutex); -- } else { -- rc = -EINVAL; -- } -- DPRINTK("bcm_power_request -> %d\n", rc); -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_request); -- --int bcm_power_close(BCM_POWER_HANDLE_T handle) --{ -- int rc; -- -- DPRINTK("bcm_power_close(%d)\n", handle); -- -- rc = bcm_power_request(handle, BCM_POWER_NONE); -- if (rc == 0) -- g_state.client_request[handle] = BCM_POWER_NOCLIENT; -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_close); -- --static int __init bcm_power_init(void) --{ --#if defined(BCM_POWER_ALWAYS_ON) -- BCM_POWER_HANDLE_T always_on_handle; --#endif -- int rc = 0; -- int i; -- -- printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -- g_state.client_request[i] = BCM_POWER_NOCLIENT; -- -- sema_init(&g_state.client_mutex, 1); -- sema_init(&g_state.mutex, 1); -- -- g_state.global_request = 0; --#if defined(BCM_POWER_ALWAYS_ON) -- if (BCM_POWER_ALWAYS_ON) { -- bcm_power_open(&always_on_handle); -- bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -- } --#endif -- -- return rc; --} -- --static void __exit bcm_power_exit(void) --{ -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); --} -- --/* -- * Load after the mailbox driver is initialized (arch_initcall), -- * but before depending drivers (module_init). -- */ --subsys_initcall(bcm_power_init); --module_exit(bcm_power_exit); -- --MODULE_AUTHOR("Phil Elwell"); --MODULE_DESCRIPTION("Interface to BCM2708 power management"); --MODULE_LICENSE("GPL"); -diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index 76d6bd4..aed58f4 100644 ---- a/drivers/soc/Kconfig -+++ b/drivers/soc/Kconfig -@@ -1,5 +1,6 @@ - menu "SOC (System On Chip) specific Drivers" - -+source "drivers/soc/bcm2835/Kconfig" - source "drivers/soc/qcom/Kconfig" - source "drivers/soc/ti/Kconfig" - source "drivers/soc/versatile/Kconfig" -diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index 063113d..897de0c5 100644 ---- a/drivers/soc/Makefile -+++ b/drivers/soc/Makefile -@@ -2,6 +2,7 @@ - # Makefile for the Linux Kernel SOC specific device drivers. - # - -+obj-y += bcm2835/ - obj-$(CONFIG_ARCH_QCOM) += qcom/ - obj-$(CONFIG_ARCH_TEGRA) += tegra/ - obj-$(CONFIG_SOC_TI) += ti/ -diff --git a/drivers/soc/bcm2835/Kconfig b/drivers/soc/bcm2835/Kconfig -new file mode 100644 -index 0000000..c2980f3 ---- /dev/null -+++ b/drivers/soc/bcm2835/Kconfig -@@ -0,0 +1,9 @@ -+# -+# BCM2835 Soc drivers -+# -+config BCM2708_POWER -+ tristate "BCM2708 legacy power driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX -+ default y -+ help -+ Turns on USB power and provides an API for controlling power. -diff --git a/drivers/soc/bcm2835/Makefile b/drivers/soc/bcm2835/Makefile -new file mode 100644 -index 0000000..3614ad9 ---- /dev/null -+++ b/drivers/soc/bcm2835/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_BCM2708_POWER) += bcm2708-power.o -diff --git a/drivers/soc/bcm2835/bcm2708-power.c b/drivers/soc/bcm2835/bcm2708-power.c -new file mode 100644 -index 0000000..e7931a9 ---- /dev/null -+++ b/drivers/soc/bcm2835/bcm2708-power.c -@@ -0,0 +1,200 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+ -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); -diff --git a/include/soc/bcm2835/power.h b/include/soc/bcm2835/power.h -new file mode 100644 -index 0000000..bf22b26 ---- /dev/null -+++ b/include/soc/bcm2835/power.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#ifndef _BCM2708_POWER_H -+#define _BCM2708_POWER_H -+ -+#include -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif - -From 7ea54e2541e0445c98c3b5bb4b0e80af76c5c197 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 23 May 2015 23:31:40 +0200 -Subject: [PATCH 186/216] bcm2835: Use empty bootargs in Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The VideoCore bootloader concatenates the bootargs property together -with /boot/cmdline.txt and includes it's own set of options. -Set bootargs to an empty string to behave like BCM270x. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 72d0354..40fc759 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -6,7 +6,7 @@ - interrupt-parent = <&intc>; - - chosen { -- bootargs = "earlyprintk console=ttyAMA0"; -+ bootargs = ""; - }; - - soc { - -From b340f9126d88eafd83e2ae6e0b593bea562f92f5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 187/216] scripts: Add mkknlimg and knlinfo scripts from tools - repo - -The Raspberry Pi firmware looks for a trailer on the kernel image to -determine whether it was compiled with Device Tree support enabled. -If the firmware finds a kernel without this trailer, or which has a -trailer indicating that it isn't DT-capable, it disables DT support -and reverts to using ATAGs. - -The mkknlimg utility adds that trailer, having first analysed the -image to look for signs of DT support and the kernel version string. - -knlinfo displays the contents of the trailer in the given kernel image. ---- - scripts/knlinfo | 167 +++++++++++++++++++++++++++++++++++ - scripts/mkknlimg | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 427 insertions(+) - create mode 100755 scripts/knlinfo - create mode 100755 scripts/mkknlimg - -diff --git a/scripts/knlinfo b/scripts/knlinfo -new file mode 100755 -index 0000000..9c9b42e3 ---- /dev/null -+++ b/scripts/knlinfo -@@ -0,0 +1,167 @@ -+#!/usr/bin/env perl -+# ---------------------------------------------------------------------- -+# knlinfo by Phil Elwell for Raspberry Pi -+# -+# (c) 2014,2015 Raspberry Pi (Trading) Limited -+# -+# Licensed under the terms of the GNU General Public License. -+# ---------------------------------------------------------------------- -+ -+use strict; -+use integer; -+ -+use Fcntl ":seek"; -+ -+my $trailer_magic = 'RPTL'; -+ -+my %atom_formats = -+( -+ 'DTOK' => \&format_bool, -+ 'KVer' => \&format_string, -+); -+ -+if (@ARGV != 1) -+{ -+ print ("Usage: knlinfo \n"); -+ exit(1); -+} -+ -+my $kernel_file = $ARGV[0]; -+ -+ -+my ($atoms, $pos) = read_trailer($kernel_file); -+ -+exit(1) if (!$atoms); -+ -+printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos); -+ -+foreach my $atom (@$atoms) -+{ -+ printf(" %s: %s\n", $atom->[0], format_atom($atom)); -+} -+ -+exit(0); -+ -+sub read_trailer -+{ -+ my ($kernel_file) = @_; -+ my $fh; -+ -+ if (!open($fh, '<', $kernel_file)) -+ { -+ print ("* Failed to open '$kernel_file'\n"); -+ return undef; -+ } -+ -+ if (!seek($fh, -12, SEEK_END)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ my $last_bytes; -+ sysread($fh, $last_bytes, 12); -+ -+ my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes); -+ -+ if (($magic ne $trailer_magic) || ($data_len != 4)) -+ { -+ print ("* no trailer\n"); -+ return undef; -+ } -+ if (!seek($fh, -12, SEEK_END)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ $trailer_len -= 12; -+ -+ while ($trailer_len > 0) -+ { -+ if ($trailer_len < 8) -+ { -+ print ("* truncated atom header in trailer\n"); -+ return undef; -+ } -+ if (!seek($fh, -8, SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ $trailer_len -= 8; -+ -+ my $atom_hdr; -+ sysread($fh, $atom_hdr, 8); -+ my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr); -+ -+ if ($trailer_len < $atom_len) -+ { -+ print ("* truncated atom data in trailer\n"); -+ return undef; -+ } -+ -+ my $rounded_len = (($atom_len + 3) & ~3); -+ if (!seek($fh, -(8 + $rounded_len), SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ $trailer_len -= $rounded_len; -+ -+ my $atom_data; -+ sysread($fh, $atom_data, $atom_len); -+ -+ if (!seek($fh, -$atom_len, SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ push @$atoms, [ $atom_type, $atom_data ]; -+ } -+ -+ if (($$atoms[-1][0] eq "\x00\x00\x00\x00") && -+ ($$atoms[-1][1] eq "")) -+ { -+ pop @$atoms; -+ } -+ else -+ { -+ print ("* end marker missing from trailer\n"); -+ } -+ -+ return ($atoms, tell($fh)); -+} -+ -+sub format_atom -+{ -+ my ($atom) = @_; -+ -+ my $format_func = $atom_formats{$atom->[0]} || \&format_hex; -+ return $format_func->($atom->[1]); -+} -+ -+sub format_bool -+{ -+ my ($data) = @_; -+ return unpack('V', $data) ? 'true' : 'false'; -+} -+ -+sub format_int -+{ -+ my ($data) = @_; -+ return unpack('V', $data); -+} -+ -+sub format_string -+{ -+ my ($data) = @_; -+ return '"'.$data.'"'; -+} -+ -+sub format_hex -+{ -+ my ($data) = @_; -+ return unpack('H*', $data); -+} -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -new file mode 100755 -index 0000000..ac829d0 ---- /dev/null -+++ b/scripts/mkknlimg -@@ -0,0 +1,260 @@ -+#!/usr/bin/env perl -+# ---------------------------------------------------------------------- -+# mkknlimg by Phil Elwell for Raspberry Pi -+# based on extract-ikconfig Dick Streefland -+# -+# (c) 2009,2010 Dick Streefland -+# (c) 2014,2015 Raspberry Pi (Trading) Limited -+# -+# Licensed under the terms of the GNU General Public License. -+# ---------------------------------------------------------------------- -+ -+use strict; -+use warnings; -+use integer; -+ -+my $trailer_magic = 'RPTL'; -+ -+my $tmpfile1 = "/tmp/mkknlimg_$$.1"; -+my $tmpfile2 = "/tmp/mkknlimg_$$.2"; -+ -+my $dtok = 0; -+ -+while (@ARGV && ($ARGV[0] =~ /^-/)) -+{ -+ my $arg = shift(@ARGV); -+ if ($arg eq '--dtok') -+ { -+ $dtok = 1; -+ } -+ else -+ { -+ print ("* Unknown option '$arg'\n"); -+ usage(); -+ } -+} -+ -+usage() if (@ARGV != 2); -+ -+my $kernel_file = $ARGV[0]; -+my $out_file = $ARGV[1]; -+ -+if (! -r $kernel_file) -+{ -+ print ("* File '$kernel_file' not found\n"); -+ usage(); -+} -+ -+my @wanted_config_lines = -+( -+ 'CONFIG_BCM2708_DT' -+); -+ -+my @wanted_strings = -+( -+ 'bcm2708_fb', -+ 'brcm,bcm2708-pinctrl', -+ 'brcm,bcm2835-gpio', -+ 'of_find_property' -+); -+ -+my $res = try_extract($kernel_file, $tmpfile1); -+$res = try_decompress('\037\213\010', 'xy', 'gunzip', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('BZh', 'xy', 'bunzip2', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\211\114\132', 'xy', 'lzop -d', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+ -+my $append_trailer; -+my $trailer; -+my $kver = '?'; -+ -+$append_trailer = $dtok; -+ -+if ($res) -+{ -+ $kver = $res->{''} || '?'; -+ print("Version: $kver\n"); -+ -+ $append_trailer = $dtok; -+ if (!$dtok) -+ { -+ if (config_bool($res, 'bcm2708_fb')) -+ { -+ $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); -+ $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); -+ $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); -+ $append_trailer = 1; -+ } -+ else -+ { -+ print ("* This doesn't look like a Raspberry Pi kernel. In pass-through mode.\n"); -+ } -+ } -+} -+elsif (!$dtok) -+{ -+ print ("* Is this a valid kernel? In pass-through mode.\n"); -+} -+ -+if ($append_trailer) -+{ -+ printf("DT: %s\n", $dtok ? "y" : "n"); -+ -+ my @atoms; -+ -+ push @atoms, [ $trailer_magic, pack('V', 0) ]; -+ push @atoms, [ 'KVer', $kver ]; -+ push @atoms, [ 'DTOK', pack('V', $dtok) ]; -+ -+ $trailer = pack_trailer(\@atoms); -+ $atoms[0]->[1] = pack('V', length($trailer)); -+ -+ $trailer = pack_trailer(\@atoms); -+} -+ -+my $ofh; -+my $total_len = 0; -+ -+if ($out_file eq $kernel_file) -+{ -+ die "* Failed to open '$out_file' for append\n" -+ if (!open($ofh, '>>', $out_file)); -+ $total_len = tell($ofh); -+} -+else -+{ -+ die "* Failed to open '$kernel_file'\n" -+ if (!open(my $ifh, '<', $kernel_file)); -+ die "* Failed to create '$out_file'\n" -+ if (!open($ofh, '>', $out_file)); -+ -+ my $copybuf; -+ while (1) -+ { -+ my $bytes = sysread($ifh, $copybuf, 64*1024); -+ last if (!$bytes); -+ syswrite($ofh, $copybuf, $bytes); -+ $total_len += $bytes; -+ } -+ close($ifh); -+} -+ -+if ($trailer) -+{ -+ # Pad to word-alignment -+ syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3)); -+ syswrite($ofh, $trailer); -+} -+ -+close($ofh); -+ -+exit($trailer ? 0 : 1); -+ -+END { -+ unlink($tmpfile1) if ($tmpfile1); -+ unlink($tmpfile2) if ($tmpfile2); -+} -+ -+ -+sub usage -+{ -+ print ("Usage: mkknlimg [--dtok] \n"); -+ exit(1); -+} -+ -+sub try_extract -+{ -+ my ($knl, $tmp) = @_; -+ -+ my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`; -+ -+ return undef if (!$ver); -+ -+ chomp($ver); -+ -+ my $res = { ''=>$ver }; -+ my $string_pattern = '^('.join('|', @wanted_strings).')$'; -+ -+ my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`; -+ foreach my $match (@matches) -+ { -+ chomp($match); -+ $res->{$match} = 1; -+ } -+ -+ my $config_pattern = '^('.join('|', @wanted_config_lines).')=(.*)$'; -+ my $cf1 = 'IKCFG_ST\037\213\010'; -+ my $cf2 = '0123456789'; -+ -+ my $pos = `tr "$cf1\n$cf2" "\n$cf2=" < "$knl" | grep -abo "^$cf2"`; -+ if ($pos) -+ { -+ $pos =~ s/:.*[\r\n]*$//s; -+ $pos += 8; -+ my $err = (system("tail -c+$pos \"$knl\" | zcat > $tmp 2> /dev/null") >> 8); -+ if (($err == 0) || ($err == 2)) -+ { -+ if (open(my $fh, '<', $tmp)) -+ { -+ while (my $line = <$fh>) -+ { -+ chomp($line); -+ $res->{$1} = $2 if ($line =~ /$config_pattern/); -+ } -+ -+ close($fh); -+ } -+ } -+ } -+ -+ return $res; -+} -+ -+ -+sub try_decompress -+{ -+ my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_; -+ -+ my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`; -+ if ($pos) -+ { -+ chomp($pos); -+ $pos = (split(/[\r\n]+/, $pos))[$idx]; -+ return undef if (!defined($pos)); -+ $pos =~ s/:.*[\r\n]*$//s; -+ my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null"; -+ my $err = (system($cmd) >> 8); -+ return undef if (($err != 0) && ($err != 2)); -+ -+ return try_extract($tmp2, $tmp1); -+ } -+ -+ return undef; -+} -+ -+sub pack_trailer -+{ -+ my ($atoms) = @_; -+ my $trailer = pack('VV', 0, 0); -+ for (my $i = $#$atoms; $i>=0; $i--) -+ { -+ my $atom = $atoms->[$i]; -+ $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]); -+ } -+ return $trailer; -+} -+ -+sub config_bool -+{ -+ my ($configs, $wanted) = @_; -+ my $val = $configs->{$wanted} || 'n'; -+ return (($val eq 'y') || ($val eq '1')); -+} - -From 2ab7f22fc98a7e6f66c3924d0eff9a721b159029 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 18:35:44 +0100 -Subject: [PATCH 188/216] scripts/mkknlimg: Add support for ARCH_BCM2835 - -Add a new trailer field indicating whether this is an ARCH_BCM2835 -build, as opposed to MACH_BCM2708/9. If the loader finds this flag -is set it changes the default base dtb file name from bcm270x... -to bcm283y... - -Also update knlinfo to show the status of the field. ---- - scripts/knlinfo | 1 + - scripts/mkknlimg | 25 ++++++++++++++++++++----- - 2 files changed, 21 insertions(+), 5 deletions(-) - -diff --git a/scripts/knlinfo b/scripts/knlinfo -index 9c9b42e3..a0e8663 100755 ---- a/scripts/knlinfo -+++ b/scripts/knlinfo -@@ -18,6 +18,7 @@ my %atom_formats = - ( - 'DTOK' => \&format_bool, - 'KVer' => \&format_string, -+ '283x' => \&format_bool, - ); - - if (@ARGV != 1) -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index ac829d0..3dff948 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -1,7 +1,7 @@ - #!/usr/bin/env perl - # ---------------------------------------------------------------------- - # mkknlimg by Phil Elwell for Raspberry Pi --# based on extract-ikconfig Dick Streefland -+# based on extract-ikconfig by Dick Streefland - # - # (c) 2009,2010 Dick Streefland - # (c) 2014,2015 Raspberry Pi (Trading) Limited -@@ -19,6 +19,7 @@ my $tmpfile1 = "/tmp/mkknlimg_$$.1"; - my $tmpfile2 = "/tmp/mkknlimg_$$.2"; - - my $dtok = 0; -+my $is_283x = 0; - - while (@ARGV && ($ARGV[0] =~ /^-/)) - { -@@ -27,6 +28,10 @@ while (@ARGV && ($ARGV[0] =~ /^-/)) - { - $dtok = 1; - } -+ elsif ($arg eq '--283x') -+ { -+ $is_283x = 1; -+ } - else - { - print ("* Unknown option '$arg'\n"); -@@ -47,15 +52,18 @@ if (! -r $kernel_file) - - my @wanted_config_lines = - ( -- 'CONFIG_BCM2708_DT' -+ 'CONFIG_BCM2708_DT', -+ 'CONFIG_ARCH_BCM2835' - ); - - my @wanted_strings = - ( - 'bcm2708_fb', -+ 'brcm,bcm2835-mmc', -+ 'brcm,bcm2835-sdhost', - 'brcm,bcm2708-pinctrl', - 'brcm,bcm2835-gpio', -- 'of_find_property' -+ 'brcm,bcm2835-pm-wdt' - ); - - my $res = try_extract($kernel_file, $tmpfile1); -@@ -86,11 +94,16 @@ if ($res) - $append_trailer = $dtok; - if (!$dtok) - { -- if (config_bool($res, 'bcm2708_fb')) -+ if (config_bool($res, 'bcm2708_fb') || -+ config_bool($res, 'brcm,bcm2835-mmc') || -+ config_bool($res, 'brcm,bcm2835-sdhost')) - { - $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); -+ $dtok ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); - $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); - $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); -+ $is_283x ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); -+ $is_283x ||= config_bool($res, 'brcm,bcm2835-pm-wdt'); - $append_trailer = 1; - } - else -@@ -107,12 +120,14 @@ elsif (!$dtok) - if ($append_trailer) - { - printf("DT: %s\n", $dtok ? "y" : "n"); -+ printf("283x: %s\n", $is_283x ? "y" : "n"); - - my @atoms; - - push @atoms, [ $trailer_magic, pack('V', 0) ]; - push @atoms, [ 'KVer', $kver ]; - push @atoms, [ 'DTOK', pack('V', $dtok) ]; -+ push @atoms, [ '283x', pack('V', $is_283x) ]; - - $trailer = pack_trailer(\@atoms); - $atoms[0]->[1] = pack('V', length($trailer)); -@@ -166,7 +181,7 @@ END { - - sub usage - { -- print ("Usage: mkknlimg [--dtok] \n"); -+ print ("Usage: mkknlimg [--dtok] [--283x] \n"); - exit(1); - } - - -From 73bb23f8980890aad84dc6b852f0aac91ab71981 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 10 Mar 2015 18:35:18 +0100 -Subject: [PATCH 189/216] config: add KEYBOARD_GPIO - ---- - arch/arm/configs/bcm2709_defconfig | 3 ++- - arch/arm/configs/bcmrpi_defconfig | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 9daaeb7..5ce9a01 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -520,7 +520,8 @@ CONFIG_INPUT_POLLDEV=m - # CONFIG_INPUT_MOUSEDEV_PSAUX is not set - CONFIG_INPUT_JOYDEV=m - CONFIG_INPUT_EVDEV=m --# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y - CONFIG_JOYSTICK_IFORCE=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index dc27aeb..da443da 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -513,7 +513,8 @@ CONFIG_INPUT_POLLDEV=m - # CONFIG_INPUT_MOUSEDEV_PSAUX is not set - CONFIG_INPUT_JOYDEV=m - CONFIG_INPUT_EVDEV=m --# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y - CONFIG_JOYSTICK_IFORCE=m - -From d7d347201d595ccc495da617ab583fdb3e282829 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 10 Mar 2015 18:35:59 +0100 -Subject: [PATCH 190/216] dts: overlay: add support for tinylcd.com 3.5" - display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for 3.5" display by tinylcd.com - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/tinylcd35-overlay.dts | 216 ++++++++++++++++++++++++++++++++ - 2 files changed, 217 insertions(+) - create mode 100644 arch/arm/boot/dts/tinylcd35-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 9124dfb..25ea8eb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -38,6 +38,7 @@ dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -diff --git a/arch/arm/boot/dts/tinylcd35-overlay.dts b/arch/arm/boot/dts/tinylcd35-overlay.dts -new file mode 100644 -index 0000000..f7102c8 ---- /dev/null -+++ b/arch/arm/boot/dts/tinylcd35-overlay.dts -@@ -0,0 +1,216 @@ -+/* -+ * tinylcd35-overlay.dts -+ * -+ * ------------------------------------------------- -+ * www.tinlylcd.com -+ * ------------------------------------------------- -+ * Device---Driver-----BUS GPIO's -+ * display tinylcd35 spi0.0 25 24 18 -+ * touch ads7846 spi0.1 5 -+ * rtc ds1307 i2c1-0068 -+ * rtc pcf8563 i2c1-0051 -+ * keypad gpio-keys --------- 17 22 27 23 28 -+ * -+ * -+ * TinyLCD.com 3.5 inch TFT -+ * -+ * Version 001 -+ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -+ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ tinylcd35_pins: tinylcd35_pins { -+ brcm,pins = <25 24 18>; -+ brcm,function = <1>; /* out */ -+ }; -+ tinylcd35_ts_pins: tinylcd35_ts_pins { -+ brcm,pins = <5>; -+ brcm,function = <0>; /* in */ -+ }; -+ keypad_pins: keypad_pins { -+ brcm,pins = <4 17 22 23 27>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <1>; /* down */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ tinylcd35: tinylcd35@0{ -+ compatible = "neosec,tinylcd"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&tinylcd35_pins>, -+ <&tinylcd35_ts_pins>; -+ -+ spi-max-frequency = <48000000>; -+ rotate = <270>; -+ fps = <20>; -+ bgr; -+ buswidth = <8>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ -+ init = <0x10000B0 0x80 -+ 0x10000C0 0x0A 0x0A -+ 0x10000C1 0x01 0x01 -+ 0x10000C2 0x33 -+ 0x10000C5 0x00 0x42 0x80 -+ 0x10000B1 0xD0 0x11 -+ 0x10000B4 0x02 -+ 0x10000B6 0x00 0x22 0x3B -+ 0x10000B7 0x07 -+ 0x1000036 0x58 -+ 0x10000F0 0x36 0xA5 0xD3 -+ 0x10000E5 0x80 -+ 0x10000E5 0x01 -+ 0x10000B3 0x00 -+ 0x10000E5 0x00 -+ 0x10000F0 0x36 0xA5 0x53 -+ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -+ 0x100003A 0x55 -+ 0x1000011 -+ 0x2000001 -+ 0x1000029>; -+ }; -+ -+ tinylcd35_ts: tinylcd35_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ status = "disabled"; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <5 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 5 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ -+ /* RTC */ -+ -+ fragment@3 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* -+ * Values for input event code is found under the -+ * 'Keys and buttons' heading in include/uapi/linux/input.h -+ */ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ keypad: keypad { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&keypad_pins>; -+ status = "disabled"; -+ autorepeat; -+ -+ button@17 { -+ label = "GPIO KEY_UP"; -+ linux,code = <103>; -+ gpios = <&gpio 17 0>; -+ }; -+ button@22 { -+ label = "GPIO KEY_DOWN"; -+ linux,code = <108>; -+ gpios = <&gpio 22 0>; -+ }; -+ button@27 { -+ label = "GPIO KEY_LEFT"; -+ linux,code = <105>; -+ gpios = <&gpio 27 0>; -+ }; -+ button@23 { -+ label = "GPIO KEY_RIGHT"; -+ linux,code = <106>; -+ gpios = <&gpio 23 0>; -+ }; -+ button@4 { -+ label = "GPIO KEY_ENTER"; -+ linux,code = <28>; -+ gpios = <&gpio 4 0>; -+ }; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&tinylcd35>,"spi-max-frequency:0"; -+ rotate = <&tinylcd35>,"rotate:0"; -+ fps = <&tinylcd35>,"fps:0"; -+ debug = <&tinylcd35>,"debug:0"; -+ touch = <&tinylcd35_ts>,"status"; -+ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -+ <&tinylcd35_ts>,"interrupts:0", -+ <&tinylcd35_ts>,"pendown-gpio:4"; -+ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -+ rtc-pcf = <&i2c1>,"status", -+ <&pcf8563>,"status"; -+ rtc-ds = <&i2c1>,"status", -+ <&ds1307>,"status"; -+ keypad = <&keypad>,"status"; -+ }; -+}; - -From 4b843d5be018d8d392a4be34a7fdfe3640e3c2a7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 29 May 2015 14:16:47 +0100 -Subject: [PATCH 191/216] BCM270X_DT: Move the overlays into a subdirectory, - adding the README - ---- - arch/arm/boot/dts/Makefile | 31 +- - arch/arm/boot/dts/ads7846-overlay.dts | 83 ---- - arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts | 23 - - arch/arm/boot/dts/ds1307-rtc-overlay.dts | 22 - - arch/arm/boot/dts/enc28j60-overlay.dts | 29 -- - arch/arm/boot/dts/hifiberry-amp-overlay.dts | 39 -- - arch/arm/boot/dts/hifiberry-dac-overlay.dts | 34 -- - arch/arm/boot/dts/hifiberry-dacplus-overlay.dts | 39 -- - arch/arm/boot/dts/hifiberry-digi-overlay.dts | 39 -- - arch/arm/boot/dts/hy28a-overlay.dts | 87 ---- - arch/arm/boot/dts/hy28b-overlay.dts | 142 ------- - arch/arm/boot/dts/i2c-rtc-overlay.dts | 43 -- - arch/arm/boot/dts/iqaudio-dac-overlay.dts | 39 -- - arch/arm/boot/dts/iqaudio-dacplus-overlay.dts | 39 -- - arch/arm/boot/dts/lirc-rpi-overlay.dts | 57 --- - arch/arm/boot/dts/mmc-overlay.dts | 19 - - arch/arm/boot/dts/mz61581-overlay.dts | 109 ----- - arch/arm/boot/dts/overlays/Makefile | 51 +++ - arch/arm/boot/dts/overlays/README | 470 +++++++++++++++++++++ - arch/arm/boot/dts/overlays/ads7846-overlay.dts | 83 ++++ - .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + - arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 29 ++ - .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 ++ - .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 ++ - .../dts/overlays/hifiberry-dacplus-overlay.dts | 39 ++ - .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/hy28a-overlay.dts | 87 ++++ - arch/arm/boot/dts/overlays/hy28b-overlay.dts | 142 +++++++ - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 49 +++ - arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 39 ++ - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 +++ - arch/arm/boot/dts/overlays/mmc-overlay.dts | 19 + - arch/arm/boot/dts/overlays/mz61581-overlay.dts | 109 +++++ - arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 94 +++++ - .../dts/overlays/pitft28-resistive-overlay.dts | 115 +++++ - arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 34 ++ - arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 34 ++ - arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 82 ++++ - arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/sdhost-overlay.dts | 75 ++++ - arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts | 18 + - arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts | 18 + - arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 216 ++++++++++ - arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 ++ - .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 ++ - arch/arm/boot/dts/pcf2127-rtc-overlay.dts | 22 - - arch/arm/boot/dts/pcf8523-rtc-overlay.dts | 22 - - arch/arm/boot/dts/piscreen-overlay.dts | 94 ----- - arch/arm/boot/dts/pitft28-resistive-overlay.dts | 115 ----- - arch/arm/boot/dts/pps-gpio-overlay.dts | 34 -- - arch/arm/boot/dts/rpi-dac-overlay.dts | 34 -- - arch/arm/boot/dts/rpi-display-overlay.dts | 82 ---- - arch/arm/boot/dts/rpi-proto-overlay.dts | 39 -- - arch/arm/boot/dts/sdhost-overlay.dts | 75 ---- - arch/arm/boot/dts/spi-bcm2708-overlay.dts | 18 - - arch/arm/boot/dts/spi-bcm2835-overlay.dts | 18 - - arch/arm/boot/dts/tinylcd35-overlay.dts | 216 ---------- - arch/arm/boot/dts/w1-gpio-overlay.dts | 39 -- - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 41 -- - 63 files changed, 2220 insertions(+), 1722 deletions(-) - delete mode 100644 arch/arm/boot/dts/ads7846-overlay.dts - delete mode 100644 arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts - delete mode 100644 arch/arm/boot/dts/ds1307-rtc-overlay.dts - delete mode 100755 arch/arm/boot/dts/enc28j60-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-amp-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-dacplus-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-digi-overlay.dts - delete mode 100644 arch/arm/boot/dts/hy28a-overlay.dts - delete mode 100644 arch/arm/boot/dts/hy28b-overlay.dts - delete mode 100644 arch/arm/boot/dts/i2c-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/iqaudio-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/iqaudio-dacplus-overlay.dts - delete mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts - delete mode 100644 arch/arm/boot/dts/mmc-overlay.dts - delete mode 100644 arch/arm/boot/dts/mz61581-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/Makefile - create mode 100644 arch/arm/boot/dts/overlays/README - create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-display-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts - delete mode 100644 arch/arm/boot/dts/pcf2127-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/pcf8523-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/piscreen-overlay.dts - delete mode 100644 arch/arm/boot/dts/pitft28-resistive-overlay.dts - delete mode 100644 arch/arm/boot/dts/pps-gpio-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-display-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-proto-overlay.dts - delete mode 100644 arch/arm/boot/dts/sdhost-overlay.dts - delete mode 100644 arch/arm/boot/dts/spi-bcm2708-overlay.dts - delete mode 100644 arch/arm/boot/dts/spi-bcm2835-overlay.dts - delete mode 100644 arch/arm/boot/dts/tinylcd35-overlay.dts - delete mode 100644 arch/arm/boot/dts/w1-gpio-overlay.dts - delete mode 100644 arch/arm/boot/dts/w1-gpio-pullup-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 25ea8eb..ea93e1d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -13,36 +13,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - --dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb -+subdir-$(RPI_DT_OVERLAYS) += overlays - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/ads7846-overlay.dts b/arch/arm/boot/dts/ads7846-overlay.dts -deleted file mode 100644 -index 6a92cd1..0000000 ---- a/arch/arm/boot/dts/ads7846-overlay.dts -+++ /dev/null -@@ -1,83 +0,0 @@ --/* -- * Generic Device Tree overlay for the ADS7846 touch controller -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- ads7846_pins: ads7846_pins { -- brcm,pins = <255>; /* illegal default value */ -- brcm,function = <0>; /* in */ -- brcm,pull = <0>; /* none */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- ads7846: ads7846@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- pinctrl-names = "default"; -- pinctrl-0 = <&ads7846_pins>; -- -- spi-max-frequency = <2000000>; -- interrupts = <255 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 255 0>; -- -- /* driver defaults */ -- ti,x-min = /bits/ 16 <0>; -- ti,y-min = /bits/ 16 <0>; -- ti,x-max = /bits/ 16 <0x0FFF>; -- ti,y-max = /bits/ 16 <0x0FFF>; -- ti,pressure-min = /bits/ 16 <0>; -- ti,pressure-max = /bits/ 16 <0xFFFF>; -- ti,x-plate-ohms = /bits/ 16 <400>; -- }; -- }; -- }; -- __overrides__ { -- cs = <&ads7846>,"reg:0"; -- speed = <&ads7846>,"spi-max-frequency:0"; -- penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -- <&ads7846>,"interrupts:0", -- <&ads7846>,"pendown-gpio:4"; -- penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -- swapxy = <&ads7846>,"ti,swap-xy?"; -- xmin = <&ads7846>,"ti,x-min;0"; -- ymin = <&ads7846>,"ti,y-min;0"; -- xmax = <&ads7846>,"ti,x-max;0"; -- ymax = <&ads7846>,"ti,y-max;0"; -- pmin = <&ads7846>,"ti,pressure-min;0"; -- pmax = <&ads7846>,"ti,pressure-max;0"; -- xohms = <&ads7846>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -deleted file mode 100644 -index b830bf2..0000000 ---- a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -+++ /dev/null -@@ -1,23 +0,0 @@ --// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- bmp085@77 { -- compatible = "bosch,bmp085"; -- reg = <0x77>; -- default-oversampling = <3>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -deleted file mode 100644 -index 7d27044..0000000 ---- a/arch/arm/boot/dts/ds1307-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for DS1307 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/enc28j60-overlay.dts b/arch/arm/boot/dts/enc28j60-overlay.dts -deleted file mode 100755 -index aa9b645..0000000 ---- a/arch/arm/boot/dts/enc28j60-overlay.dts -+++ /dev/null -@@ -1,29 +0,0 @@ --// Overlay for the Microchip ENC28J60 Ethernet Controller --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- enc28j60@0{ -- compatible = "microchip,enc28j60"; -- reg = <0>; /* CE0 */ -- spi-max-frequency = <12000000>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -deleted file mode 100644 -index 2c81448..0000000 ---- a/arch/arm/boot/dts/hifiberry-amp-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry Amp/Amp+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-amp"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- tas5713@1b { -- #sound-dai-cells = <0>; -- compatible = "ti,tas5713"; -- reg = <0x1b>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -deleted file mode 100644 -index 5e7633a..0000000 ---- a/arch/arm/boot/dts/hifiberry-dac-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --// Definitions for HiFiBerry DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target-path = "/"; -- __overlay__ { -- pcm5102a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5102a"; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -deleted file mode 100644 -index deb9c625..0000000 ---- a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry DAC+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-dacplus"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4d { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4d>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -deleted file mode 100644 -index d0e0d8a..0000000 ---- a/arch/arm/boot/dts/hifiberry-digi-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry Digi --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-digi"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- wm8804@3b { -- #sound-dai-cells = <0>; -- compatible = "wlf,wm8804"; -- reg = <0x3b>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hy28a-overlay.dts b/arch/arm/boot/dts/hy28a-overlay.dts -deleted file mode 100644 -index 3cd3083..0000000 ---- a/arch/arm/boot/dts/hy28a-overlay.dts -+++ /dev/null -@@ -1,87 +0,0 @@ --/* -- * Device Tree overlay for HY28A display -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- hy28a_pins: hy28a_pins { -- brcm,pins = <17 25 18>; -- brcm,function = <0 1 1>; /* in out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- hy28a: hy28a@0{ -- compatible = "ilitek,ili9320"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&hy28a_pins>; -- -- spi-max-frequency = <32000000>; -- spi-cpol; -- spi-cpha; -- rotate = <270>; -- bgr; -- fps = <50>; -- buswidth = <8>; -- startbyte = <0x70>; -- reset-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- }; -- -- hy28a_ts: hy28a-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&hy28a>,"spi-max-frequency:0"; -- rotate = <&hy28a>,"rotate:0"; -- fps = <&hy28a>,"fps:0"; -- debug = <&hy28a>,"debug:0"; -- xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -- resetgpio = <&hy28a>,"reset-gpios:4", -- <&hy28a_pins>, "brcm,pins:1"; -- ledgpio = <&hy28a>,"led-gpios:4", -- <&hy28a_pins>, "brcm,pins:2"; -- }; --}; -diff --git a/arch/arm/boot/dts/hy28b-overlay.dts b/arch/arm/boot/dts/hy28b-overlay.dts -deleted file mode 100644 -index f774c4a..0000000 ---- a/arch/arm/boot/dts/hy28b-overlay.dts -+++ /dev/null -@@ -1,142 +0,0 @@ --/* -- * Device Tree overlay for HY28b display shield by Texy -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- hy28b_pins: hy28b_pins { -- brcm,pins = <17 25 18>; -- brcm,function = <0 1 1>; /* in out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- hy28b: hy28b@0{ -- compatible = "ilitek,ili9325"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&hy28b_pins>; -- -- spi-max-frequency = <48000000>; -- spi-cpol; -- spi-cpha; -- rotate = <270>; -- bgr; -- fps = <50>; -- buswidth = <8>; -- startbyte = <0x70>; -- reset-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 1>; -- -- gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -- -- init = <0x10000e7 0x0010 -- 0x1000000 0x0001 -- 0x1000001 0x0100 -- 0x1000002 0x0700 -- 0x1000003 0x1030 -- 0x1000004 0x0000 -- 0x1000008 0x0207 -- 0x1000009 0x0000 -- 0x100000a 0x0000 -- 0x100000c 0x0001 -- 0x100000d 0x0000 -- 0x100000f 0x0000 -- 0x1000010 0x0000 -- 0x1000011 0x0007 -- 0x1000012 0x0000 -- 0x1000013 0x0000 -- 0x2000032 -- 0x1000010 0x1590 -- 0x1000011 0x0227 -- 0x2000032 -- 0x1000012 0x009c -- 0x2000032 -- 0x1000013 0x1900 -- 0x1000029 0x0023 -- 0x100002b 0x000e -- 0x2000032 -- 0x1000020 0x0000 -- 0x1000021 0x0000 -- 0x2000032 -- 0x1000050 0x0000 -- 0x1000051 0x00ef -- 0x1000052 0x0000 -- 0x1000053 0x013f -- 0x1000060 0xa700 -- 0x1000061 0x0001 -- 0x100006a 0x0000 -- 0x1000080 0x0000 -- 0x1000081 0x0000 -- 0x1000082 0x0000 -- 0x1000083 0x0000 -- 0x1000084 0x0000 -- 0x1000085 0x0000 -- 0x1000090 0x0010 -- 0x1000092 0x0000 -- 0x1000093 0x0003 -- 0x1000095 0x0110 -- 0x1000097 0x0000 -- 0x1000098 0x0000 -- 0x1000007 0x0133 -- 0x1000020 0x0000 -- 0x1000021 0x0000 -- 0x2000064>; -- debug = <0>; -- }; -- -- hy28b_ts: hy28b-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&hy28b>,"spi-max-frequency:0"; -- rotate = <&hy28b>,"rotate:0"; -- fps = <&hy28b>,"fps:0"; -- debug = <&hy28b>,"debug:0"; -- xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -- resetgpio = <&hy28b>,"reset-gpios:4", -- <&hy28b_pins>, "brcm,pins:1"; -- ledgpio = <&hy28b>,"led-gpios:4", -- <&hy28b_pins>, "brcm,pins:2"; -- }; --}; -diff --git a/arch/arm/boot/dts/i2c-rtc-overlay.dts b/arch/arm/boot/dts/i2c-rtc-overlay.dts -deleted file mode 100644 -index 5d5abb1..0000000 ---- a/arch/arm/boot/dts/i2c-rtc-overlay.dts -+++ /dev/null -@@ -1,43 +0,0 @@ --// Definitions for several I2C based Real Time Clocks --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- ds1307: ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "disable"; -- }; -- ds3231: ds3231@68 { -- compatible = "maxim,ds3231"; -- reg = <0x68>; -- status = "disable"; -- }; -- pcf2127: pcf2127@51 { -- compatible = "nxp,pcf2127"; -- reg = <0x51>; -- status = "disable"; -- }; -- pcf8523: pcf8523@68 { -- compatible = "nxp,pcf8523"; -- reg = <0x68>; -- status = "disable"; -- }; -- }; -- }; -- __overrides__ { -- ds1307 = <&ds1307>,"status"; -- ds3231 = <&ds3231>,"status"; -- pcf2127 = <&pcf2127>,"status"; -- pcf8523 = <&pcf8523>,"status"; -- }; --}; -diff --git a/arch/arm/boot/dts/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -deleted file mode 100644 -index ea8173e..0000000 ---- a/arch/arm/boot/dts/iqaudio-dac-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for IQaudIO DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "iqaudio,iqaudio-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4c { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4c>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -deleted file mode 100644 -index 735d8ab..0000000 ---- a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for IQaudIO DAC+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "iqaudio,iqaudio-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4c { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4c>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts -deleted file mode 100644 -index 7d5d82b..0000000 ---- a/arch/arm/boot/dts/lirc-rpi-overlay.dts -+++ /dev/null -@@ -1,57 +0,0 @@ --// Definitions for lirc-rpi module --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- lirc_rpi: lirc_rpi { -- compatible = "rpi,lirc-rpi"; -- pinctrl-names = "default"; -- pinctrl-0 = <&lirc_pins>; -- status = "okay"; -- -- // Override autodetection of IR receiver circuit -- // (0 = active high, 1 = active low, -1 = no override ) -- rpi,sense = <0xffffffff>; -- -- // Software carrier -- // (0 = off, 1 = on) -- rpi,softcarrier = <1>; -- -- // Invert output -- // (0 = off, 1 = on) -- rpi,invert = <0>; -- -- // Enable debugging messages -- // (0 = off, 1 = on) -- rpi,debug = <0>; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- lirc_pins: lirc_pins { -- brcm,pins = <17 18>; -- brcm,function = <1 0>; // out in -- brcm,pull = <0 1>; // off down -- }; -- }; -- }; -- -- __overrides__ { -- gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -- gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -- gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -- -- sense = <&lirc_rpi>,"rpi,sense:0"; -- softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -- invert = <&lirc_rpi>,"rpi,invert:0"; -- debug = <&lirc_rpi>,"rpi,debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/mmc-overlay.dts b/arch/arm/boot/dts/mmc-overlay.dts -deleted file mode 100644 -index 0a37cf4..0000000 ---- a/arch/arm/boot/dts/mmc-overlay.dts -+++ /dev/null -@@ -1,19 +0,0 @@ --/dts-v1/; --/plugin/; -- --/{ -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&mmc>; -- -- __overlay__ { -- brcm,overclock-50 = <0>; -- }; -- }; -- -- __overrides__ { -- overclock_50 = <&mmc>,"brcm,overclock-50:0"; -- force_pio = <&mmc>,"brcm,force-pio?"; -- }; --}; -diff --git a/arch/arm/boot/dts/mz61581-overlay.dts b/arch/arm/boot/dts/mz61581-overlay.dts -deleted file mode 100644 -index c06fe12..0000000 ---- a/arch/arm/boot/dts/mz61581-overlay.dts -+++ /dev/null -@@ -1,109 +0,0 @@ --/* -- * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- mz61581_pins: mz61581_pins { -- brcm,pins = <4 15 18 25>; -- brcm,function = <0 1 1 1>; /* in out out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- mz61581: mz61581@0{ -- compatible = "samsung,s6d02a1"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&mz61581_pins>; -- -- spi-max-frequency = <128000000>; -- spi-cpol; -- spi-cpha; -- -- width = <320>; -- height = <480>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- -- reset-gpios = <&gpio 15 0>; -- dc-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 0>; -- -- init = <0x10000b0 00 -- 0x1000011 -- 0x20000ff -- 0x10000b3 0x02 0x00 0x00 0x00 -- 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -- 0x10000c1 0x08 0x16 0x08 0x08 -- 0x10000c4 0x11 0x07 0x03 0x03 -- 0x10000c6 0x00 -- 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -- 0x1000035 0x00 -- 0x1000036 0xa0 -- 0x100003a 0x55 -- 0x1000044 0x00 0x01 -- 0x10000d0 0x07 0x07 0x1d 0x03 -- 0x10000d1 0x03 0x30 0x10 -- 0x10000d2 0x03 0x14 0x04 -- 0x1000029 -- 0x100002c>; -- -- /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -- debug = <3>; -- }; -- -- mz61581_ts: mz61581_ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <4 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 4 0>; -- -- ti,x-plate-ohms = /bits/ 16 <60>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&mz61581>, "spi-max-frequency:0"; -- rotate = <&mz61581>, "rotate:0"; -- fps = <&mz61581>, "fps:0"; -- debug = <&mz61581>, "debug:0"; -- xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -new file mode 100644 -index 0000000..d64e6b4 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,51 @@ -+ifeq ($(CONFIG_OF),y) -+ -+# Overlays for the Raspberry Pi platform -+ -+ifeq ($(CONFIG_BCM2708_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_BCM2709_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ -+dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+ -+targets += dtbs dtbs_install -+targets += $(dtb-y) -+ -+endif -+ -+always := $(dtb-y) -+clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) -+ DTC_FLAGS ?= -@ -+endif -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -new file mode 100644 -index 0000000..c260612 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,470 @@ -+Introduction -+============ -+ -+This directory contains Device Tree overlays. Device Tree makes it possible -+to support many hardware configurations with a single kernel and without the -+need to explicitly load or blacklist kernel modules. Note that this isn't a -+"pure" Device Tree configuration (c.f. MACH_BCM2835) - some on-board devices -+are still configured by the board support code, but the intention is to -+eventually reach that goal. -+ -+On Raspberry Pi, Device Tree usage is controlled from /boot/config.txt. By -+default, the Raspberry Pi kernel boots with device tree enabled. You can -+completely disable DT usage (for now) by adding: -+ -+ device_tree= -+ -+to your config.txt, which should cause your Pi to revert to the old way of -+doing things after a reboot. -+ -+In /boot you will find a .dtb for each base platform. This describes the -+hardware that is part of the Raspberry Pi board. The loader (start.elf and its -+siblings) selects the .dtb file appropriate for the platform by name, and reads -+it into memory. At this point, all of the optional interfaces (i2c, i2s, spi) -+are disabled, but they can be enabled using Device Tree parameters: -+ -+ dtparam=i2c=on,i2s=on,spi=on -+ -+However, this shouldn't be necessary in many use cases because loading an -+overlay that requires one of those interfaces will cause it to be enabled -+automatically, and it is advisable to only enable interfaces if they are -+needed. -+ -+Configuring additional, optional hardware is done using Device Tree overlays -+(see below). -+ -+raspi-config -+============ -+ -+The Advanced Options section of the raspi-config utility can enable and disable -+Device Tree use, as well as toggling the I2C and SPI interfaces. Note that it -+is possible to both enable an interface and blacklist the driver, if for some -+reason you should want to defer the loading. -+ -+Modules -+======= -+ -+As well as describing the hardware, Device Tree also gives enough information -+to allow suitable driver modules to be located and loaded, with the corollary -+that unneeded modules are not loaded. As a result it should be possible to -+remove lines from /etc/modules, and /etc/modprobe.d/raspi-blacklist.conf can -+have its contents deleted (or commented out). -+ -+Using Overlays -+============== -+ -+Overlays are loaded using the "dtoverlay" directive. As an example, consider the -+popular lirc-rpi module, the Linux Infrared Remote Control driver. In the -+pre-DT world this would be loaded from /etc/modules, with an explicit -+"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled, -+this becomes a line in config.txt: -+ -+ dtoverlay=lirc-rpi -+ -+This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By -+default it will use GPIOs 17 (out) and 18 (in), but this can be modified using -+DT parameters: -+ -+ dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13 -+ -+Parameters always have default values, although in some cases (e.g. "w1-gpio") -+it is necessary to provided multiple overlays in order to get the desired -+behaviour. See the list of overlays below for a description of the parameters and their defaults. -+ -+The Overlay and Parameter Reference -+=================================== -+ -+Name: -+Info: Configures the base Raspberry Pi hardware -+Load: -+Params: -+ i2c_arm Set to "on" to enable the ARM's i2c interface -+ (default "off") -+ -+ i2c_vc Set to "on" to enable the i2c interface -+ usually reserved for the VideoCore processor -+ (default "off") -+ -+ i2c An alias for i2c_arm -+ -+ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface -+ (default "100000") -+ -+ i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface -+ (default "100000") -+ -+ i2c_baudrate An alias for i2c_arm_baudrate -+ -+ i2s Set to "on" to enable the i2s interface -+ (default "off") -+ -+ spi Set to "on" to enable the spi interfaces -+ (default "off") -+ -+ act_led_trigger Choose which activity the LED tracks. -+ Use "heartbeat" for a nice load indicator. -+ (default "mmc") -+ -+ act_led_activelow Set to "on" to invert the sense of the LED -+ (default "off") -+ -+ act_led_gpio Set which GPIO to use for the activity LED -+ (in case you want to connect it to an external -+ device) -+ (default "16" on a non-Plus board, "47" on a -+ Plus or Pi 2) -+ -+ pwr_led_trigger -+ pwr_led_activelow -+ pwr_led_gpio -+ As for act_led_*, but using the PWR LED. -+ Not available on Model A/B boards. -+ -+ N.B. It is recommended to only enable those interfaces that are needed. -+ Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc -+ interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.) -+ Note also that i2c, i2c_arm and i2c_vc are aliases for the physical -+ interfaces i2c0 and i2c1. Use of the numeric variants is still possible -+ but deprecated because the ARM/VC assignments differ between board -+ revisions. The same board-specific mapping applies to i2c_baudrate, -+ and the other i2c baudrate parameters. -+ -+ -+Name: ads7846 -+Info: ADS7846 Touch controller -+Load: dtoverlay=ads7846,= -+Params: cs SPI bus Chip Select (default 1) -+ speed SPI bus speed (default 2Mhz, max 3.25MHz) -+ penirq GPIO used for PENIRQ. REQUIRED -+ penirq_pull Set GPIO pull (default 0=none, 2=pullup) -+ swapxy Swap x and y axis -+ xmin Minimum value on the X axis (default 0) -+ ymin Minimum value on the Y axis (default 0) -+ xmax Maximum value on the X axis (default 4095) -+ ymax Maximum value on the Y axis (default 4095) -+ pmin Minimum reported pressure value (default 0) -+ pmax Maximum reported pressure value (default 65535) -+ xohms Touchpanel sensitivity (X-plate resistance) -+ (default 400) -+ -+ penirq is required and usually xohms (60-100) has to be set as well. -+ Apart from that, pmax (255) and swapxy are also common. -+ The rest of the calibration can be done with xinput-calibrator. -+ See: github.com/notro/fbtft/wiki/FBTFT-on-Raspian -+ Device Tree binding document: -+ www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt -+ -+ -+Name: bmp085_i2c-sensor -+Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -+ sensors from Bosch Sensortec -+Load: dtoverlay=bmp085_i2c-sensor -+Params: -+ -+ -+[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+Name: enc28j60 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) -+Load: dtoverlay=enc28j60,= -+Params: int_pin GPIO used for INT (default 25) -+ -+ speed SPI bus speed (default 12000000) -+ -+ -+Name: hifiberry-amp -+Info: Configures the HifiBerry Amp and Amp+ audio cards -+Load: dtoverlay=hifiberry-amp -+Params: -+ -+ -+Name: hifiberry-dac -+Info: Configures the HifiBerry DAC audio card -+Load: dtoverlay=hifiberry-dac -+Params: -+ -+ -+Name: hifiberry-dacplus -+Info: Configures the HifiBerry DAC+ audio card -+Load: dtoverlay=hifiberry-dacplus -+Params: -+ -+ -+Name: hifiberry-digi -+Info: Configures the HifiBerry Digi audio card -+Load: dtoverlay=hifiberry-digi -+Params: -+ -+ -+Name: hy28a -+Info: HY28A - 2.8" TFT LCD Display Module by HAOYU Electronics -+ Default values match Texy's display shield -+Load: dtoverlay=hy28a,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ resetgpio GPIO used to reset controller -+ -+ ledgpio GPIO used to control backlight -+ -+ -+Name: hy28b -+Info: HY28B - 2.8" TFT LCD Display Module by HAOYU Electronics -+ Default values match Texy's display shield -+Load: dtoverlay=hy28b,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ resetgpio GPIO used to reset controller -+ -+ ledgpio GPIO used to control backlight -+ -+ -+Name: i2c-rtc -+Info: Adds support for a number of I2C Real Time Clock devices -+Load: dtoverlay=i2c-rtc, -+Params: ds1307 Select the DS1307 device -+ -+ ds3231 Select the DS3231 device -+ -+ pcf2127 Select the PCF2127 device -+ -+ pcf8523 Select the PCF8523 device -+ -+ pcf8563 Select the PCF8563 device -+ -+ -+Name: iqaudio-dac -+Info: Configures the IQaudio DAC audio card -+Load: dtoverlay=iqaudio-dac -+Params: -+ -+ -+Name: iqaudio-dacplus -+Info: Configures the IQaudio DAC+ audio card -+Load: dtoverlay=iqaudio-dacplus -+Params: -+ -+ -+Name: lirc-rpi -+Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi) -+ Consult the module documentation for more details. -+Load: dtoverlay=lirc-rpi,=,... -+Params: gpio_out_pin GPIO for output (default "17") -+ -+ gpio_in_pin GPIO for input (default "18") -+ -+ gpio_in_pull Pull up/down/off on the input pin -+ (default "down") -+ -+ sense Override the IR receive auto-detection logic: -+ "1" = force active high -+ "0" = force active low -+ "-1" = use auto-detection -+ (default "-1") -+ -+ softcarrier Turn the software carrier "on" or "off" -+ (default "on") -+ -+ invert "on" = invert the output pin (default "off") -+ -+ debug "on" = enable additional debug messages -+ (default "off") -+ -+ -+Name: mmc -+Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock -+Load: dtoverlay=mmc,= -+Params: overclock_50 Clock (in MHz) to use when the MMC framework -+ requests 50MHz -+ force_pio Disable DMA support -+ -+ -+Name: mz61581 -+Info: MZ61581 display by Tontec -+Load: dtoverlay=mz61581,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ -+[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+[ The pcf8523-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+[ The pcf8563-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+Name: piscreen -+Info: PiScreen display by OzzMaker.com -+Load: dtoverlay=piscreen,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ -+Name: pitft28-resistive -+Info: Adafruit PiTFT 2.8" resistive touch screen -+Load: dtoverlay=pitft28-resistive,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ -+Name: pps-gpio -+Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). -+Load: dtoverlay=pps-gpio,= -+Params: gpiopin Input GPIO (default "18") -+ -+ -+Name: rpi-dac -+Info: Configures the RPi DAC audio card -+Load: dtoverlay=rpi-dac -+Params: -+ -+ -+Name: rpi-display -+Info: RPi-Display - 2.8" Touch Display by Watterott -+Load: dtoverlay=rpi-display,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ -+Name: rpi-proto -+Info: Configures the RPi Proto audio card -+Load: dtoverlay=rpi-proto -+Params: -+ -+ -+Name: sdhost -+Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock -+Load: dtoverlay=sdhost,= -+Params: overclock_50 Clock (in MHz) to use when the MMC framework -+ requests 50MHz -+ force_pio Disable DMA support -+ -+ -+Name: spi-bcm2708 -+Info: Selects the bcm2708-spi SPI driver -+Load: dtoverlay=spi-bcm2708 -+Params: -+ -+ -+Name: spi-bcm2835 -+Info: Selects the bcm2835-spi SPI driver -+Load: dtoverlay=spi-bcm2835 -+Params: -+ -+ -+Name: tinylcd35 -+Info: 3.5" Color TFT Display by www.tinlylcd.com -+ Options: Touch, RTC, keypad -+Load: dtoverlay=tinylcd35,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ touch Enable touch panel -+ -+ touchgpio Touch controller IRQ GPIO -+ -+ xohms Touchpanel: Resistance of X-plate in ohms -+ -+ rtc-pcf PCF8563 Real Time Clock -+ -+ rtc-ds DS1307 Real Time Clock -+ -+ keypad Enable keypad -+ -+ Examples: -+ Display with touchpanel, PCF8563 RTC and keypad: -+ dtoverlay=tinylcd35,touch,rtc-pcf,keypad -+ Old touch display: -+ dtoverlay=tinylcd35,touch,touchgpio=3 -+ -+ -+Name: w1-gpio -+Info: Configures the w1-gpio Onewire interface module. -+ Use this overlay if you *don't* need a GPIO to drive an external pullup. -+Load: dtoverlay=w1-gpio,= -+Params: gpiopin GPIO for I/O (default "4") -+ -+ pullup Non-zero, "on", or "y" to enable the parasitic -+ power (2-wire, power-on-data) feature -+ -+ -+Name: w1-gpio-pullup -+Info: Configures the w1-gpio Onewire interface module. -+ Use this overlay if you *do* need a GPIO to drive an external pullup. -+Load: dtoverlay=w1-gpio-pullup,=,... -+Params: gpiopin GPIO for I/O (default "4") -+ -+ pullup Non-zero, "on", or "y" to enable the parasitic -+ power (2-wire, power-on-data) feature -+ -+ extpullup GPIO for external pullup (default "5") -+ -+ -+Troubleshooting -+=============== -+ -+If you are experiencing problems that you think are DT-related, enable DT -+diagnostic output by adding this to /boot/config.txt: -+ -+ dtdebug=on -+ -+and rebooting. Then run: -+ -+ sudo vcdbg log msg -+ -+and look for relevant messages. -+ -+Further reading -+=============== -+ -+This is only meant to be a quick introduction to the subject of Device Tree on -+Raspberry Pi. There is a more complete explanation here: -+ -+http://www.raspberrypi.org/documentation/configuration/device-tree.md -diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts -new file mode 100644 -index 0000000..6a92cd1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts -@@ -0,0 +1,83 @@ -+/* -+ * Generic Device Tree overlay for the ADS7846 touch controller -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ ads7846_pins: ads7846_pins { -+ brcm,pins = <255>; /* illegal default value */ -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ads7846: ads7846@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ads7846_pins>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <255 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 255 0>; -+ -+ /* driver defaults */ -+ ti,x-min = /bits/ 16 <0>; -+ ti,y-min = /bits/ 16 <0>; -+ ti,x-max = /bits/ 16 <0x0FFF>; -+ ti,y-max = /bits/ 16 <0x0FFF>; -+ ti,pressure-min = /bits/ 16 <0>; -+ ti,pressure-max = /bits/ 16 <0xFFFF>; -+ ti,x-plate-ohms = /bits/ 16 <400>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ cs = <&ads7846>,"reg:0"; -+ speed = <&ads7846>,"spi-max-frequency:0"; -+ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -+ <&ads7846>,"interrupts:0", -+ <&ads7846>,"pendown-gpio:4"; -+ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -+ swapxy = <&ads7846>,"ti,swap-xy?"; -+ xmin = <&ads7846>,"ti,x-min;0"; -+ ymin = <&ads7846>,"ti,y-min;0"; -+ xmax = <&ads7846>,"ti,x-max;0"; -+ ymax = <&ads7846>,"ti,y-max;0"; -+ pmin = <&ads7846>,"ti,pressure-min;0"; -+ pmax = <&ads7846>,"ti,pressure-max;0"; -+ xohms = <&ads7846>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts -new file mode 100644 -index 0000000..b830bf2 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts -@@ -0,0 +1,23 @@ -+// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts -new file mode 100644 -index 0000000..7d27044 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for DS1307 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts -new file mode 100644 -index 0000000..aa9b645 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts -@@ -0,0 +1,29 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts -new file mode 100644 -index 0000000..2c81448 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Amp/Amp+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-amp"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ tas5713@1b { -+ #sound-dai-cells = <0>; -+ compatible = "ti,tas5713"; -+ reg = <0x1b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts -new file mode 100644 -index 0000000..5e7633a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for HiFiBerry DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -new file mode 100644 -index 0000000..deb9c625 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dacplus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4d { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4d>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -new file mode 100644 -index 0000000..d0e0d8a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Digi -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-digi"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8804@3b { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hy28a-overlay.dts b/arch/arm/boot/dts/overlays/hy28a-overlay.dts -new file mode 100644 -index 0000000..3cd3083 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts -@@ -0,0 +1,87 @@ -+/* -+ * Device Tree overlay for HY28A display -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28a_pins: hy28a_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28a: hy28a@0{ -+ compatible = "ilitek,ili9320"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28a_pins>; -+ -+ spi-max-frequency = <32000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ hy28a_ts: hy28a-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28a>,"spi-max-frequency:0"; -+ rotate = <&hy28a>,"rotate:0"; -+ fps = <&hy28a>,"fps:0"; -+ debug = <&hy28a>,"debug:0"; -+ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28a>,"reset-gpios:4", -+ <&hy28a_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28a>,"led-gpios:4", -+ <&hy28a_pins>, "brcm,pins:2"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hy28b-overlay.dts b/arch/arm/boot/dts/overlays/hy28b-overlay.dts -new file mode 100644 -index 0000000..f774c4a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts -@@ -0,0 +1,142 @@ -+/* -+ * Device Tree overlay for HY28b display shield by Texy -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28b_pins: hy28b_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28b: hy28b@0{ -+ compatible = "ilitek,ili9325"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28b_pins>; -+ -+ spi-max-frequency = <48000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ -+ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -+ -+ init = <0x10000e7 0x0010 -+ 0x1000000 0x0001 -+ 0x1000001 0x0100 -+ 0x1000002 0x0700 -+ 0x1000003 0x1030 -+ 0x1000004 0x0000 -+ 0x1000008 0x0207 -+ 0x1000009 0x0000 -+ 0x100000a 0x0000 -+ 0x100000c 0x0001 -+ 0x100000d 0x0000 -+ 0x100000f 0x0000 -+ 0x1000010 0x0000 -+ 0x1000011 0x0007 -+ 0x1000012 0x0000 -+ 0x1000013 0x0000 -+ 0x2000032 -+ 0x1000010 0x1590 -+ 0x1000011 0x0227 -+ 0x2000032 -+ 0x1000012 0x009c -+ 0x2000032 -+ 0x1000013 0x1900 -+ 0x1000029 0x0023 -+ 0x100002b 0x000e -+ 0x2000032 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000032 -+ 0x1000050 0x0000 -+ 0x1000051 0x00ef -+ 0x1000052 0x0000 -+ 0x1000053 0x013f -+ 0x1000060 0xa700 -+ 0x1000061 0x0001 -+ 0x100006a 0x0000 -+ 0x1000080 0x0000 -+ 0x1000081 0x0000 -+ 0x1000082 0x0000 -+ 0x1000083 0x0000 -+ 0x1000084 0x0000 -+ 0x1000085 0x0000 -+ 0x1000090 0x0010 -+ 0x1000092 0x0000 -+ 0x1000093 0x0003 -+ 0x1000095 0x0110 -+ 0x1000097 0x0000 -+ 0x1000098 0x0000 -+ 0x1000007 0x0133 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000064>; -+ debug = <0>; -+ }; -+ -+ hy28b_ts: hy28b-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28b>,"spi-max-frequency:0"; -+ rotate = <&hy28b>,"rotate:0"; -+ fps = <&hy28b>,"fps:0"; -+ debug = <&hy28b>,"debug:0"; -+ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28b>,"reset-gpios:4", -+ <&hy28b_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28b>,"led-gpios:4", -+ <&hy28b_pins>, "brcm,pins:2"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -new file mode 100644 -index 0000000..6bccfdc ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,49 @@ -+// Definitions for several I2C based Real Time Clocks -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ ds3231: ds3231@68 { -+ compatible = "maxim,ds3231"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf2127: pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ pcf8523: pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ __overrides__ { -+ ds1307 = <&ds1307>,"status"; -+ ds3231 = <&ds3231>,"status"; -+ pcf2127 = <&pcf2127>,"status"; -+ pcf8523 = <&pcf8523>,"status"; -+ pcf8563 = <&pcf8563>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -new file mode 100644 -index 0000000..ea8173e ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -new file mode 100644 -index 0000000..735d8ab ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts -new file mode 100644 -index 0000000..7d5d82b ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts -@@ -0,0 +1,57 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ lirc_rpi: lirc_rpi { -+ compatible = "rpi,lirc-rpi"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lirc_pins>; -+ status = "okay"; -+ -+ // Override autodetection of IR receiver circuit -+ // (0 = active high, 1 = active low, -1 = no override ) -+ rpi,sense = <0xffffffff>; -+ -+ // Software carrier -+ // (0 = off, 1 = on) -+ rpi,softcarrier = <1>; -+ -+ // Invert output -+ // (0 = off, 1 = on) -+ rpi,invert = <0>; -+ -+ // Enable debugging messages -+ // (0 = off, 1 = on) -+ rpi,debug = <0>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ lirc_pins: lirc_pins { -+ brcm,pins = <17 18>; -+ brcm,function = <1 0>; // out in -+ brcm,pull = <0 1>; // off down -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -+ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -+ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -+ -+ sense = <&lirc_rpi>,"rpi,sense:0"; -+ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -+ invert = <&lirc_rpi>,"rpi,invert:0"; -+ debug = <&lirc_rpi>,"rpi,debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts -new file mode 100644 -index 0000000..0a37cf4 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts -@@ -0,0 +1,19 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ -+ __overlay__ { -+ brcm,overclock-50 = <0>; -+ }; -+ }; -+ -+ __overrides__ { -+ overclock_50 = <&mmc>,"brcm,overclock-50:0"; -+ force_pio = <&mmc>,"brcm,force-pio?"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/mz61581-overlay.dts b/arch/arm/boot/dts/overlays/mz61581-overlay.dts -new file mode 100644 -index 0000000..c06fe12 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts -@@ -0,0 +1,109 @@ -+/* -+ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ mz61581_pins: mz61581_pins { -+ brcm,pins = <4 15 18 25>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mz61581: mz61581@0{ -+ compatible = "samsung,s6d02a1"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mz61581_pins>; -+ -+ spi-max-frequency = <128000000>; -+ spi-cpol; -+ spi-cpha; -+ -+ width = <320>; -+ height = <480>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ -+ reset-gpios = <&gpio 15 0>; -+ dc-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 0>; -+ -+ init = <0x10000b0 00 -+ 0x1000011 -+ 0x20000ff -+ 0x10000b3 0x02 0x00 0x00 0x00 -+ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -+ 0x10000c1 0x08 0x16 0x08 0x08 -+ 0x10000c4 0x11 0x07 0x03 0x03 -+ 0x10000c6 0x00 -+ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -+ 0x1000035 0x00 -+ 0x1000036 0xa0 -+ 0x100003a 0x55 -+ 0x1000044 0x00 0x01 -+ 0x10000d0 0x07 0x07 0x1d 0x03 -+ 0x10000d1 0x03 0x30 0x10 -+ 0x10000d2 0x03 0x14 0x04 -+ 0x1000029 -+ 0x100002c>; -+ -+ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -+ debug = <3>; -+ }; -+ -+ mz61581_ts: mz61581_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <4 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 4 0>; -+ -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&mz61581>, "spi-max-frequency:0"; -+ rotate = <&mz61581>, "rotate:0"; -+ fps = <&mz61581>, "fps:0"; -+ debug = <&mz61581>, "debug:0"; -+ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts -new file mode 100644 -index 0000000..01fc81d ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF2127 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts -new file mode 100644 -index 0000000..0071f62 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF8523 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -new file mode 100644 -index 0000000..b7fd7ea ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -0,0 +1,94 @@ -+/* -+ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ piscreen_pins: piscreen_pins { -+ brcm,pins = <17 25 24 22>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ piscreen: piscreen@0{ -+ compatible = "ilitek,ili9486"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&piscreen_pins>; -+ -+ spi-max-frequency = <24000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ regwidth = <16>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 22 1>; -+ debug = <0>; -+ -+ init = <0x10000b0 0x00 -+ 0x1000011 -+ 0x20000ff -+ 0x100003a 0x55 -+ 0x1000036 0x28 -+ 0x10000c2 0x44 -+ 0x10000c5 0x00 0x00 0x00 0x00 -+ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -+ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x1000011 -+ 0x1000029>; -+ }; -+ -+ piscreen-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&piscreen>,"spi-max-frequency:0"; -+ rotate = <&piscreen>,"rotate:0"; -+ fps = <&piscreen>,"fps:0"; -+ debug = <&piscreen>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts -new file mode 100644 -index 0000000..d506eae ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts -@@ -0,0 +1,115 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "ilitek,ili9340"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts -new file mode 100644 -index 0000000..40bf0e1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts -@@ -0,0 +1,34 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ pps: pps { -+ compatible = "pps-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pps_pins>; -+ gpios = <&gpio 18 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pps_pins: pps_pins { -+ brcm,pins = <18>; -+ brcm,function = <0>; // in -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&pps>,"gpios:4", -+ <&pps_pins>,"brcm,pins:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -new file mode 100644 -index 0000000..7fc6ac9 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for RPi DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm1794a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm1794a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts -new file mode 100644 -index 0000000..a8fa974 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts -@@ -0,0 +1,82 @@ -+/* -+ * Device Tree overlay for rpi-display by Watterott -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ rpi_display_pins: rpi_display_pins { -+ brcm,pins = <18 23 24 25>; -+ brcm,function = <1 1 1 0>; /* out out out in */ -+ brcm,pull = <0 0 0 2>; /* - - - up */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rpidisplay: rpi-display@0{ -+ compatible = "ilitek,ili9341"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rpi_display_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ reset-gpios = <&gpio 23 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ rpidisplay_ts: rpi-display-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <25 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 25 0>; -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&rpidisplay>,"spi-max-frequency:0"; -+ rotate = <&rpidisplay>,"rotate:0"; -+ fps = <&rpidisplay>,"fps:0"; -+ debug = <&rpidisplay>,"debug:0"; -+ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts -new file mode 100644 -index 0000000..2029930 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for Rpi-Proto -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-proto"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8731@1a { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8731"; -+ reg = <0x1a>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -new file mode 100644 -index 0000000..b2653e9 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -@@ -0,0 +1,75 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&soc>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; -+ interrupts = <2 24>; -+ clocks = <&clk_sdhost>; -+ dmas = <&dma 13>, -+ <&dma 13>; -+ dma-names = "tx", "rx"; -+ brcm,delay-after-stop = <0>; -+ brcm,overclock-50 = <0>; -+ status = "okay"; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_sdhost: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ sdhost_pins: sdhost_pins { -+ brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&mmc>; -+ __overlay__ { -+ /* Find a way to disable the other driver */ -+ compatible = ""; -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/__overrides__"; -+ __overlay__ { -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+ }; -+ -+ __overrides__ { -+ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; -+ force_pio = <&sdhost>,"brcm,force-pio?"; -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts -new file mode 100644 -index 0000000..e378ef1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2708-spi"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts -new file mode 100644 -index 0000000..fc1e39b ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2835-spi"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts -new file mode 100644 -index 0000000..f7102c8 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts -@@ -0,0 +1,216 @@ -+/* -+ * tinylcd35-overlay.dts -+ * -+ * ------------------------------------------------- -+ * www.tinlylcd.com -+ * ------------------------------------------------- -+ * Device---Driver-----BUS GPIO's -+ * display tinylcd35 spi0.0 25 24 18 -+ * touch ads7846 spi0.1 5 -+ * rtc ds1307 i2c1-0068 -+ * rtc pcf8563 i2c1-0051 -+ * keypad gpio-keys --------- 17 22 27 23 28 -+ * -+ * -+ * TinyLCD.com 3.5 inch TFT -+ * -+ * Version 001 -+ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -+ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ tinylcd35_pins: tinylcd35_pins { -+ brcm,pins = <25 24 18>; -+ brcm,function = <1>; /* out */ -+ }; -+ tinylcd35_ts_pins: tinylcd35_ts_pins { -+ brcm,pins = <5>; -+ brcm,function = <0>; /* in */ -+ }; -+ keypad_pins: keypad_pins { -+ brcm,pins = <4 17 22 23 27>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <1>; /* down */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ tinylcd35: tinylcd35@0{ -+ compatible = "neosec,tinylcd"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&tinylcd35_pins>, -+ <&tinylcd35_ts_pins>; -+ -+ spi-max-frequency = <48000000>; -+ rotate = <270>; -+ fps = <20>; -+ bgr; -+ buswidth = <8>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ -+ init = <0x10000B0 0x80 -+ 0x10000C0 0x0A 0x0A -+ 0x10000C1 0x01 0x01 -+ 0x10000C2 0x33 -+ 0x10000C5 0x00 0x42 0x80 -+ 0x10000B1 0xD0 0x11 -+ 0x10000B4 0x02 -+ 0x10000B6 0x00 0x22 0x3B -+ 0x10000B7 0x07 -+ 0x1000036 0x58 -+ 0x10000F0 0x36 0xA5 0xD3 -+ 0x10000E5 0x80 -+ 0x10000E5 0x01 -+ 0x10000B3 0x00 -+ 0x10000E5 0x00 -+ 0x10000F0 0x36 0xA5 0x53 -+ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -+ 0x100003A 0x55 -+ 0x1000011 -+ 0x2000001 -+ 0x1000029>; -+ }; -+ -+ tinylcd35_ts: tinylcd35_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ status = "disabled"; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <5 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 5 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ -+ /* RTC */ -+ -+ fragment@3 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* -+ * Values for input event code is found under the -+ * 'Keys and buttons' heading in include/uapi/linux/input.h -+ */ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ keypad: keypad { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&keypad_pins>; -+ status = "disabled"; -+ autorepeat; -+ -+ button@17 { -+ label = "GPIO KEY_UP"; -+ linux,code = <103>; -+ gpios = <&gpio 17 0>; -+ }; -+ button@22 { -+ label = "GPIO KEY_DOWN"; -+ linux,code = <108>; -+ gpios = <&gpio 22 0>; -+ }; -+ button@27 { -+ label = "GPIO KEY_LEFT"; -+ linux,code = <105>; -+ gpios = <&gpio 27 0>; -+ }; -+ button@23 { -+ label = "GPIO KEY_RIGHT"; -+ linux,code = <106>; -+ gpios = <&gpio 23 0>; -+ }; -+ button@4 { -+ label = "GPIO KEY_ENTER"; -+ linux,code = <28>; -+ gpios = <&gpio 4 0>; -+ }; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&tinylcd35>,"spi-max-frequency:0"; -+ rotate = <&tinylcd35>,"rotate:0"; -+ fps = <&tinylcd35>,"fps:0"; -+ debug = <&tinylcd35>,"debug:0"; -+ touch = <&tinylcd35_ts>,"status"; -+ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -+ <&tinylcd35_ts>,"interrupts:0", -+ <&tinylcd35_ts>,"pendown-gpio:4"; -+ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -+ rtc-pcf = <&i2c1>,"status", -+ <&pcf8563>,"status"; -+ rtc-ds = <&i2c1>,"status", -+ <&ds1307>,"status"; -+ keypad = <&keypad>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts -new file mode 100644 -index 0000000..29a3b48 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for w1-gpio module (without external pullup) -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>; -+ rpi,parasitic-power = <0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4>; -+ brcm,function = <0>; // in (initially) -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts -new file mode 100644 -index 0000000..66a98f6 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts -@@ -0,0 +1,41 @@ -+// Definitions for w1-gpio module (with external pullup) -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>, <&gpio 5 1>; -+ rpi,parasitic-power = <0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4 5>; -+ brcm,function = <0 1>; // in out -+ brcm,pull = <0 0>; // off off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ extpullup = <&w1>,"gpios:16", -+ <&w1_pins>,"brcm,pins:4"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -deleted file mode 100644 -index 01fc81d..0000000 ---- a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for PCF2127 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcf2127@51 { -- compatible = "nxp,pcf2127"; -- reg = <0x51>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -deleted file mode 100644 -index 0071f62..0000000 ---- a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for PCF8523 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcf8523@68 { -- compatible = "nxp,pcf8523"; -- reg = <0x68>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -deleted file mode 100644 -index b7fd7ea..0000000 ---- a/arch/arm/boot/dts/piscreen-overlay.dts -+++ /dev/null -@@ -1,94 +0,0 @@ --/* -- * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- piscreen_pins: piscreen_pins { -- brcm,pins = <17 25 24 22>; -- brcm,function = <0 1 1 1>; /* in out out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- piscreen: piscreen@0{ -- compatible = "ilitek,ili9486"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&piscreen_pins>; -- -- spi-max-frequency = <24000000>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- regwidth = <16>; -- reset-gpios = <&gpio 25 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 22 1>; -- debug = <0>; -- -- init = <0x10000b0 0x00 -- 0x1000011 -- 0x20000ff -- 0x100003a 0x55 -- 0x1000036 0x28 -- 0x10000c2 0x44 -- 0x10000c5 0x00 0x00 0x00 0x00 -- 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -- 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -- 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -- 0x1000011 -- 0x1000029>; -- }; -- -- piscreen-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&piscreen>,"spi-max-frequency:0"; -- rotate = <&piscreen>,"rotate:0"; -- fps = <&piscreen>,"fps:0"; -- debug = <&piscreen>,"debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -deleted file mode 100644 -index d506eae..0000000 ---- a/arch/arm/boot/dts/pitft28-resistive-overlay.dts -+++ /dev/null -@@ -1,115 +0,0 @@ --/* -- * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- pitft_pins: pitft_pins { -- brcm,pins = <24 25>; -- brcm,function = <0 1>; /* in out */ -- brcm,pull = <2 0>; /* pullup none */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- pitft: pitft@0{ -- compatible = "ilitek,ili9340"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pitft_pins>; -- -- spi-max-frequency = <32000000>; -- rotate = <90>; -- fps = <25>; -- bgr; -- buswidth = <8>; -- dc-gpios = <&gpio 25 0>; -- debug = <0>; -- }; -- -- pitft_ts@1 { -- #address-cells = <1>; -- #size-cells = <0>; -- compatible = "st,stmpe610"; -- reg = <1>; -- -- spi-max-frequency = <500000>; -- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -- interrupts = <24 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- interrupt-controller; -- -- stmpe_touchscreen { -- compatible = "st,stmpe-ts"; -- st,sample-time = <4>; -- st,mod-12b = <1>; -- st,ref-sel = <0>; -- st,adc-freq = <2>; -- st,ave-ctrl = <3>; -- st,touch-det-delay = <4>; -- st,settling = <2>; -- st,fraction-z = <7>; -- st,i-drive = <0>; -- }; -- -- stmpe_gpio: stmpe_gpio { -- #gpio-cells = <2>; -- compatible = "st,stmpe-gpio"; -- /* -- * only GPIO2 is wired/available -- * and it is wired to the backlight -- */ -- st,norequest-mask = <0x7b>; -- }; -- }; -- }; -- }; -- -- fragment@3 { -- target-path = "/soc"; -- __overlay__ { -- backlight { -- compatible = "gpio-backlight"; -- gpios = <&stmpe_gpio 2 0>; -- default-on; -- }; -- }; -- }; -- -- __overrides__ { -- speed = <&pitft>,"spi-max-frequency:0"; -- rotate = <&pitft>,"rotate:0"; -- fps = <&pitft>,"fps:0"; -- debug = <&pitft>,"debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/pps-gpio-overlay.dts b/arch/arm/boot/dts/pps-gpio-overlay.dts -deleted file mode 100644 -index 40bf0e1..0000000 ---- a/arch/arm/boot/dts/pps-gpio-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- pps: pps { -- compatible = "pps-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pps_pins>; -- gpios = <&gpio 18 0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- pps_pins: pps_pins { -- brcm,pins = <18>; -- brcm,function = <0>; // in -- brcm,pull = <0>; // off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&pps>,"gpios:4", -- <&pps_pins>,"brcm,pins:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-dac-overlay.dts b/arch/arm/boot/dts/rpi-dac-overlay.dts -deleted file mode 100644 -index 7fc6ac9..0000000 ---- a/arch/arm/boot/dts/rpi-dac-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --// Definitions for RPi DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "rpi,rpi-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target-path = "/"; -- __overlay__ { -- pcm1794a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm1794a"; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -deleted file mode 100644 -index a8fa974..0000000 ---- a/arch/arm/boot/dts/rpi-display-overlay.dts -+++ /dev/null -@@ -1,82 +0,0 @@ --/* -- * Device Tree overlay for rpi-display by Watterott -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- rpi_display_pins: rpi_display_pins { -- brcm,pins = <18 23 24 25>; -- brcm,function = <1 1 1 0>; /* out out out in */ -- brcm,pull = <0 0 0 2>; /* - - - up */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- rpidisplay: rpi-display@0{ -- compatible = "ilitek,ili9341"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&rpi_display_pins>; -- -- spi-max-frequency = <32000000>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- reset-gpios = <&gpio 23 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- }; -- -- rpidisplay_ts: rpi-display-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <25 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 25 0>; -- ti,x-plate-ohms = /bits/ 16 <60>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&rpidisplay>,"spi-max-frequency:0"; -- rotate = <&rpidisplay>,"rotate:0"; -- fps = <&rpidisplay>,"fps:0"; -- debug = <&rpidisplay>,"debug:0"; -- xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-proto-overlay.dts b/arch/arm/boot/dts/rpi-proto-overlay.dts -deleted file mode 100644 -index 2029930..0000000 ---- a/arch/arm/boot/dts/rpi-proto-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for Rpi-Proto --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "rpi,rpi-proto"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- wm8731@1a { -- #sound-dai-cells = <0>; -- compatible = "wlf,wm8731"; -- reg = <0x1a>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -deleted file mode 100644 -index b2653e9..0000000 ---- a/arch/arm/boot/dts/sdhost-overlay.dts -+++ /dev/null -@@ -1,75 +0,0 @@ --/dts-v1/; --/plugin/; -- --/{ -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&soc>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <1>; -- -- sdhost: sdhost@7e202000 { -- compatible = "brcm,bcm2835-sdhost"; -- reg = <0x7e202000 0x100>; -- pinctrl-names = "default"; -- pinctrl-0 = <&sdhost_pins>; -- interrupts = <2 24>; -- clocks = <&clk_sdhost>; -- dmas = <&dma 13>, -- <&dma 13>; -- dma-names = "tx", "rx"; -- brcm,delay-after-stop = <0>; -- brcm,overclock-50 = <0>; -- status = "okay"; -- }; -- -- clocks { -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_sdhost: clock@3 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "sdhost"; -- clock-frequency = <250000000>; -- }; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- sdhost_pins: sdhost_pins { -- brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <4>; /* alt0 */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&mmc>; -- __overlay__ { -- /* Find a way to disable the other driver */ -- compatible = ""; -- status = "disabled"; -- }; -- }; -- -- fragment@3 { -- target-path = "/__overrides__"; -- __overlay__ { -- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -- }; -- }; -- -- __overrides__ { -- delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -- overclock_50 = <&sdhost>,"brcm,overclock-50:0"; -- force_pio = <&sdhost>,"brcm,force-pio?"; -- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -deleted file mode 100644 -index e378ef1..0000000 ---- a/arch/arm/boot/dts/spi-bcm2708-overlay.dts -+++ /dev/null -@@ -1,18 +0,0 @@ --/* -- * Device tree overlay for spi-bcm2835 -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -- /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- compatible = "brcm,bcm2708-spi"; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -deleted file mode 100644 -index fc1e39b..0000000 ---- a/arch/arm/boot/dts/spi-bcm2835-overlay.dts -+++ /dev/null -@@ -1,18 +0,0 @@ --/* -- * Device tree overlay for spi-bcm2835 -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -- /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- compatible = "brcm,bcm2835-spi"; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/tinylcd35-overlay.dts b/arch/arm/boot/dts/tinylcd35-overlay.dts -deleted file mode 100644 -index f7102c8..0000000 ---- a/arch/arm/boot/dts/tinylcd35-overlay.dts -+++ /dev/null -@@ -1,216 +0,0 @@ --/* -- * tinylcd35-overlay.dts -- * -- * ------------------------------------------------- -- * www.tinlylcd.com -- * ------------------------------------------------- -- * Device---Driver-----BUS GPIO's -- * display tinylcd35 spi0.0 25 24 18 -- * touch ads7846 spi0.1 5 -- * rtc ds1307 i2c1-0068 -- * rtc pcf8563 i2c1-0051 -- * keypad gpio-keys --------- 17 22 27 23 28 -- * -- * -- * TinyLCD.com 3.5 inch TFT -- * -- * Version 001 -- * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -- * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- tinylcd35_pins: tinylcd35_pins { -- brcm,pins = <25 24 18>; -- brcm,function = <1>; /* out */ -- }; -- tinylcd35_ts_pins: tinylcd35_ts_pins { -- brcm,pins = <5>; -- brcm,function = <0>; /* in */ -- }; -- keypad_pins: keypad_pins { -- brcm,pins = <4 17 22 23 27>; -- brcm,function = <0>; /* in */ -- brcm,pull = <1>; /* down */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- tinylcd35: tinylcd35@0{ -- compatible = "neosec,tinylcd"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&tinylcd35_pins>, -- <&tinylcd35_ts_pins>; -- -- spi-max-frequency = <48000000>; -- rotate = <270>; -- fps = <20>; -- bgr; -- buswidth = <8>; -- reset-gpios = <&gpio 25 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- -- init = <0x10000B0 0x80 -- 0x10000C0 0x0A 0x0A -- 0x10000C1 0x01 0x01 -- 0x10000C2 0x33 -- 0x10000C5 0x00 0x42 0x80 -- 0x10000B1 0xD0 0x11 -- 0x10000B4 0x02 -- 0x10000B6 0x00 0x22 0x3B -- 0x10000B7 0x07 -- 0x1000036 0x58 -- 0x10000F0 0x36 0xA5 0xD3 -- 0x10000E5 0x80 -- 0x10000E5 0x01 -- 0x10000B3 0x00 -- 0x10000E5 0x00 -- 0x10000F0 0x36 0xA5 0x53 -- 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -- 0x100003A 0x55 -- 0x1000011 -- 0x2000001 -- 0x1000029>; -- }; -- -- tinylcd35_ts: tinylcd35_ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- status = "disabled"; -- -- spi-max-frequency = <2000000>; -- interrupts = <5 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 5 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- -- /* RTC */ -- -- fragment@3 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- pcf8563: pcf8563@51 { -- compatible = "nxp,pcf8563"; -- reg = <0x51>; -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@4 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- ds1307: ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "disabled"; -- }; -- }; -- }; -- -- /* -- * Values for input event code is found under the -- * 'Keys and buttons' heading in include/uapi/linux/input.h -- */ -- fragment@5 { -- target-path = "/soc"; -- __overlay__ { -- keypad: keypad { -- compatible = "gpio-keys"; -- #address-cells = <1>; -- #size-cells = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&keypad_pins>; -- status = "disabled"; -- autorepeat; -- -- button@17 { -- label = "GPIO KEY_UP"; -- linux,code = <103>; -- gpios = <&gpio 17 0>; -- }; -- button@22 { -- label = "GPIO KEY_DOWN"; -- linux,code = <108>; -- gpios = <&gpio 22 0>; -- }; -- button@27 { -- label = "GPIO KEY_LEFT"; -- linux,code = <105>; -- gpios = <&gpio 27 0>; -- }; -- button@23 { -- label = "GPIO KEY_RIGHT"; -- linux,code = <106>; -- gpios = <&gpio 23 0>; -- }; -- button@4 { -- label = "GPIO KEY_ENTER"; -- linux,code = <28>; -- gpios = <&gpio 4 0>; -- }; -- }; -- }; -- }; -- -- __overrides__ { -- speed = <&tinylcd35>,"spi-max-frequency:0"; -- rotate = <&tinylcd35>,"rotate:0"; -- fps = <&tinylcd35>,"fps:0"; -- debug = <&tinylcd35>,"debug:0"; -- touch = <&tinylcd35_ts>,"status"; -- touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -- <&tinylcd35_ts>,"interrupts:0", -- <&tinylcd35_ts>,"pendown-gpio:4"; -- xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -- rtc-pcf = <&i2c1>,"status", -- <&pcf8563>,"status"; -- rtc-ds = <&i2c1>,"status", -- <&ds1307>,"status"; -- keypad = <&keypad>,"status"; -- }; --}; -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -deleted file mode 100644 -index 29a3b48..0000000 ---- a/arch/arm/boot/dts/w1-gpio-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for w1-gpio module (without external pullup) --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- -- w1: onewire@0 { -- compatible = "w1-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&w1_pins>; -- gpios = <&gpio 4 0>; -- rpi,parasitic-power = <0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- w1_pins: w1_pins { -- brcm,pins = <4>; -- brcm,function = <0>; // in (initially) -- brcm,pull = <0>; // off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&w1>,"gpios:4", -- <&w1_pins>,"brcm,pins:0"; -- pullup = <&w1>,"rpi,parasitic-power:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -deleted file mode 100644 -index 66a98f6..0000000 ---- a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -+++ /dev/null -@@ -1,41 +0,0 @@ --// Definitions for w1-gpio module (with external pullup) --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- -- w1: onewire@0 { -- compatible = "w1-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&w1_pins>; -- gpios = <&gpio 4 0>, <&gpio 5 1>; -- rpi,parasitic-power = <0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- w1_pins: w1_pins { -- brcm,pins = <4 5>; -- brcm,function = <0 1>; // in out -- brcm,pull = <0 0>; // off off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&w1>,"gpios:4", -- <&w1_pins>,"brcm,pins:0"; -- extpullup = <&w1>,"gpios:16", -- <&w1_pins>,"brcm,pins:4"; -- pullup = <&w1>,"rpi,parasitic-power:0"; -- }; --}; - -From 9c2920928cae9f7d35cb3c0e4f677b7f266a7ae3 Mon Sep 17 00:00:00 2001 -From: mwilliams03 -Date: Fri, 3 Apr 2015 12:40:10 +0000 -Subject: [PATCH 192/216] Swap X Y axis of ads7846 touchscreen controller for - PiScreen TFT - ---- - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -index b7fd7ea..be1e2ec 100644 ---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -80,6 +80,7 @@ - interrupts = <17 2>; /* high-to-low edge triggered */ - interrupt-parent = <&gpio>; - pendown-gpio = <&gpio 17 0>; -+ ti,swap-xy; - ti,x-plate-ohms = /bits/ 16 <100>; - ti,pressure-max = /bits/ 16 <255>; - }; - -From a4d119709c817d2bf6caea401b8266f55ad861c2 Mon Sep 17 00:00:00 2001 -From: mwilliams03 -Date: Wed, 8 Apr 2015 01:13:47 +0000 -Subject: [PATCH 193/216] Added optional parameter to set resistance of touch - plate(x-plate-ohms) - ---- - arch/arm/boot/dts/overlays/README | 2 ++ - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 3 ++- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c260612..9d4f283 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -329,6 +329,8 @@ Params: speed Display SPI bus speed - - debug Debug output level {0-7} - -+ xohms Touchpanel sensitivity (X-plate resistance) -+ - - Name: pitft28-resistive - Info: Adafruit PiTFT 2.8" resistive touch screen -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -index be1e2ec..ba4ad33 100644 ---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -72,7 +72,7 @@ - 0x1000029>; - }; - -- piscreen-ts@1 { -+ piscreen_ts: piscreen-ts@1 { - compatible = "ti,ads7846"; - reg = <1>; - -@@ -91,5 +91,6 @@ - rotate = <&piscreen>,"rotate:0"; - fps = <&piscreen>,"fps:0"; - debug = <&piscreen>,"debug:0"; -+ xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; - }; - }; - -From df11ad948112ccee4eae40b6f4810946a8dc5019 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 28 May 2015 18:50:21 +0200 -Subject: [PATCH 194/216] BCM270x: Move vc_mem -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the vc_mem module available for ARCH_BCM2835 by moving it. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Kconfig | 7 - - arch/arm/mach-bcm2708/Makefile | 1 - - arch/arm/mach-bcm2708/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2708/vc_mem.c | 431 ---------------------------- - arch/arm/mach-bcm2709/Kconfig | 7 - - arch/arm/mach-bcm2709/Makefile | 1 - - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- - drivers/char/broadcom/Kconfig | 13 +- - drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_mem.c | 423 +++++++++++++++++++++++++++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 3 +- - include/linux/broadcom/vc_mem.h | 35 +++ - 13 files changed, 472 insertions(+), 951 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2708/vc_mem.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c - create mode 100644 drivers/char/broadcom/vc_mem.c - create mode 100644 include/linux/broadcom/vc_mem.h - -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 4cfae55..68e3706 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -28,13 +28,6 @@ config BCM2708_GPIO - help - Include support for the Broadcom(R) BCM2708 gpio. - --config BCM2708_VCMEM -- bool "Videocore Memory" -- depends on MACH_BCM2708 -- default y -- help -- Helper for videocore memory access and total size allocation. -- - config BCM2708_NOL2CACHE - bool "Videocore L2 cache disable" - depends on MACH_BCM2708 -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 5552ae8..5120994 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o --obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a338..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -deleted file mode 100644 -index 226b737..0000000 ---- a/arch/arm/mach-bcm2708/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif CONFIG_ARCH_BCM2708 --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -index 4fb6e1b..d61ade0 100644 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -25,13 +25,6 @@ config BCM2708_GPIO - help - Include support for the Broadcom(R) BCM2709 gpio. - --config BCM2708_VCMEM -- bool "Videocore Memory" -- depends on MACH_BCM2709 -- default y -- help -- Helper for videocore memory access and total size allocation. -- - config BCM2708_NOL2CACHE - bool "Videocore L2 cache disable" - depends on MACH_BCM2709 -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 706116f..1ae8b80 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o --obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a338..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -deleted file mode 100644 -index d2adfd1..0000000 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); -diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index fd23e00..c310d9d 100644 ---- a/drivers/char/broadcom/Kconfig -+++ b/drivers/char/broadcom/Kconfig -@@ -7,16 +7,27 @@ menuconfig BRCM_CHAR_DRIVERS - help - Broadcom's char drivers - -+if BRCM_CHAR_DRIVERS -+ - config BCM_VC_CMA - bool "Videocore CMA" -- depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ -+ depends on CMA && BCM2708_VCHIQ - default n - help - Helper for videocore CMA access. - - config BCM_VC_SM - bool "VMCS Shared Memory" -+ select BCM2708_VCMEM - default n - help - Support for the VC shared memory on the Broadcom reference - design. Uses the VCHIQ stack. -+ -+config BCM2708_VCMEM -+ bool "Videocore Memory" -+ default y -+ help -+ Helper for videocore memory access and total size allocation. -+ -+endif -diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 0bf7fdf..b4f8e39d 100644 ---- a/drivers/char/broadcom/Makefile -+++ b/drivers/char/broadcom/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ - obj-$(CONFIG_BCM_VC_SM) += vc_sm/ -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/drivers/char/broadcom/vc_mem.c b/drivers/char/broadcom/vc_mem.c -new file mode 100644 -index 0000000..fcde6b1 ---- /dev/null -+++ b/drivers/char/broadcom/vc_mem.c -@@ -0,0 +1,423 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); -diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c -index 39a8971..0bfb42e 100644 ---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c -+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -15,6 +15,7 @@ - /* ---- Include Files ----------------------------------------------------- */ - - #include -+#include - #include - #include - #include -@@ -35,8 +36,6 @@ - #include - #include - --#include -- - #include "vchiq_connected.h" - #include "vc_vchi_sm.h" - -diff --git a/include/linux/broadcom/vc_mem.h b/include/linux/broadcom/vc_mem.h -new file mode 100644 -index 0000000..20a4753 ---- /dev/null -+++ b/include/linux/broadcom/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#ifndef _VC_MEM_H -+#define _VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* _VC_MEM_H */ - -From 7495f032da212d310393adf5c4d1694190e6f309 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 1 Jun 2015 20:40:11 +0200 -Subject: [PATCH 195/216] BCM270x: Add USB controller to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to dwc_otg driver. -Add device to Device Tree. -Don't add platform devices when booting in DT mode. - -Tested on Pi1 and Pi2 with and without DT. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 8 ++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 7 +++++++ - 4 files changed, 17 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 3f8af85..dc7df47 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -121,6 +121,14 @@ - status = "disabled"; - }; - -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+ - leds: leds { - compatible = "gpio-leds"; - }; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 06438df..6298309 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -955,7 +955,7 @@ void __init bcm2708_init(void) - #endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); -- bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device_dt(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ce06b7d..d8c2336 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -978,7 +978,7 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_systemtimer_device); - #endif - bcm_register_device_dt(&bcm2708_fb_device); -- bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device_dt(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index dc7cd32..53307f0 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -1043,9 +1043,16 @@ static struct platform_device_id platform_ids[] = { - }; - MODULE_DEVICE_TABLE(platform, platform_ids); - -+static const struct of_device_id dwc_otg_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-usb", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, dwc_otg_of_match_table); -+ - static struct platform_driver dwc_otg_driver = { - .driver = { - .name = (char *)dwc_driver_name, -+ .of_match_table = dwc_otg_of_match_table, - }, - .id_table = platform_ids, - - -From da5345649e7ad4deb51692d4d969ba4a2f86974b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 2 Mar 2015 17:57:30 +0000 -Subject: [PATCH 196/216] added mcp251x module to list of modules to get - compiled as well as the corresponding overlay - ---- - arch/arm/boot/dts/Makefile | 2 +- - arch/arm/boot/dts/overlays/Makefile | 1 + - .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 69 ++++++++++++++++++++++ - arch/arm/configs/bcm2709_defconfig | 5 ++ - arch/arm/configs/bcmrpi_defconfig | 8 +++ - 5 files changed, 84 insertions(+), 1 deletion(-) - create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ea93e1d..d5b6a82 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,9 +1,9 @@ - ifeq ($(CONFIG_OF),y) - - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb --dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb -+dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - - # Raspberry Pi - ifeq ($(CONFIG_BCM2708_DT),y) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index d64e6b4..d18a1f2 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -22,6 +22,7 @@ dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mcp2515-can0-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -diff --git a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts -new file mode 100755 -index 0000000..398d59c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts -@@ -0,0 +1,69 @@ -+/* -+ * Device tree overlay for mcp251x/can0 on spi0.0 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* disable spi-dev for spi0.0 */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ spidev@0{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* the interrupt pin of the can-controller */ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ can0_pins: can0_pins { -+ brcm,pins = <25>; -+ brcm,function = <0>; /* input */ -+ }; -+ }; -+ }; -+ -+ /* the clock/oscillator of the can-controller */ -+ fragment@2 { -+ target-path = "/clocks"; -+ __overlay__ { -+ /* external oscillator of mcp2515 on SPI0.0 */ -+ can0_osc: can0_osc { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <16000000>; -+ }; -+ }; -+ }; -+ -+ /* the spi config of the can-controller itself binding everything together */ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ can0: mcp2515@0 { -+ reg = <0>; -+ compatible = "microchip,mcp2515"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&can0_pins>; -+ spi-max-frequency = <10000000>; -+ interrupt-parent = <&gpio>; -+ interrupts = <25 0x2>; -+ clocks = <&can0_osc>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ oscillator = <&can0_osc>,"clock-frequency:0"; -+ spimaxfrequency = <&can0>,"spi-max-frequency:0"; -+ interrupt = <&can0_pins>,"brcm,pins:0",<&can0>,"interrupts:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 5ce9a01..2a1a15a 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -344,7 +344,12 @@ CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m -+CONFIG_CAN_RAW=m -+CONFIG_CAN_BCM=m -+CONFIG_CAN_GW=m - CONFIG_CAN_VCAN=m -+CONFIG_CAN_DEV=m -+CONFIG_CAN_CALC_BITTIMING=y - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index da443da..a2d7291 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -335,6 +335,14 @@ CONFIG_6PACK=m - CONFIG_BPQETHER=m - CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m -+CONFIG_CAN=m -+CONFIG_CAN_RAW=m -+CONFIG_CAN_BCM=m -+CONFIG_CAN_GW=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_DEV=m -+CONFIG_CAN_CALC_BITTIMING=y -+CONFIG_CAN_MCP251X=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m - -From 8e999dc420b342d1304fc2bcd755ab6a36d6896c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 13:55:05 +0200 -Subject: [PATCH 197/216] BCM270x: Move thermal sensor to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to bcm2835-thermal driver. -Add thermal sensor device to Device Tree. -Don't add platform device when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 4 ++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - drivers/thermal/bcm2835-thermal.c | 8 +++++++- - 4 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index dc7df47..fcb5828 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -143,6 +143,10 @@ - reg = <0x7e00b840 0xf>; - interrupts = <0 2>; - }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ }; - }; - - clocks { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6298309..e141c0b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -984,7 +984,7 @@ void __init bcm2708_init(void) - } - - bcm_register_device(&bcm2835_hwmon_device); -- bcm_register_device(&bcm2835_thermal_device); -+ bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) - bcm_register_device_dt(&bcm2708_i2s_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d8c2336..6dadb80 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1007,7 +1007,7 @@ void __init bcm2709_init(void) - } - - bcm_register_device(&bcm2835_hwmon_device); -- bcm_register_device(&bcm2835_thermal_device); -+ bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) - bcm_register_device_dt(&bcm2708_i2s_device); -diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c -index 0c556d1..3bc80f1 100644 ---- a/drivers/thermal/bcm2835-thermal.c -+++ b/drivers/thermal/bcm2835-thermal.c -@@ -167,13 +167,19 @@ static struct thermal_zone_device_ops ops = { - .get_mode = bcm2835_get_mode, - }; - --/* Thermal Driver */ -+static const struct of_device_id bcm2835_thermal_of_match_table[] = { -+ { .compatible = "brcm,bcm2835-thermal", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); -+ - static struct platform_driver bcm2835_thermal_driver = { - .probe = bcm2835_thermal_probe, - .remove = bcm2835_thermal_remove, - .driver = { - .name = "bcm2835_thermal", - .owner = THIS_MODULE, -+ .of_match_table = bcm2835_thermal_of_match_table, - }, - }; - - -From fd724791a4d515e8069884b72f52752501ee0f92 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 13:55:22 +0200 -Subject: [PATCH 198/216] bcm2835: Add thermal sensor to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add the BCM2835 thermal sensor to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 40fc759..efaf4df 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -170,6 +170,10 @@ - reg = <0x7e00b840 0xf>; - interrupts = <0 2>; - }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ }; - }; - - clocks { - -From 34638ffefe49111b137c8b0927c47f9aab23215b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 15:51:24 +0200 -Subject: [PATCH 199/216] BCM270x: Enable bcm2835_wdt and bcm2835-rng -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Change the kconfig dependency to make bcm2835_wdt and bcm2835-rng -available on ARCH_BCM2708 and ARCH_BCM2709. -Enable them as loadable modules in bcmrpi_defconfig and -bcm2709_defconfig. - -There is a commit in linux-next that will move restart/pm_power_off -to bcm2835_wdt for ARCH_BCM2835. This will not affect ARCH_BCM270x -since arm_pm_restart (.restart = bcm2708_restart) and -pm_power_off (=bcm2708_power_off) is set in -arch/arm/mach-bcm270X/bcm270X.c and will take presedence. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - drivers/char/hw_random/Kconfig | 2 +- - drivers/watchdog/Kconfig | 2 +- - 4 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 2a1a15a..d08ae51 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -561,6 +561,7 @@ CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y - CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m - CONFIG_HW_RANDOM_BCM2708=m - CONFIG_RAW_DRIVER=y - CONFIG_BRCM_CHAR_DRIVERS=y -@@ -603,6 +604,7 @@ CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y - CONFIG_BCM2708_WDT=m -+CONFIG_BCM2835_WDT=m - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index a2d7291..11bbfac 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -557,6 +557,7 @@ CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y - CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m - CONFIG_HW_RANDOM_BCM2708=m - CONFIG_RAW_DRIVER=y - CONFIG_BRCM_CHAR_DRIVERS=y -@@ -599,6 +600,7 @@ CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y - CONFIG_BCM2708_WDT=m -+CONFIG_BCM2835_WDT=m - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 1c97093..0996083 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index ca7d6463..e010420 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1222,7 +1222,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom - -From 6779bd793d41be8d73ee771b149606e13e13e0b7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 15:51:52 +0200 -Subject: [PATCH 200/216] BCM270X_DT: Add bcm2835-pm-wdt and bcm2835-rng -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to use the mainline watchdog and -random generator drivers: -dtparam=watchdog=on -dtparam=random=on - -bcm2708_wdog and bcm2708-rng can still be used. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 12 ++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 4 files changed, 18 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 75df21c..52b1404 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -124,5 +124,7 @@ - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index df12b7d..876dfca 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -114,5 +114,7 @@ - act_led_trigger = <&act_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index fcb5828..a80b1a8 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -43,6 +43,18 @@ - #interrupt-cells = <2>; - }; - -+ watchdog: watchdog@7e100000 { -+ compatible = "brcm,bcm2835-pm-wdt"; -+ reg = <0x7e100000 0x28>; -+ status = "disabled"; -+ }; -+ -+ random: rng@7e104000 { -+ compatible = "brcm,bcm2835-rng"; -+ reg = <0x7e104000 0x10>; -+ status = "disabled"; -+ }; -+ - mailbox: mailbox@7e00b800 { - compatible = "brcm,bcm2708-vcio"; - reg = <0x7e00b880 0x40>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 78bc756..b226dfb 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -124,5 +124,7 @@ - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; - -From 493b7b5c56b4afd21bd980e38deb0f9d7d06061c Mon Sep 17 00:00:00 2001 +From 070a6f51cd5f81f635cfcccd3452ee5f252a7ee4 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 201/216] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 73/77] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -153634,3120 +134261,186 @@ index 70f2f39..f7fdacd 100644 static const char * const bcm2835_compat[] = { -From e98419e0f836f39ae77a595f0d7218ba4b0576ab Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:34:24 +0200 -Subject: [PATCH 202/216] bcm2835: Match BCM270X Device Trees -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 45 +++++++++++------ - arch/arm/boot/dts/bcm2835-rpi-b.dts | 29 +++++++---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 85 +++++++++++++++++++++++++------- - arch/arm/boot/dts/bcm2835.dtsi | 12 ++--- - 4 files changed, 122 insertions(+), 49 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -index e479515..b0fb0e8 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -@@ -4,27 +4,40 @@ - / { - compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; - model = "Raspberry Pi Model B+"; -+}; -+ -+&gpio { -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; - -- leds { -- act { -- gpios = <&gpio 47 0>; -- }; -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+&act_led { -+ gpios = <&gpio 47 0>; -+}; - -- pwr { -- label = "PWR"; -- gpios = <&gpio 35 0>; -- default-state = "keep"; -- linux,default-trigger = "default-on"; -- }; -+&leds { -+ pwr_led: pwr { -+ label = "led1"; -+ linux,default-trigger = "input"; -+ gpios = <&gpio 35 0>; - }; - }; - --&gpio { -- pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; - -- /* I2S interface */ -- i2s_alt0: i2s_alt0 { -- brcm,pins = <18 19 20 21>; -- brcm,function = <4>; /* alt0 */ -+ pwr_led_gpio = <&pwr_led>,"gpios:4"; -+ pwr_led_activelow = <&pwr_led>,"gpios:8"; -+ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts -index bafa46f..b867224 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts -@@ -5,19 +5,28 @@ - compatible = "raspberrypi,model-b", "brcm,bcm2835"; - model = "Raspberry Pi Model B"; - -- leds { -- act { -- gpios = <&gpio 16 1>; -- }; -- }; - }; - - &gpio { -- pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; -- -- /* I2S interface */ -- i2s_alt2: i2s_alt2 { -+ i2s_pins: i2s { - brcm,pins = <28 29 30 31>; -- brcm,function = <6>; /* alt2 */ -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+&act_led { -+ gpios = <&gpio 16 1>; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index f23835e..466f02b 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -1,17 +1,29 @@ - /include/ "bcm2835.dtsi" - - / { -+ /* This is left here in case u-boot needs it */ - memory { - reg = <0 0x10000000>; - }; - -- leds { -+ aliases { -+ soc = &soc; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ intc = &intc; -+ leds = &leds; -+ sound = &sound; -+ }; -+ -+ leds: leds { - compatible = "gpio-leds"; - -- act { -- label = "ACT"; -- default-state = "keep"; -- linux,default-trigger = "heartbeat"; -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; - }; - }; - -@@ -19,35 +31,61 @@ - audio: audio { - compatible = "brcm,bcm2835-audio"; - brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ -+ /* External sound card */ -+ sound: sound { - }; - }; - - &gpio { -- pinctrl-names = "default"; -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; - -- gpioout: gpioout { -- brcm,pins = <6>; -- brcm,function = <1>; /* GPIO out */ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; - }; - -- alt0: alt0 { -- brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; -- brcm,function = <4>; /* alt0 */ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; - }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; - -- alt3: alt3 { -- brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <7>; /* alt3 */ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; - }; - }; - - &i2c0 { -- status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; - clock-frequency = <100000>; - }; - - &i2c1 { -- status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; - clock-frequency = <100000>; - }; - -@@ -59,3 +97,16 @@ - &fb { - status = "okay"; - }; -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ audio = <&audio>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index efaf4df..4b6dd65f 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -9,7 +9,7 @@ - bootargs = ""; - }; - -- soc { -+ soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; -@@ -51,12 +51,12 @@ - #interrupt-cells = <2>; - }; - -- watchdog@7e100000 { -+ watchdog: watchdog@7e100000 { - compatible = "brcm,bcm2835-pm-wdt"; - reg = <0x7e100000 0x28>; - }; - -- rng@7e104000 { -+ random: rng@7e104000 { - compatible = "brcm,bcm2835-rng"; - reg = <0x7e104000 0x10>; - }; -@@ -90,7 +90,7 @@ - #interrupt-cells = <2>; - }; - -- uart@7e201000 { -+ uart0: uart@7e201000 { - compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; - reg = <0x7e201000 0x1000>; - interrupts = <2 25>; -@@ -109,7 +109,7 @@ - status = "disabled"; - }; - -- spi: spi@7e204000 { -+ spi0: spi@7e204000 { - compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; - interrupts = <2 22>; -@@ -150,7 +150,7 @@ - status = "disabled"; - }; - -- usb@7e980000 { -+ usb: usb@7e980000 { - compatible = "brcm,bcm2835-usb"; - reg = <0x7e980000 0x10000>; - interrupts = <1 9>; - -From 3ac358b4ca8e0b71da28992689669218e0dbbacf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:35:11 +0200 -Subject: [PATCH 203/216] dts: Enable overlays on ARCH_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Build Device Tree overlays on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 3 +++ - arch/arm/boot/dts/overlays/Makefile | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index d5b6a82..e7ce7c4 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,9 @@ endif - ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif - - subdir-$(RPI_DT_OVERLAYS) += overlays - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index d18a1f2..c449c3f 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -8,6 +8,9 @@ endif - ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif - - dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - -From 6c6321340ea33c79dbfb15441ad58db03ec94167 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:35:55 +0200 -Subject: [PATCH 204/216] bcm2835: Make camera and sound drivers available -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Change kconfig dependency to make SND_BCM2708_SOC_* and -VIDEO_BCM2835 available on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/media/platform/bcm2835/Kconfig | 2 +- - sound/soc/bcm/Kconfig | 14 +++++++------- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig -index 2cb1a68..99a5cbc 100644 ---- a/drivers/media/platform/bcm2835/Kconfig -+++ b/drivers/media/platform/bcm2835/Kconfig -@@ -2,7 +2,7 @@ - - config VIDEO_BCM2835 - bool "Broadcom BCM2835 camera interface driver" -- depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709) -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) - ---help--- - Say Y here to enable camera host interface devices for - Broadcom BCM2835 SoC. This operates over the VCHIQ interface -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 003ae28..516ab9d 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -21,49 +21,49 @@ config SND_BCM2708_SOC_I2S - - config SND_BCM2708_SOC_HIFIBERRY_DAC - tristate "Support for HifiBerry DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM5102A - help - Say Y or M if you want to add support for HifiBerry DAC. - - config SND_BCM2708_SOC_HIFIBERRY_DACPLUS - tristate "Support for HifiBerry DAC+" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM512x - help - Say Y or M if you want to add support for HifiBerry DAC+. - - config SND_BCM2708_SOC_HIFIBERRY_DIGI - tristate "Support for HifiBerry Digi" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_WM8804 - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - - config SND_BCM2708_SOC_HIFIBERRY_AMP - tristate "Support for the HifiBerry Amp" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_TAS5713 - help - Say Y or M if you want to add support for the HifiBerry Amp amplifier board. - - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. - - config SND_BCM2708_SOC_RPI_PROTO - tristate "Support for Rpi-PROTO" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_WM8731 - help - Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). - - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM512x_I2C - help - Say Y or M if you want to add support for IQaudIO-DAC. - -From b5b5fa6e2a877089b48daaaac9b135c95c71e24f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:36:19 +0200 -Subject: [PATCH 205/216] bcm2835: Merge bcm2835_defconfig with - bcmrpi_defconfig -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These commands where used to make this commit: - -./scripts/diffconfig -m arch/arm/configs/bcm2835_defconfig arch/arm/configs/bcmrpi_defconfig > merge.cfg - -cat << EOF > filter -CONFIG_ARCH_BCM2708 -CONFIG_BCM2708_DT -CONFIG_ARM_PATCH_PHYS_VIRT -CONFIG_PHYS_OFFSET -CONFIG_CMDLINE -CONFIG_BCM2708_WDT -CONFIG_HW_RANDOM_BCM2708 -CONFIG_I2C_BCM2708 -CONFIG_SPI_BCM2708 -CONFIG_SND_BCM2708_SOC_I2S -CONFIG_USB_DWCOTG -CONFIG_LIRC_RPI -EOF - -grep -F -v -f filter merge.cfg > filtered.cfg - -cat << EOF > added.cfg -CONFIG_WATCHDOG=y -CONFIG_BCM2835_WDT=y -CONFIG_MISC_FILESYSTEMS=y -CONFIG_SND_BCM2835_SOC_I2S=m -EOF - -ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2835_defconfig filtered.cfg added.cfg -ARCH=arm make oldconfig - -ARCH=arm make savedefconfig -cp defconfig arch/arm/configs/bcm2835_defconfig - -rm merge.cfg filter filtered.cfg added.cfg defconfig - -ARCH=arm make bcm2835_defconfig -ARCH=arm make oldconfig - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 1114 +++++++++++++++++++++++++++++++++++- - 1 file changed, 1097 insertions(+), 17 deletions(-) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 1af6069..2e8a95a 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -1,107 +1,1071 @@ - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y - CONFIG_FHANDLE=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y - CONFIG_BSD_PROCESS_ACCT=y - CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y - CONFIG_LOG_BUF_SHIFT=18 - CONFIG_CGROUP_FREEZER=y - CONFIG_CGROUP_DEVICE=y - CONFIG_CPUSETS=y - CONFIG_CGROUP_CPUACCT=y -+CONFIG_MEMCG=y - CONFIG_CGROUP_PERF=y - CONFIG_CFS_BANDWIDTH=y - CONFIG_RT_GROUP_SCHED=y -+CONFIG_BLK_CGROUP=y - CONFIG_NAMESPACES=y - CONFIG_SCHED_AUTOGROUP=y --CONFIG_RELAY=y - CONFIG_BLK_DEV_INITRD=y - CONFIG_CC_OPTIMIZE_FOR_SIZE=y --CONFIG_KALLSYMS_ALL=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_PROFILING=y --CONFIG_OPROFILE=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y - CONFIG_JUMP_LABEL=y - CONFIG_CC_STACKPROTECTOR_REGULAR=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_MULTI_V6=y - # CONFIG_ARCH_MULTI_V7 is not set - CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2835=y --CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_PREEMPT=y - CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y - CONFIG_KSM=y - CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_KEXEC=y - CONFIG_CRASH_DUMP=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=m -+CONFIG_CPU_FREQ_STAT_DETAILS=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_VFP=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+CONFIG_BINFMT_MISC=m - # CONFIG_SUSPEND is not set - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m - CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_LRO=m -+CONFIG_INET_DIAG=m -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y - CONFIG_NETWORK_SECMARK=y - CONFIG_NETFILTER=y --CONFIG_CFG80211=y --CONFIG_MAC80211=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_NFC_PN533=m - CONFIG_DEVTMPFS=y - CONFIG_DEVTMPFS_MOUNT=y - # CONFIG_STANDALONE is not set -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m - CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m - CONFIG_SCSI_CONSTANTS=y - CONFIG_SCSI_SCAN_ASYNC=y -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m - CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m - CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m - CONFIG_USB_NET_SMSC95XX=y --CONFIG_ZD1211RW=y --CONFIG_INPUT_EVDEV=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_AT76C50X_USB=m -+CONFIG_USB_ZD1201=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_RTL8187=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_ATH_CARDS=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8192CU=m -+CONFIG_ZD1211RW=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y - # CONFIG_LEGACY_PTYS is not set - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m -+CONFIG_RAW_DRIVER=y -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VC_SM=y - CONFIG_I2C=y --CONFIG_I2C_CHARDEV=y -+CONFIG_I2C_CHARDEV=m - CONFIG_I2C_BCM2835=y - CONFIG_SPI=y --CONFIG_SPI_BCM2835=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m - CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m - # CONFIG_HWMON is not set -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y - CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m - CONFIG_USB_DWC2=y -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_LED=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m - CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2835=y --CONFIG_NEW_LEDS=y -+CONFIG_MMC_SPI=m - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_GPIO=y --CONFIG_LEDS_TRIGGERS=y - CONFIG_LEDS_TRIGGER_TIMER=y - CONFIG_LEDS_TRIGGER_ONESHOT=y - CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y - CONFIG_LEDS_TRIGGER_CPU=y - CONFIG_LEDS_TRIGGER_GPIO=y - CONFIG_LEDS_TRIGGER_DEFAULT_ON=y --CONFIG_LEDS_TRIGGER_TRANSIENT=y --CONFIG_LEDS_TRIGGER_CAMERA=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_DS3234=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_RX4581=m - CONFIG_DMADEVICES=y - CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m - CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m - CONFIG_MAILBOX=y - CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m - CONFIG_EXT2_FS=y - CONFIG_EXT2_FS_XATTR=y - CONFIG_EXT2_FS_POSIX_ACL=y -@@ -109,18 +1073,110 @@ CONFIG_EXT3_FS=y - CONFIG_EXT3_FS_POSIX_ACL=y - CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m - CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y --# CONFIG_MISC_FILESYSTEMS is not set -+CONFIG_CONFIGFS_FS=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_F2FS_FS=y - CONFIG_NFS_FS=y --CONFIG_NFSD=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" - CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m - CONFIG_NLS_ASCII=y --CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m - CONFIG_NLS_UTF8=y -+CONFIG_DLM=m - CONFIG_PRINTK_TIME=y - CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_DYNAMIC_DEBUG=y -@@ -130,14 +1186,38 @@ CONFIG_DEBUG_INFO=y - CONFIG_UNUSED_SYMBOLS=y - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_LOCKUP_DETECTOR=y -+CONFIG_TIMER_STATS=y -+# CONFIG_DEBUG_PREEMPT is not set -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y - CONFIG_SCHED_TRACER=y - CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set - CONFIG_FUNCTION_PROFILER=y - CONFIG_TEST_KSTRTOX=y - CONFIG_KGDB=y - CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y - CONFIG_STRICT_DEVMEM=y - CONFIG_DEBUG_LL=y - CONFIG_EARLY_PRINTK=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_SHA1_ARM=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_AES_ARM=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+# CONFIG_CRYPTO_HW is not set -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y - # CONFIG_XZ_DEC_ARM is not set - # CONFIG_XZ_DEC_ARMTHUMB is not set - -From c712b42d06623b5410a3921f71278963a9a45209 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 24 Mar 2015 16:57:04 +0000 -Subject: [PATCH 206/216] BCM270x_DT: Configure UART using DT - -See: https://github.com/raspberrypi/firmware/issues/393 ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708_common.dtsi | 27 +++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 7 +++++++ - arch/arm/mach-bcm2708/bcm2708.c | 9 +++++---- - arch/arm/mach-bcm2709/bcm2709.c | 9 +++++---- - 6 files changed, 58 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 52b1404..99ab3c9 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -108,6 +113,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 876dfca..e8c80cd 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -102,6 +107,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a80b1a8..a09a3c7 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -84,6 +84,17 @@ - status = "disabled"; - }; - -+ uart0: uart@7e201000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x7e201000 0x1000>; -+ interrupts = <2 25>; -+ clocks = <&clk_uart0 &clk_apb_p>; -+ clock-names = "uartclk","apb_pclk"; -+ arm,primecell-periphid = <0x00241011>; // For an explanation, see -+ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -188,5 +199,21 @@ - clock-output-names = "spi"; - clock-frequency = <250000000>; - }; -+ -+ clk_uart0: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <3>; -+ #clock-cells = <0>; -+ clock-output-names = "uart0_pclk"; -+ clock-frequency = <3000000>; -+ }; -+ -+ clk_apb_p: clock@4 { -+ compatible = "fixed-clock"; -+ reg = <4>; -+ #clock-cells = <0>; -+ clock-output-names = "apb_pclk"; -+ clock-frequency = <126000000>; -+ }; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index b226dfb..39b6fd4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -108,6 +113,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e141c0b..e17c1de 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -1020,10 +1020,11 @@ void __init bcm2708_init(void) - i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); - #endif - -- -- for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -- struct amba_device *d = amba_devs[i]; -- amba_device_register(d, &iomem_resource); -+ if (!use_dt) { -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); -+ } - } - system_rev = boardrev; - system_serial_low = serial; -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 6dadb80..8834a10 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1043,10 +1043,11 @@ void __init bcm2709_init(void) - i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); - #endif - -- -- for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -- struct amba_device *d = amba_devs[i]; -- amba_device_register(d, &iomem_resource); -+ if (!use_dt) { -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); -+ } - } - system_rev = boardrev; - system_serial_low = serial; - -From aa05d1fe61d794be63d7e6055881e36c33cdb09c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 4 Jun 2015 16:16:08 +0100 -Subject: [PATCH 207/216] vchiq_arm: ARCH_BCM2835 compatibility - -Use virt_to_dma (not ideal, I know) to calculate the virt-to-bus -offset. This will make use of the "dma-ranges" property, if -present. ---- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 660aad2..c739083 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -46,7 +46,7 @@ - - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - --#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) -+#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) - - #include "vchiq_arm.h" - #include "vchiq_2835.h" -@@ -66,7 +66,8 @@ typedef struct vchiq_2835_state_struct { - static void __iomem *g_regs; - static FRAGMENTS_T *g_fragments_base; - static FRAGMENTS_T *g_free_fragments; --struct semaphore g_free_fragments_sema; -+static struct semaphore g_free_fragments_sema; -+static unsigned long g_virt_to_bus_offset; - - extern int vchiq_arm_log_level; - -@@ -92,6 +93,8 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) - int slot_mem_size, frag_mem_size; - int err, irq, i; - -+ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); -+ - /* Allocate space for the channels in coherent memory */ - slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); - frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); - -From fa0a4bff157dddc6207cba9911a1581864cf2307 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Jun 2015 14:00:54 +0100 -Subject: [PATCH 208/216] BCM270x_DT: Enable UART in the example Compute Module - DTS as well +From 3add74da14e27d18ef276f66c55a69e6dc014216 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 16 Jun 2015 17:47:27 +0100 +Subject: [PATCH 74/77] platform: Add force_core command line setting to boot + from a different core number --- - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 11 +++++++++++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 3 ++- - 3 files changed, 14 insertions(+), 1 deletion(-) + arch/arm/mach-bcm2709/armctrl.c | 17 ++++++++++++++++- + arch/arm/mach-bcm2709/bcm2709.c | 2 ++ + 2 files changed, 18 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -index 45f8244..238bd65 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -5,3 +5,14 @@ - / { - model = "Raspberry Pi Compute Module"; - }; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+/ { -+ __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 1c2cfcf..43830a6 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -11,6 +11,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a09a3c7..dc0346b 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -185,10 +185,11 @@ - clock-frequency = <250000000>; - }; - -- clk_i2c: i2c { -+ clk_i2c: clock@1 { - compatible = "fixed-clock"; - reg = <1>; - #clock-cells = <0>; -+ clock-output-names = "i2c"; - clock-frequency = <250000000>; - }; - - -From fae583caba82c37f9a1e0cff81fbaa4c3f768657 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Jun 2015 15:59:08 +0100 -Subject: [PATCH 209/216] bcm270x defconfigs: Remove spurious entries - ---- - arch/arm/configs/bcm2709_defconfig | 5 ----- - arch/arm/configs/bcmrpi_defconfig | 8 -------- - 2 files changed, 13 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index d08ae51..78e1202 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -344,12 +344,7 @@ CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m --CONFIG_CAN_RAW=m --CONFIG_CAN_BCM=m --CONFIG_CAN_GW=m - CONFIG_CAN_VCAN=m --CONFIG_CAN_DEV=m --CONFIG_CAN_CALC_BITTIMING=y - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 11bbfac..c6a5db2 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -335,14 +335,6 @@ CONFIG_6PACK=m - CONFIG_BPQETHER=m - CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m --CONFIG_CAN=m --CONFIG_CAN_RAW=m --CONFIG_CAN_BCM=m --CONFIG_CAN_GW=m --CONFIG_CAN_VCAN=m --CONFIG_CAN_DEV=m --CONFIG_CAN_CALC_BITTIMING=y --CONFIG_CAN_MCP251X=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m - -From 549ff9d4fee2f6dc0abdeaa552754ce2197ba331 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 09:00:01 +0100 -Subject: [PATCH 210/216] BCM270x_DT: Add a label to the clocks node, and a few - aliases - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 2 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 2 +- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 5 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 99ab3c9..c9053f8 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e8c80cd..32066c3 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 43830a6..f38a0c2 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -10,8 +10,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index dc0346b..a9f1507 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -172,7 +172,7 @@ - }; - }; - -- clocks { -+ clocks: clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 39b6fd4..a9adaf4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { - -From 1b8bcc8ef9b600f7ac5e4d40bd70b507ad02aa01 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 09:01:02 +0100 -Subject: [PATCH 211/216] sdhost-overlay: Move clock declaration out of /soc - ---- - arch/arm/boot/dts/overlays/sdhost-overlay.dts | 29 +++++++++++++++------------ - 1 file changed, 16 insertions(+), 13 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -index b2653e9..8fb28e9 100644 ---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts -+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -@@ -24,23 +24,26 @@ - brcm,overclock-50 = <0>; - status = "okay"; - }; -+ }; -+ }; - -- clocks { -- #address-cells = <1>; -- #size-cells = <0>; -+ fragment@1 { -+ target = <&clocks>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; - -- clk_sdhost: clock@3 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "sdhost"; -- clock-frequency = <250000000>; -- }; -+ clk_sdhost: sdhost { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; - }; - }; - }; - -- fragment@1 { -+ fragment@2 { - target = <&gpio>; - __overlay__ { - sdhost_pins: sdhost_pins { -@@ -50,7 +53,7 @@ - }; - }; - -- fragment@2 { -+ fragment@3 { - target = <&mmc>; - __overlay__ { - /* Find a way to disable the other driver */ -@@ -59,7 +62,7 @@ - }; - }; - -- fragment@3 { -+ fragment@4 { - target-path = "/__overrides__"; - __overlay__ { - sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; - -From 24d8164a16fb825c4bee4a8cca87f55a68f33edf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 6 Jun 2015 23:45:32 +0200 -Subject: [PATCH 212/216] BCM270X_DT: Enable 'make clean' on overlays directory -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Always add the overlays directory to subdir so it can be -cleaned with 'make clean'. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e7ce7c4..d85583c 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -16,8 +16,6 @@ ifeq ($(CONFIG_ARCH_BCM2835),y) - RPI_DT_OVERLAYS=y - endif - --subdir-$(RPI_DT_OVERLAYS) += overlays -- - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC -@@ -676,3 +674,5 @@ clean-files := *.dtb - ifeq ($(RPI_DT_OVERLAYS),y) - DTC_FLAGS ?= -@ - endif -+ -+subdir-y += overlays - -From 2b53c727bbb2ba40102236f127ea6e68b1148335 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 13:35:33 +0200 -Subject: [PATCH 213/216] hwmon: Remove bcm2835-hwmon -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -bcm2835-thermal combined with the configs HWMON=y and -THERMAL_HWMON=y, gives the same functionality. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 5 - - arch/arm/mach-bcm2709/bcm2709.c | 5 - - drivers/hwmon/Kconfig | 10 -- - drivers/hwmon/Makefile | 1 - - drivers/hwmon/bcm2835-hwmon.c | 219 ---------------------------------------- - 5 files changed, 240 deletions(-) - delete mode 100644 drivers/hwmon/bcm2835-hwmon.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e17c1de..4f191d9 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -697,10 +697,6 @@ static struct platform_device bcm2708_bsc1_device = { - .resource = bcm2708_bsc1_resources, +diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c +index a366275..90805a6 100644 +--- a/arch/arm/mach-bcm2709/armctrl.c ++++ b/arch/arm/mach-bcm2709/armctrl.c +@@ -45,6 +45,8 @@ static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { + INTERRUPT_VC_ARASANSDIO }; --static struct platform_device bcm2835_hwmon_device = { -- .name = "bcm2835_hwmon", --}; -- - static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; -@@ -983,7 +979,6 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2708_bsc1_device); - } - -- bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8834a10..d61bb30 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -718,10 +718,6 @@ static struct platform_device bcm2708_bsc1_device = { - .resource = bcm2708_bsc1_resources, - }; - --static struct platform_device bcm2835_hwmon_device = { -- .name = "bcm2835_hwmon", --}; -- - static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; -@@ -1006,7 +1002,6 @@ void __init bcm2709_init(void) - bcm_register_device_dt(&bcm2708_bsc1_device); - } - -- bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 8c4474d..110fade 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -1703,16 +1703,6 @@ config SENSORS_ULTRA45 - This driver provides support for the Ultra45 workstation environmental - sensors. - --config SENSORS_BCM2835 -- depends on THERMAL_BCM2835=n -- tristate "Broadcom BCM2835 HWMON Driver" -- help -- If you say yes here you get support for the hardware -- monitoring features of the BCM2835 Chip -- -- This driver can also be built as a module. If so, the module -- will be called bcm2835-hwmon. -- - if ACPI - - comment "ACPI drivers" -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index e7c60cb..6c94147 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -155,7 +155,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o - obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o - obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o - obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o --obj-$(CONFIG_SENSORS_BCM2835) += bcm2835-hwmon.o - - obj-$(CONFIG_PMBUS) += pmbus/ - -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -deleted file mode 100644 -index d14502c..0000000 ---- a/drivers/hwmon/bcm2835-hwmon.c -+++ /dev/null -@@ -1,219 +0,0 @@ --/***************************************************************************** --* Copyright 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define MODULE_NAME "bcm2835_hwmon" -- --/*#define HWMON_DEBUG_ENABLE*/ -- --#ifdef HWMON_DEBUG_ENABLE --#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__) --#else --#define print_debug(fmt,...) --#endif --#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__) --#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__) -- --#define VC_TAG_GET_TEMP 0x00030006 --#define VC_TAG_GET_MAX_TEMP 0x0003000A -- --/* --- STRUCTS --- */ --struct bcm2835_hwmon_data { -- struct device *hwmon_dev; --}; -- --/* tag part of the message */ --struct vc_msg_tag { -- uint32_t tag_id; /* the tag ID for the temperature */ -- uint32_t buffer_size; /* size of the buffer (should be 8) */ -- uint32_t request_code; /* identifies message as a request (should be 0) */ -- uint32_t id; /* extra ID field (should be 0) */ -- uint32_t val; /* returned value of the temperature */ --}; -- --/* message structure to be sent to videocore */ --struct vc_msg { -- uint32_t msg_size; /* simply, sizeof(struct vc_msg) */ -- uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */ -- struct vc_msg_tag tag; /* the tag structure above to make */ -- uint32_t end_tag; /* an end identifier, should be set to NULL */ --}; -- --typedef enum { -- TEMP, -- MAX_TEMP, --} temp_type; -- --/* --- PROTOTYPES --- */ --static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf); --static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf); -- --/* --- GLOBALS --- */ -- --static struct bcm2835_hwmon_data *bcm2835_data; --static struct platform_driver bcm2835_hwmon_driver; -- --static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0); --static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP); --static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP); -- --static struct attribute* bcm2835_attributes[] = { -- &sensor_dev_attr_name.dev_attr.attr, -- &sensor_dev_attr_temp1_input.dev_attr.attr, -- &sensor_dev_attr_temp1_max.dev_attr.attr, -- NULL, --}; -- --static struct attribute_group bcm2835_attr_group = { -- .attrs = bcm2835_attributes, --}; -- --/* --- FUNCTIONS --- */ -- --static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf) --{ -- return sprintf(buf,"bcm2835_hwmon\n"); --} -- --static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf) --{ -- struct vc_msg msg; -- int result; -- uint temp = 0; -- int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index; -- -- print_debug("IN"); -- -- /* wipe all previous message data */ -- memset(&msg, 0, sizeof msg); -- -- /* determine the message type */ -- if(index == TEMP) -- msg.tag.tag_id = VC_TAG_GET_TEMP; -- else if (index == MAX_TEMP) -- msg.tag.tag_id = VC_TAG_GET_MAX_TEMP; -- else -- { -- print_debug("Unknown temperature message!"); -- return -EINVAL; -- } -- -- msg.msg_size = sizeof msg; -- msg.tag.buffer_size = 8; -- -- /* send the message */ -- result = bcm_mailbox_property(&msg, sizeof msg); -- -- /* check if it was all ok and return the rate in milli degrees C */ -- if (result == 0 && (msg.request_code & 0x80000000)) -- temp = (uint)msg.tag.val; -- #ifdef HWMON_DEBUG_ENABLE -- else -- print_debug("Failed to get temperature!"); -- #endif -- print_debug("Got temperature as %u",temp); -- print_debug("OUT"); -- return sprintf(buf, "%u\n", temp); --} -- -- --static int bcm2835_hwmon_probe(struct platform_device *pdev) --{ -- int err; -- -- print_debug("IN"); -- print_debug("HWMON Driver has been probed!"); -- -- /* check that the device isn't null!*/ -- if(pdev == NULL) -- { -- print_debug("Platform device is empty!"); -- return -ENODEV; -- } -- -- /* allocate memory for neccessary data */ -- bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL); -- if(!bcm2835_data) -- { -- print_debug("Unable to allocate memory for hwmon data!"); -- err = -ENOMEM; -- goto kzalloc_error; -- } -- -- /* create the sysfs files */ -- if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group)) -- { -- print_debug("Unable to create sysfs files!"); -- err = -EFAULT; -- goto sysfs_error; -- } -- -- /* register the hwmon device */ -- bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev); -- if (IS_ERR(bcm2835_data->hwmon_dev)) -- { -- err = PTR_ERR(bcm2835_data->hwmon_dev); -- goto hwmon_error; -- } -- print_debug("OUT"); -- return 0; -- -- /* error goto's */ -- hwmon_error: -- sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -- -- sysfs_error: -- kfree(bcm2835_data); -- -- kzalloc_error: -- -- return err; -- --} -- --static int bcm2835_hwmon_remove(struct platform_device *pdev) --{ -- print_debug("IN"); -- hwmon_device_unregister(bcm2835_data->hwmon_dev); -- -- sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -- print_debug("OUT"); -- return 0; --} -- --/* Hwmon Driver */ --static struct platform_driver bcm2835_hwmon_driver = { -- .probe = bcm2835_hwmon_probe, -- .remove = bcm2835_hwmon_remove, -- .driver = { -- .name = "bcm2835_hwmon", -- .owner = THIS_MODULE, -- }, --}; -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Dorian Peake"); --MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip"); -- --module_platform_driver(bcm2835_hwmon_driver); - -From a4573f4e07996b61582f828189091bede1296d25 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 6 Jun 2015 22:59:28 +0200 -Subject: [PATCH 214/216] BCM270x: Make uart1 work with Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add uart1 to Device Tree. Enable it in AUXENB when it's used. -Remove old platform device. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + - arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 10 +++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + - arch/arm/mach-bcm2708/bcm2708.c | 35 +++++++++++--------------------- - arch/arm/mach-bcm2709/bcm2709.c | 34 +++++++++++-------------------- - 7 files changed, 38 insertions(+), 45 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index c9053f8..0fa2210 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 32066c3..3fd49d0 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index f38a0c2..3da7d3b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -13,6 +13,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a9f1507..8caa234 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -134,6 +134,16 @@ - status = "disabled"; - }; - -+ uart1: uart@7e215040 { -+ compatible = "brcm,bcm2835-aux-uart", "ns16550"; -+ reg = <0x7e215040 0x40>; -+ interrupts = <1 29>; -+ clock-frequency = <500000000>; -+ reg-shift = <2>; -+ no-loopback-test; -+ status = "disabled"; -+ }; ++extern unsigned force_core; + - i2c1: i2c@7e804000 { - compatible = "brcm,bcm2708-i2c"; - reg = <0x7e804000 0x1000>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index a9adaf4..8aaaf1f 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 4f191d9..f1706366 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -353,28 +353,6 @@ static struct platform_device bcm2708_fb_device = { - }, - }; - --static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -- { -- .mapbase = UART1_BASE + 0x40, -- .irq = IRQ_AUX, -- .uartclk = 500000000, -- .regshift = 2, -- .iotype = UPIO_MEM, -- .flags = UPF_SHARE_IRQ | UPF_FIXED_TYPE | UPF_FIXED_PORT | -- UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_16550, -- }, -- {}, --}; -- --static struct platform_device bcm2708_uart1_device = { -- .name = "serial8250", -- .id = PLAT8250_DEV_PLATFORM, -- .dev = { -- .platform_data = bcm2708_uart1_platform_data, -- }, --}; -- - static struct resource bcm2708_usb_resources[] = { - [0] = { - .start = USB_BASE, -@@ -897,6 +875,17 @@ static void bcm2708_power_off(void) - } - } - -+static void __init bcm2708_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2708: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ - #ifdef CONFIG_OF - static void __init bcm2708_dt_init(void) + static void armctrl_mask_irq(struct irq_data *d) { -@@ -952,13 +941,13 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); + static const unsigned int disables[4] = { +@@ -92,7 +94,13 @@ static void armctrl_unmask_irq(struct irq_data *d) + int i; + if (d->irq >= FIQ_START) { + unsigned int data; +- if (num_online_cpus() > 1) { ++ if (force_core) { ++ data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ data &= ~0xc; ++ data |= ((force_core-1) << 2); ++ writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ } ++ else if (num_online_cpus() > 1) { + data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); + data &= ~0xc; + data |= (1 << 2); +@@ -119,6 +127,13 @@ static void armctrl_unmask_irq(struct irq_data *d) + } #endif - bcm2708_init_led(); -+ bcm2708_init_uart1(); - - /* Only create the platform devices for the ALSA driver in the - absence of an enabled "audio" DT node */ + } else if (d->irq >= ARM_IRQ1_BASE && d->irq < ARM_IRQ_LOCAL_BASE) { ++ if (force_core) { ++ unsigned int data; ++ data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ data &= ~0x3; ++ data |= ((force_core-1) << 0); ++ writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ } + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); + } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d61bb30..ffa667e 100644 +index 507ff52..c5e51e8 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -363,27 +363,6 @@ static struct platform_device bcm2708_fb_device = { - }, - }; +@@ -96,6 +96,7 @@ static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + static int pps_gpio_pin = -1; ++unsigned force_core; --static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -- { -- .mapbase = UART1_BASE + 0x40, -- .irq = IRQ_AUX, -- .uartclk = 125000000, -- .regshift = 2, -- .iotype = UPIO_MEM, -- .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_8250, -- }, -- {}, --}; -- --static struct platform_device bcm2708_uart1_device = { -- .name = "serial8250", -- .id = PLAT8250_DEV_PLATFORM, -- .dev = { -- .platform_data = bcm2708_uart1_platform_data, -- }, --}; -- - static struct resource bcm2708_usb_resources[] = { - [0] = { - .start = USB_BASE, -@@ -918,6 +897,17 @@ static void bcm2709_power_off(void) + static unsigned use_dt = 0; + +@@ -1305,6 +1306,7 @@ MACHINE_START(BCM2708, "BCM2709") + .dt_compat = bcm2709_compat, + MACHINE_END + ++module_param(force_core, uint, 0644); + module_param(boardrev, uint, 0644); + module_param(serial, uint, 0644); + module_param(uart_clock, uint, 0644); + +From a283be0c98260b1f29c8c46df7e8fb2a9cdaf5a8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jun 2015 17:46:17 +0100 +Subject: [PATCH 75/77] mach-bcm270x: Enable the building of pinctrl-bcm2835 + +--- + drivers/pinctrl/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index 6eadf04..ca6e1be 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o + ++obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ + obj-$(CONFIG_ARCH_BCM) += bcm/ + obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-y += freescale/ + +From fd08db11f15960c30449a5a2cb14d3ab7fd470ea Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jun 2015 18:06:28 +0100 +Subject: [PATCH 76/77] squash: Fix inconsistency in pinctrl Makefile patch + +--- + drivers/pinctrl/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index ca6e1be..9119513 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -38,7 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o + +-obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ ++obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += bcm/ + obj-$(CONFIG_ARCH_BCM) += bcm/ + obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-y += freescale/ + +From 05376fce25aaab4f47182a5af04928bfa06f30d6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Jun 2015 19:53:58 +0100 +Subject: [PATCH 77/77] platform: squash: Remove IRQF_DISABLED + +--- + arch/arm/mach-bcm2708/armctrl.c | 2 +- + arch/arm/mach-bcm2708/bcm2708.c | 2 +- + arch/arm/mach-bcm2708/bcm2708_gpio.c | 2 +- + arch/arm/mach-bcm2709/bcm2709.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c +index 74bacb3..0429225 100644 +--- a/arch/arm/mach-bcm2708/armctrl.c ++++ b/arch/arm/mach-bcm2708/armctrl.c +@@ -305,7 +305,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); +- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - } -+static void __init bcm2709_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2709: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ - #ifdef CONFIG_OF - static void __init bcm2709_dt_init(void) - { -@@ -975,13 +965,13 @@ void __init bcm2709_init(void) - #endif - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2709_init_led(); -+ bcm2709_init_uart1(); - - /* Only create the platform devices for the ALSA driver in the - absence of an enabled "audio" DT node */ - -From 31c0f40b228b657d4c8968c32768992a3bbcefb6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 20:42:35 +0200 -Subject: [PATCH 215/216] fixup: BCM2709: Remove unused clock implementation - ---- - arch/arm/mach-bcm2709/clock.c | 61 ------------------------------------------- - arch/arm/mach-bcm2709/clock.h | 24 ----------------- - 2 files changed, 85 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/clock.c - delete mode 100644 arch/arm/mach-bcm2709/clock.h - -diff --git a/arch/arm/mach-bcm2709/clock.c b/arch/arm/mach-bcm2709/clock.c -deleted file mode 100644 -index 4fc556e..0000000 ---- a/arch/arm/mach-bcm2709/clock.c -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "clock.h" -- --int clk_enable(struct clk *clk) --{ -- return 0; --} --EXPORT_SYMBOL(clk_enable); -- --void clk_disable(struct clk *clk) --{ --} --EXPORT_SYMBOL(clk_disable); -- --unsigned long clk_get_rate(struct clk *clk) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_get_rate); -- --long clk_round_rate(struct clk *clk, unsigned long rate) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_round_rate); -- --int clk_set_rate(struct clk *clk, unsigned long rate) --{ -- return -EIO; --} --EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2709/clock.h b/arch/arm/mach-bcm2709/clock.h -deleted file mode 100644 -index 5f9d725..0000000 ---- a/arch/arm/mach-bcm2709/clock.h -+++ /dev/null -@@ -1,24 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --struct module; -- --struct clk { -- unsigned long rate; --}; - -From 6ae9c7a93909159bde1a92fd305e99443e4ac680 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 20:42:52 +0200 -Subject: [PATCH 216/216] BCM270x: Remove bcm2708_systemtimer and - bcm2708_powerman -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These devices do not have a matching driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 50 -------------------------------------- - arch/arm/mach-bcm2709/bcm2709.c | 54 ----------------------------------------- - 2 files changed, 104 deletions(-) - + armctrl_pm_register(base, irq_start, resume_sources); diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f1706366..00fc5d6 100644 +index cfc4f13..937c2d3 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -465,33 +465,6 @@ static struct platform_device bcm2708_gpio_device = { +@@ -1028,7 +1028,7 @@ static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, }; - #endif --static struct resource bcm2708_systemtimer_resources[] = { -- [0] = { /* system timer access */ -- .start = ST_BASE, -- .end = ST_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -- { -- .start = IRQ_TIMER3, -- .end = IRQ_TIMER3, -- .flags = IORESOURCE_IRQ, -- } -- --}; -- --static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --static struct platform_device bcm2708_systemtimer_device = { -- .name = "bcm2708_systemtimer", -- .id = -1, /* only one VideoCore I/O area */ -- .resource = bcm2708_systemtimer_resources, -- .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -- .dev = { -- .dma_mask = &systemtimer_dmamask, -- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -- }, --}; -- - #ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ - static struct resource bcm2835_emmc_resources[] = { - [0] = { -@@ -520,27 +493,6 @@ struct platform_device bcm2835_emmc_device = { +diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c +index c1e9254..e33265d 100644 +--- a/arch/arm/mach-bcm2708/bcm2708_gpio.c ++++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c +@@ -306,7 +306,7 @@ static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, }; - #endif /* CONFIG_MMC_BCM2835 */ --static struct resource bcm2708_powerman_resources[] = { -- [0] = { -- .start = PM_BASE, -- .end = PM_BASE + SZ_256 - 1, -- .flags = IORESOURCE_MEM, -- }, --}; -- --static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --struct platform_device bcm2708_powerman_device = { -- .name = "bcm2708_powerman", -- .id = 0, -- .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -- .resource = bcm2708_powerman_resources, -- .dev = { -- .dma_mask = &powerman_dmamask, -- .coherent_dma_mask = 0xffffffffUL}, --}; -- -- - static struct platform_device bcm2708_alsa_devices[] = { - [0] = { - .name = "bcm2835_AUD0", -@@ -938,10 +890,8 @@ void __init bcm2708_init(void) - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; - bcm_register_device_dt(&w1_device); - #endif -- bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ffa667e..a5cac5b 100644 +index c5e51e8..fe71c50 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -485,35 +485,6 @@ static struct platform_device bcm2708_gpio_device = { +@@ -1050,7 +1050,7 @@ static irqreturn_t bcm2709_timer_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2709_timer_irq = { + .name = "BCM2709 Timer Tick", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2709_timer_interrupt, }; - #endif --#ifdef SYSTEM_TIMER --static struct resource bcm2708_systemtimer_resources[] = { -- [0] = { /* system timer access */ -- .start = ST_BASE, -- .end = ST_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -- { -- .start = IRQ_TIMER3, -- .end = IRQ_TIMER3, -- .flags = IORESOURCE_IRQ, -- } -- --}; -- --static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --static struct platform_device bcm2708_systemtimer_device = { -- .name = "bcm2708_systemtimer", -- .id = -1, /* only one VideoCore I/O area */ -- .resource = bcm2708_systemtimer_resources, -- .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -- .dev = { -- .dma_mask = &systemtimer_dmamask, -- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -- }, --}; --#endif -- - #ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ - static struct resource bcm2835_emmc_resources[] = { - [0] = { -@@ -542,27 +513,6 @@ struct platform_device bcm2835_emmc_device = { - }; - #endif /* CONFIG_MMC_BCM2835 */ - --static struct resource bcm2708_powerman_resources[] = { -- [0] = { -- .start = PM_BASE, -- .end = PM_BASE + SZ_256 - 1, -- .flags = IORESOURCE_MEM, -- }, --}; -- --static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --struct platform_device bcm2708_powerman_device = { -- .name = "bcm2708_powerman", -- .id = 0, -- .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -- .resource = bcm2708_powerman_resources, -- .dev = { -- .dma_mask = &powerman_dmamask, -- .coherent_dma_mask = 0xffffffffUL}, --}; -- -- - static struct platform_device bcm2708_alsa_devices[] = { - [0] = { - .name = "bcm2835_AUD0", -@@ -960,12 +910,8 @@ void __init bcm2709_init(void) - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; - bcm_register_device_dt(&w1_device); - #endif --#ifdef SYSTEM_TIMER -- bcm_register_device(&bcm2708_systemtimer_device); --#endif - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); diff --git a/projects/RPi2/linux/linux.arm.conf b/projects/RPi2/linux/linux.arm.conf index 7825e17135..d472b2287f 100644 --- a/projects/RPi2/linux/linux.arm.conf +++ b/projects/RPi2/linux/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.0.5 Kernel Configuration +# Linux/arm 4.1.0-rc8 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -19,6 +19,7 @@ CONFIG_ARM_PATCH_PHYS_VIRT=y CONFIG_NEED_MACH_IO_H=y CONFIG_NEED_MACH_MEMORY_H=y CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -58,13 +59,14 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y +CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_ARCH_HAS_TICK_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y @@ -103,6 +105,7 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_TREE_RCU_TRACE is not set CONFIG_RCU_KTHREAD_PRIO=0 # CONFIG_RCU_NOCB_CPU is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y @@ -140,6 +143,7 @@ CONFIG_HAVE_UID16=y CONFIG_BPF=y CONFIG_EXPERT=y # CONFIG_UID16 is not set +CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set # CONFIG_SYSFS_SYSCALL is not set CONFIG_SYSCTL_SYSCALL=y @@ -207,6 +211,7 @@ CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y @@ -286,11 +291,11 @@ CONFIG_LOCK_SPIN_ON_OWNER=y # System Type # CONFIG_MMU=y +# CONFIG_ARCH_BCM2708 is not set +CONFIG_ARCH_BCM2709=y # CONFIG_ARCH_MULTIPLATFORM is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCM2708 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set @@ -309,7 +314,6 @@ CONFIG_MMU=y # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE_LEGACY is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set @@ -317,7 +321,6 @@ CONFIG_MMU=y # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set -CONFIG_ARCH_BCM2709=y CONFIG_BCM2708_GPIO=y CONFIG_BCM2708_NOL2CACHE=y CONFIG_BCM2708_SPIDEV=y @@ -354,9 +357,9 @@ CONFIG_ARM_THUMB=y CONFIG_ARM_VIRT_EXT=y CONFIG_SWP_EMULATE=y # CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_KUSER_HELPERS=y +CONFIG_VDSO=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y # CONFIG_CACHE_L2X0 is not set CONFIG_ARM_L1_CACHE_SHIFT_6=y @@ -445,6 +448,7 @@ CONFIG_CLEANCACHE=y CONFIG_FRONTSWAP=y CONFIG_CMA=y # CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set CONFIG_CMA_AREAS=7 # CONFIG_ZSWAP is not set # CONFIG_ZPOOL is not set @@ -502,6 +506,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y # CONFIG_CPUFREQ_DT is not set # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set CONFIG_ARM_BCM2835_CPUFREQ=y +# CONFIG_QORIQ_CPUFREQ is not set # # CPU Idle @@ -513,6 +518,7 @@ CONFIG_CPU_IDLE_GOV_MENU=y # # ARM CPU Idle Drivers # +# CONFIG_ARM_CPUIDLE is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # @@ -531,7 +537,6 @@ CONFIG_NEON=y # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -819,7 +824,7 @@ CONFIG_DNS_RESOLVER=y # CONFIG_VSOCKETS is not set # CONFIG_NETLINK_MMAP is not set # CONFIG_NETLINK_DIAG is not set -# CONFIG_NET_MPLS_GSO is not set +# CONFIG_MPLS is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set CONFIG_RPS=y @@ -847,11 +852,15 @@ CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_HIDP=m CONFIG_BT_LE=y # CONFIG_BT_SELFTEST is not set +# CONFIG_BT_DEBUGFS is not set # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set CONFIG_BT_HCIBCM203X=m @@ -942,7 +951,6 @@ CONFIG_CMA_ALIGNMENT=8 # Bus devices # # CONFIG_BRCMSTB_GISB_ARB is not set -# CONFIG_ARM_CCI is not set # CONFIG_VEXPRESS_CONFIG is not set # CONFIG_CONNECTOR is not set # CONFIG_MTD is not set @@ -974,6 +982,7 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_PMEM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set @@ -1110,13 +1119,7 @@ CONFIG_TUN=y # Distributed Switch Architecture drivers # # CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6060 is not set # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -# CONFIG_NET_DSA_MV88E6171 is not set -# CONFIG_NET_DSA_MV88E6352 is not set -# CONFIG_NET_DSA_BCM_SF2 is not set # CONFIG_ETHERNET is not set CONFIG_PHYLIB=y @@ -1125,7 +1128,6 @@ CONFIG_PHYLIB=y # # CONFIG_AT803X_PHY is not set # CONFIG_AMD_PHY is not set -# CONFIG_AMD_XGBE_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -1430,8 +1432,8 @@ CONFIG_HW_RANDOM_BCM2708=m # CONFIG_TCG_TPM is not set CONFIG_BRCM_CHAR_DRIVERS=y CONFIG_BCM_VC_CMA=y -# CONFIG_BCM_VC_SM is not set CONFIG_BCM2708_VCMEM=y +# CONFIG_BCM_VC_SM is not set # CONFIG_XILLYBUS is not set # @@ -1548,8 +1550,9 @@ CONFIG_PINCTRL=y CONFIG_PINMUX=y CONFIG_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set -CONFIG_PINCTRL_BCM2835=y +# CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_BCM2835=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y @@ -1559,55 +1562,44 @@ CONFIG_OF_GPIO=y CONFIG_GPIO_SYSFS=y # -# Memory mapped GPIO drivers: +# Memory mapped GPIO drivers # # CONFIG_GPIO_74XX_MMIO is not set -# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_ALTERA is not set # CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_EM is not set -# CONFIG_GPIO_ZEVIO is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_SCH311X is not set -# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_ZEVIO is not set # -# I2C GPIO expanders: +# I2C GPIO expanders # -CONFIG_GPIO_ARIZONA=m +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set -# CONFIG_GPIO_ADNP is not set # -# PCI GPIO expanders: +# MFD GPIO expanders # +CONFIG_GPIO_ARIZONA=m # -# SPI GPIO expanders: +# SPI GPIO expanders # +# CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_MAX7301 is not set # CONFIG_GPIO_MCP23S08 is not set # CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set # -# AC97 GPIO expanders: -# - -# -# LPC GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# - -# -# USB GPIO expanders: +# USB GPIO expanders # CONFIG_W1=m @@ -1736,6 +1728,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT15 is not set @@ -1871,10 +1864,12 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set # CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_VIPERBOARD is not set @@ -1890,6 +1885,7 @@ CONFIG_MFD_RTSX_USB=y # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set # CONFIG_MFD_STMPE is not set @@ -2191,7 +2187,6 @@ CONFIG_MEDIA_TUNER_FC0013=m CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88TS2022=m CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_IT913X=m @@ -2448,6 +2443,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m # CONFIG_SND_SOC_FSL_SPDIF is not set # CONFIG_SND_SOC_FSL_ESAI is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_QCOM is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -2511,6 +2507,8 @@ CONFIG_SND_SOC_WM8731=m # CONFIG_SND_SOC_WM8770 is not set # CONFIG_SND_SOC_WM8776 is not set CONFIG_SND_SOC_WM8804=m +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set # CONFIG_SND_SOC_WM8903 is not set # CONFIG_SND_SOC_WM8962 is not set # CONFIG_SND_SOC_WM8978 is not set @@ -2551,7 +2549,6 @@ CONFIG_DRAGONRISE_FF=y CONFIG_HID_EZKEY=y # CONFIG_HID_HOLTEK is not set # CONFIG_HID_GT683R is not set -# CONFIG_HID_HUION is not set # CONFIG_HID_KEYTOUCH is not set CONFIG_HID_KYE=y # CONFIG_HID_UCLOGIC is not set @@ -2780,6 +2777,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set # CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set # # USB Physical Layer drivers @@ -2854,6 +2852,7 @@ CONFIG_LEDS_GPIO=y # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers @@ -2895,6 +2894,7 @@ CONFIG_RTC_INTF_DEV=y # I2C RTC drivers # # CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set CONFIG_RTC_DRV_DS1307=m # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set @@ -2975,7 +2975,6 @@ CONFIG_DMADEVICES=y # DMA Devices # # CONFIG_AMBA_PL08X is not set -# CONFIG_DW_DMAC_CORE is not set # CONFIG_DW_DMAC is not set # CONFIG_PL330_DMA is not set CONFIG_DMA_BCM2708=y @@ -3040,6 +3039,7 @@ CONFIG_LIRC_XBOX=m # CONFIG_GS_FPGABOOT is not set # CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_FB_TFT is not set +# CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3052,7 +3052,6 @@ CONFIG_COMMON_CLK=y # CONFIG_CLK_QORIQ is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_CDCE706 is not set -# CONFIG_COMMON_CLK_QCOM is not set # # Hardware Spinlock drivers @@ -3069,9 +3068,9 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y # CONFIG_SH_TIMER_MTU2 is not set # CONFIG_SH_TIMER_TMU is not set # CONFIG_EM_TIMER_STI is not set -# CONFIG_CLKSRC_VERSATILE is not set CONFIG_MAILBOX=y CONFIG_BCM2708_MBOX=y +# CONFIG_ARM_MHU is not set # CONFIG_PL320_MBOX is not set # CONFIG_ALTERA_MBOX is not set # CONFIG_IOMMU_SUPPORT is not set @@ -3100,6 +3099,7 @@ CONFIG_EXTCON_ARIZONA=m # CONFIG_EXTCON_GPIO is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set # CONFIG_MEMORY is not set # CONFIG_IIO is not set # CONFIG_PWM is not set @@ -3121,6 +3121,11 @@ CONFIG_IRQCHIP=y # # CONFIG_ANDROID is not set +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set + # # File systems # @@ -3131,6 +3136,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set @@ -3158,6 +3164,10 @@ CONFIG_BTRFS_FS=m # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set # CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +# CONFIG_F2FS_FS_XATTR is not set +CONFIG_F2FS_CHECK_FS=y CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y CONFIG_FILE_LOCKING=y @@ -3245,10 +3255,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_F2FS_FS=y -CONFIG_F2FS_STAT_FS=y -# CONFIG_F2FS_FS_XATTR is not set -CONFIG_F2FS_CHECK_FS=y CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3402,6 +3408,7 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_TIMER_STATS is not set # @@ -3429,6 +3436,7 @@ CONFIG_PANIC_TIMEOUT=0 # # RCU Debugging # +# CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set @@ -3467,6 +3475,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -3566,7 +3575,6 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA1_ARM=m CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3576,7 +3584,6 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_ARM=m # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -3611,6 +3618,10 @@ CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_USER_API_RNG is not set # CONFIG_CRYPTO_HW is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_SHA256_ARM=m +CONFIG_CRYPTO_AES_ARM=m # CONFIG_BINARY_PRINTF is not set # diff --git a/projects/RPi2/options b/projects/RPi2/options index e8df837a09..28b3747c9d 100644 --- a/projects/RPi2/options +++ b/projects/RPi2/options @@ -57,7 +57,7 @@ # Kernel to use. values can be: # default: default mainline kernel - LINUX="4.0" + LINUX="default" # NOOBS supported hex versions NOOBS_HEX="1040,1041" diff --git a/projects/RPi2/patches/linux/linux-01-RPi_support.patch b/projects/RPi2/patches/linux/linux-01-RPi_support.patch index c1f57bb01c..0008aa8b30 100644 --- a/projects/RPi2/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi2/patches/linux/linux-01-RPi_support.patch @@ -1,52 +1,77 @@ -From 0e7aaf92061593060fc62957aeec745534add9a4 Mon Sep 17 00:00:00 2001 +From 8e2bdce040b3459de0954cb2f212dea47549131c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 001/216] Main bcm2708 linux port +Subject: [PATCH 01/77] Main bcm2708/bcm2709 linux port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix +Signed-off-by: Noralf Trønnes --- - arch/arm/Kconfig | 17 + + arch/arm/Kconfig | 39 ++ arch/arm/Kconfig.debug | 8 + - arch/arm/Makefile | 1 + + arch/arm/Makefile | 2 + + arch/arm/kernel/head.S | 8 + arch/arm/kernel/process.c | 10 + - arch/arm/mach-bcm2708/Kconfig | 26 + - arch/arm/mach-bcm2708/Makefile | 6 + + arch/arm/mach-bcm2708/Kconfig | 30 + + arch/arm/mach-bcm2708/Makefile | 5 + arch/arm/mach-bcm2708/Makefile.boot | 3 + - arch/arm/mach-bcm2708/armctrl.c | 208 +++++++ + arch/arm/mach-bcm2708/armctrl.c | 304 +++++++++ arch/arm/mach-bcm2708/armctrl.h | 27 + - arch/arm/mach-bcm2708/bcm2708.c | 662 +++++++++++++++++++++++ + arch/arm/mach-bcm2708/bcm2708.c | 622 ++++++++++++++++++ arch/arm/mach-bcm2708/bcm2708.h | 49 ++ - arch/arm/mach-bcm2708/clock.c | 61 +++ - arch/arm/mach-bcm2708/clock.h | 24 + - arch/arm/mach-bcm2708/dma.c | 399 ++++++++++++++ - arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 ++++++++++++++ - arch/arm/mach-bcm2708/include/mach/arm_power.h | 62 +++ + arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 ++++++++++++ arch/arm/mach-bcm2708/include/mach/clkdev.h | 7 + arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 + - arch/arm/mach-bcm2708/include/mach/dma.h | 88 +++ - arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 +++ + arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 ++ arch/arm/mach-bcm2708/include/mach/frc.h | 38 ++ arch/arm/mach-bcm2708/include/mach/hardware.h | 28 + arch/arm/mach-bcm2708/include/mach/io.h | 27 + - arch/arm/mach-bcm2708/include/mach/irqs.h | 196 +++++++ + arch/arm/mach-bcm2708/include/mach/irqs.h | 196 ++++++ arch/arm/mach-bcm2708/include/mach/memory.h | 57 ++ - arch/arm/mach-bcm2708/include/mach/platform.h | 228 ++++++++ - arch/arm/mach-bcm2708/include/mach/power.h | 26 + + arch/arm/mach-bcm2708/include/mach/platform.h | 228 +++++++ arch/arm/mach-bcm2708/include/mach/system.h | 38 ++ arch/arm/mach-bcm2708/include/mach/timex.h | 23 + arch/arm/mach-bcm2708/include/mach/uncompress.h | 84 +++ - arch/arm/mach-bcm2708/include/mach/vc_mem.h | 35 ++ - arch/arm/mach-bcm2708/include/mach/vcio.h | 165 ++++++ arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + - arch/arm/mach-bcm2708/power.c | 197 +++++++ - arch/arm/mach-bcm2708/vc_mem.c | 431 +++++++++++++++ - arch/arm/mach-bcm2708/vcio.c | 474 ++++++++++++++++ + arch/arm/mach-bcm2709/Kconfig | 42 ++ + arch/arm/mach-bcm2709/Makefile | 6 + + arch/arm/mach-bcm2709/Makefile.boot | 3 + + arch/arm/mach-bcm2709/armctrl.c | 361 ++++++++++ + arch/arm/mach-bcm2709/armctrl.h | 27 + + arch/arm/mach-bcm2709/bcm2708_gpio.c | 426 ++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 801 +++++++++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.h | 49 ++ + arch/arm/mach-bcm2709/delay.S | 21 + + arch/arm/mach-bcm2709/include/mach/arm_control.h | 493 ++++++++++++++ + arch/arm/mach-bcm2709/include/mach/barriers.h | 3 + + arch/arm/mach-bcm2709/include/mach/clkdev.h | 7 + + arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 + + arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 ++++ + arch/arm/mach-bcm2709/include/mach/frc.h | 38 ++ + arch/arm/mach-bcm2709/include/mach/gpio.h | 17 + + arch/arm/mach-bcm2709/include/mach/hardware.h | 28 + + arch/arm/mach-bcm2709/include/mach/io.h | 27 + + arch/arm/mach-bcm2709/include/mach/irqs.h | 225 +++++++ + arch/arm/mach-bcm2709/include/mach/memory.h | 57 ++ + arch/arm/mach-bcm2709/include/mach/platform.h | 225 +++++++ + arch/arm/mach-bcm2709/include/mach/system.h | 38 ++ + arch/arm/mach-bcm2709/include/mach/timex.h | 23 + + arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 +++ + arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 + + arch/arm/mach-bcm2709/include/mach/vc_support.h | 69 ++ + arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 + + arch/arm/mach-bcm2709/vc_mem.c | 431 ++++++++++++ + arch/arm/mach-bcm2709/vc_support.c | 318 +++++++++ arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 15 +- - arch/arm/tools/mach-types | 1 + + arch/arm/mm/proc-v7.S | 1 + + arch/arm/tools/mach-types | 2 + + drivers/clocksource/arm_arch_timer.c | 36 + drivers/tty/serial/amba-pl011.c | 2 +- include/linux/mmc/host.h | 1 + - 41 files changed, 4251 insertions(+), 5 deletions(-) + 62 files changed, 6436 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-bcm2708/Kconfig create mode 100644 arch/arm/mach-bcm2708/Makefile create mode 100644 arch/arm/mach-bcm2708/Makefile.boot @@ -54,14 +79,9 @@ Signed-off-by: popcornmix create mode 100644 arch/arm/mach-bcm2708/armctrl.h create mode 100644 arch/arm/mach-bcm2708/bcm2708.c create mode 100644 arch/arm/mach-bcm2708/bcm2708.h - create mode 100644 arch/arm/mach-bcm2708/clock.c - create mode 100644 arch/arm/mach-bcm2708/clock.h - create mode 100644 arch/arm/mach-bcm2708/dma.c create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_control.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/clkdev.h create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h create mode 100644 arch/arm/mach-bcm2708/include/mach/entry-macro.S create mode 100644 arch/arm/mach-bcm2708/include/mach/frc.h create mode 100644 arch/arm/mach-bcm2708/include/mach/hardware.h @@ -69,57 +89,102 @@ Signed-off-by: popcornmix create mode 100644 arch/arm/mach-bcm2708/include/mach/irqs.h create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h create mode 100644 arch/arm/mach-bcm2708/include/mach/timex.h create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h - create mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2708/power.c - create mode 100644 arch/arm/mach-bcm2708/vc_mem.c - create mode 100644 arch/arm/mach-bcm2708/vcio.c + create mode 100644 arch/arm/mach-bcm2709/Kconfig + create mode 100644 arch/arm/mach-bcm2709/Makefile + create mode 100644 arch/arm/mach-bcm2709/Makefile.boot + create mode 100644 arch/arm/mach-bcm2709/armctrl.c + create mode 100644 arch/arm/mach-bcm2709/armctrl.h + create mode 100644 arch/arm/mach-bcm2709/bcm2708_gpio.c + create mode 100644 arch/arm/mach-bcm2709/bcm2709.c + create mode 100644 arch/arm/mach-bcm2709/bcm2709.h + create mode 100644 arch/arm/mach-bcm2709/delay.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_control.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/barriers.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/clkdev.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S + create mode 100644 arch/arm/mach-bcm2709/include/mach/frc.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/gpio.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/hardware.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/irqs.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/timex.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h + create mode 100755 arch/arm/mach-bcm2709/include/mach/vc_support.h + create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h + create mode 100644 arch/arm/mach-bcm2709/vc_mem.c + create mode 100644 arch/arm/mach-bcm2709/vc_support.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index cf4c0c9..6876ae8 100644 +index 45df48b..bd9b2f3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -369,6 +369,22 @@ config ARCH_AT91 - This enables support for systems based on Atmel - AT91RM9200, AT91SAM9 and SAMA5 processors. +@@ -314,6 +314,42 @@ choice + default ARCH_VERSATILE if !MMU + default ARCH_MULTIPLATFORM if MMU +config ARCH_BCM2708 + bool "Broadcom BCM2708 family" + select CPU_V6 + select ARM_AMBA -+ select HAVE_CLK + select HAVE_SCHED_CLOCK + select NEED_MACH_GPIO_H + select NEED_MACH_MEMORY_H -+ select CLKDEV_LOOKUP ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ + select GENERIC_CLOCKEVENTS + select ARM_ERRATA_411920 + select MACH_BCM2708 + select VC4 ++ select FIQ + help + This enables support for Broadcom BCM2708 boards. + - config ARCH_CLPS711X - bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" - select ARCH_REQUIRE_GPIOLIB -@@ -967,6 +983,7 @@ source "arch/arm/plat-versatile/Kconfig" - source "arch/arm/mach-vt8500/Kconfig" - - source "arch/arm/mach-w90x900/Kconfig" ++config ARCH_BCM2709 ++ bool "Broadcom BCM2709 family" ++ select ARCH_HAS_BARRIERS if SMP ++ select CPU_V7 ++ select HAVE_SMP ++ select ARM_AMBA ++ select MIGHT_HAVE_CACHE_L2X0 ++ select HAVE_SCHED_CLOCK ++ select NEED_MACH_MEMORY_H ++ select NEED_MACH_IO_H ++ select COMMON_CLK ++ select ARCH_HAS_CPUFREQ ++ select GENERIC_CLOCKEVENTS ++ select MACH_BCM2709 ++ select VC4 ++ select FIQ ++ help ++ This enables support for Broadcom BCM2709 boards. ++ + config ARCH_MULTIPLATFORM + bool "Allow multiple platforms to be selected" + depends on MMU +@@ -823,6 +859,9 @@ config ARCH_VIRT + # Kconfigs may be included either alphabetically (according to the + # plat- suffix) or along side the corresponding mach-* source. + # +source "arch/arm/mach-bcm2708/Kconfig" ++source "arch/arm/mach-bcm2709/Kconfig" ++ + source "arch/arm/mach-mvebu/Kconfig" - source "arch/arm/mach-zynq/Kconfig" - + source "arch/arm/mach-alpine/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 970de75..eaadbe8 100644 +index 0c12ffb..18db6c4 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -1209,6 +1209,14 @@ choice +@@ -1197,6 +1197,14 @@ choice options; the platform specific options are deprecated and will be soon removed. @@ -135,22 +200,42 @@ index 970de75..eaadbe8 100644 config DEBUG_AT91_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index eb7bb51..27c0f92 100644 +index 985227c..e5df9a5 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile -@@ -146,6 +146,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 +@@ -142,6 +142,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 + + # Machine directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. ++machine-$(CONFIG_ARCH_BCM2708) += bcm2708 ++machine-$(CONFIG_ARCH_BCM2709) += bcm2709 + machine-$(CONFIG_ARCH_ALPINE) += alpine machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_AXXIA) += axxia - machine-$(CONFIG_ARCH_BCM) += bcm -+machine-$(CONFIG_ARCH_BCM2708) += bcm2708 - machine-$(CONFIG_ARCH_BERLIN) += berlin - machine-$(CONFIG_ARCH_CLPS711X) += clps711x - machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 3637973..380430a 100644 +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -680,6 +680,14 @@ ARM_BE8(rev16 ip, ip) + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 1b + ret lr ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop + #endif + ENDPROC(__fixup_a_pv_table) + diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 2bf1a16..2915516 100644 +index f192a2a..f638dae 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c -@@ -172,6 +172,16 @@ void arch_cpu_idle_dead(void) +@@ -98,6 +98,16 @@ void arch_cpu_idle_dead(void) } #endif @@ -164,15 +249,15 @@ index 2bf1a16..2915516 100644 + +__setup("reboot=", reboot_setup); + - /* - * Called by kexec, immediately prior to machine_kexec(). - * + void __show_regs(struct pt_regs *regs) + { + unsigned long flags; diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig new file mode 100644 -index 0000000..1f11478 +index 0000000..4955422 --- /dev/null +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -0,0 +1,26 @@ +@@ -0,0 +1,30 @@ +menu "Broadcom BCM2708 Implementations" + depends on ARCH_BCM2708 + @@ -184,12 +269,16 @@ index 0000000..1f11478 + help + Include support for the Broadcom(R) BCM2708 platform. + -+config BCM2708_VCMEM -+ bool "Videocore Memory" ++config BCM2708_DT ++ bool "BCM2708 Device Tree support" + depends on MACH_BCM2708 -+ default y -+ help -+ Helper for videocore memory access and total size allocation. ++ default n ++ select USE_OF ++ select ARCH_REQUIRE_GPIOLIB ++ select PINCTRL ++ select PINCTRL_BCM2835 ++ help ++ Enable Device Tree support for BCM2708 + +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" @@ -201,16 +290,15 @@ index 0000000..1f11478 +endmenu diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile new file mode 100644 -index 0000000..c76f39bc +index 0000000..e7d5a29 --- /dev/null +++ b/arch/arm/mach-bcm2708/Makefile -@@ -0,0 +1,6 @@ +@@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + -+obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o ++obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot new file mode 100644 index 0000000..67039c3 @@ -222,10 +310,10 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c new file mode 100644 -index 0000000..ef1c8d5 +index 0000000..cd252fa --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -0,0 +1,208 @@ +@@ -0,0 +1,304 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * @@ -251,6 +339,8 @@ index 0000000..ef1c8d5 +#include +#include +#include ++#include ++#include + +#include +#include @@ -297,6 +387,99 @@ index 0000000..ef1c8d5 + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); +} + ++#ifdef CONFIG_OF ++ ++#define NR_IRQS_BANK0 21 ++#define NR_BANKS 3 ++#define IRQS_PER_BANK 32 ++ ++/* from drivers/irqchip/irq-bcm2835.c */ ++static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ if (WARN_ON(intsize != 2)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[0] >= NR_BANKS)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) ++ return -EINVAL; ++ ++ if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) ++ return -EINVAL; ++ ++ if (intspec[0] == 0) ++ *out_hwirq = ARM_IRQ0_BASE + intspec[1]; ++ else if (intspec[0] == 1) ++ *out_hwirq = ARM_IRQ1_BASE + intspec[1]; ++ else ++ *out_hwirq = ARM_IRQ2_BASE + intspec[1]; ++ ++ /* reverse remap_irqs[] */ ++ switch (*out_hwirq) { ++ case INTERRUPT_VC_JPEG: ++ *out_hwirq = INTERRUPT_JPEG; ++ break; ++ case INTERRUPT_VC_USB: ++ *out_hwirq = INTERRUPT_USB; ++ break; ++ case INTERRUPT_VC_3D: ++ *out_hwirq = INTERRUPT_3D; ++ break; ++ case INTERRUPT_VC_DMA2: ++ *out_hwirq = INTERRUPT_DMA2; ++ break; ++ case INTERRUPT_VC_DMA3: ++ *out_hwirq = INTERRUPT_DMA3; ++ break; ++ case INTERRUPT_VC_I2C: ++ *out_hwirq = INTERRUPT_I2C; ++ break; ++ case INTERRUPT_VC_SPI: ++ *out_hwirq = INTERRUPT_SPI; ++ break; ++ case INTERRUPT_VC_I2SPCM: ++ *out_hwirq = INTERRUPT_I2SPCM; ++ break; ++ case INTERRUPT_VC_SDIO: ++ *out_hwirq = INTERRUPT_SDIO; ++ break; ++ case INTERRUPT_VC_UART: ++ *out_hwirq = INTERRUPT_UART; ++ break; ++ case INTERRUPT_VC_ARASANSDIO: ++ *out_hwirq = INTERRUPT_ARASANSDIO; ++ break; ++ } ++ ++ *out_type = IRQ_TYPE_NONE; ++ return 0; ++} ++ ++static struct irq_domain_ops armctrl_ops = { ++ .xlate = armctrl_xlate ++}; ++ ++void __init armctrl_dt_init(void) ++{ ++ struct device_node *np; ++ struct irq_domain *domain; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); ++ if (!np) ++ return; ++ ++ domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, ++ IRQ_ARMCTRL_START, 0, ++ &armctrl_ops, NULL); ++ WARN_ON(!domain); ++} ++#else ++void __init armctrl_dt_init(void) { } ++#endif /* CONFIG_OF */ ++ +#if defined(CONFIG_PM) + +/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ @@ -432,6 +615,7 @@ index 0000000..ef1c8d5 + } + + armctrl_pm_register(base, irq_start, resume_sources); ++ armctrl_dt_init(); + return 0; +} diff --git a/arch/arm/mach-bcm2708/armctrl.h b/arch/arm/mach-bcm2708/armctrl.h @@ -469,10 +653,10 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 -index 0000000..9b4e709 +index 0000000..d6659b0 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -0,0 +1,662 @@ +@@ -0,0 +1,622 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * @@ -502,10 +686,14 @@ index 0000000..9b4e709 +#include +#include +#include ++#include ++#include +#include +#include +#include +#include ++#include ++#include + +#include +#include @@ -523,15 +711,12 @@ index 0000000..9b4e709 +#include + +#include -+#include -+#include +#include + +#include + +#include "bcm2708.h" +#include "armctrl.h" -+#include "clock.h" + +#ifdef CONFIG_BCM_VC_CMA +#include @@ -552,11 +737,13 @@ index 0000000..9b4e709 + +/* command line parameters */ +static unsigned boardrev, serial; -+static unsigned uart_clock; ++static unsigned uart_clock = UART0_CLOCK; +static unsigned disk_led_gpio = 16; +static unsigned disk_led_active_low = 1; +static unsigned reboot_part = 0; + ++static unsigned use_dt = 0; ++ +static void __init bcm2708_init_led(void); + +void __init bcm2708_init_irq(void) @@ -662,44 +849,40 @@ index 0000000..9b4e709 + } +} + ++struct clk __init *bcm2708_clk_register(const char *name, unsigned long fixed_rate) ++{ ++ struct clk *clk; + -+/* -+ * These are fixed clocks. -+ */ -+static struct clk ref24_clk = { -+ .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */ -+}; ++ clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, ++ fixed_rate); ++ if (IS_ERR(clk)) ++ pr_err("%s not registered\n", name); + -+static struct clk osc_clk = { -+#ifdef CONFIG_ARCH_BCM2708_CHIPIT -+ .rate = 27000000, -+#else -+ .rate = 500000000, /* ARM clock is set from the VideoCore booter */ -+#endif -+}; ++ return clk; ++} + -+/* warning - the USB needs a clock > 34MHz */ ++void __init bcm2708_register_clkdev(struct clk *clk, const char *name) ++{ ++ int ret; + -+#ifdef CONFIG_MMC_BCM2708 -+static struct clk sdhost_clk = { -+#ifdef CONFIG_ARCH_BCM2708_CHIPIT -+ .rate = 4000000, /* 4MHz */ -+#else -+ .rate = 250000000, /* 250MHz */ -+#endif -+}; -+#endif ++ ret = clk_register_clkdev(clk, NULL, name); ++ if (ret) ++ pr_err("%s alias not registered\n", name); ++} + -+static struct clk_lookup lookups[] = { -+ { /* UART0 */ -+ .dev_id = "dev:f1", -+ .clk = &ref24_clk, -+ }, -+ { /* USB */ -+ .dev_id = "bcm2708_usb", -+ .clk = &osc_clk, -+ } -+}; ++void __init bcm2708_init_clocks(void) ++{ ++ struct clk *clk; ++ ++ clk = bcm2708_clk_register("uart0_clk", uart_clock); ++ bcm2708_register_clkdev(clk, "dev:f1"); ++ ++ clk = bcm2708_clk_register("sdhost_clk", 250000000); ++ bcm2708_register_clkdev(clk, "mmc-bcm2835.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_spi.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); ++ bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); ++} + +#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } +#define UART0_DMA { 15, 14 } @@ -710,21 +893,6 @@ index 0000000..9b4e709 + &uart0_device, +}; + -+static struct resource bcm2708_dmaman_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_dmaman_device = { -+ .name = BCM_DMAMAN_DRIVER_NAME, -+ .id = 0, /* first bcm2708_dma */ -+ .resource = bcm2708_dmaman_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), -+}; -+ +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { @@ -738,38 +906,17 @@ index 0000000..9b4e709 + }, +}; + -+static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -+ { -+ .mapbase = UART1_BASE + 0x40, -+ .irq = IRQ_AUX, -+ .uartclk = 125000000, -+ .regshift = 2, -+ .iotype = UPIO_MEM, -+ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_8250, -+ }, -+ {}, -+}; -+ -+static struct platform_device bcm2708_uart1_device = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = bcm2708_uart1_platform_data, -+ }, -+}; -+ +static struct resource bcm2708_usb_resources[] = { + [0] = { -+ .start = USB_BASE, -+ .end = USB_BASE + SZ_128K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ .start = USB_BASE, ++ .end = USB_BASE + SZ_128K - 1, ++ .flags = IORESOURCE_MEM, ++ }, + [1] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, -+ .flags = IORESOURCE_IRQ, -+ }, ++ .start = IRQ_USB, ++ .end = IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); @@ -786,17 +933,21 @@ index 0000000..9b4e709 +}; + +static struct resource bcm2708_vcio_resources[] = { -+ [0] = { /* mailbox/semaphore/doorbell access */ -+ .start = MCORE_BASE, -+ .end = MCORE_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ { ++ .start = ARMCTRL_0_MAIL0_BASE, ++ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_MAILBOX, ++ .end = IRQ_ARM_MAILBOX, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { -+ .name = BCM_VCIO_DRIVER_NAME, ++ .name = "bcm2708_vcio", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), @@ -806,53 +957,6 @@ index 0000000..9b4e709 + }, +}; + -+static struct resource bcm2708_systemtimer_resources[] = { -+ [0] = { /* system timer access */ -+ .start = ST_BASE, -+ .end = ST_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IRQ_TIMER3, -+ .end = IRQ_TIMER3, -+ .flags = IORESOURCE_IRQ, -+ } -+ -+}; -+ -+static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_systemtimer_device = { -+ .name = "bcm2708_systemtimer", -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_systemtimer_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -+ .dev = { -+ .dma_mask = &systemtimer_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ -+static struct resource bcm2708_powerman_resources[] = { -+ [0] = { -+ .start = PM_BASE, -+ .end = PM_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+struct platform_device bcm2708_powerman_device = { -+ .name = "bcm2708_powerman", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -+ .resource = bcm2708_powerman_resources, -+ .dev = { -+ .dma_mask = &powerman_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+ +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; @@ -865,6 +969,16 @@ index 0000000..9b4e709 + return ret; +} + ++/* ++ * Use these macros for platform and i2c devices that are present in the ++ * Device Tree. This way the devices are only added on non-DT systems. ++ */ ++#define bcm_register_device_dt(pdev) \ ++ if (!use_dt) bcm_register_device(pdev) ++ ++#define i2c_register_board_info_dt(busnum, info, n) \ ++ if (!use_dt) i2c_register_board_info(busnum, info, n) ++ +int calc_rsts(int partition) +{ + return PM_PASSWORD | @@ -930,6 +1044,35 @@ index 0000000..9b4e709 + } +} + ++static void __init bcm2708_init_uart1(void) ++{ ++ struct device_node *np; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); ++ if (of_device_is_available(np)) { ++ pr_info("bcm2708: Mini UART enabled\n"); ++ writel(1, __io_address(UART1_BASE + 0x4)); ++ } ++} ++ ++#ifdef CONFIG_OF ++static void __init bcm2708_dt_init(void) ++{ ++ int ret; ++ ++ of_clk_init(NULL); ++ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); ++ if (ret) { ++ pr_err("of_platform_populate failed: %d\n", ret); ++ /* Proceed as if CONFIG_OF was not defined */ ++ } else { ++ use_dt = 1; ++ } ++} ++#else ++static void __init bcm2708_dt_init(void) { } ++#endif /* CONFIG_OF */ ++ +void __init bcm2708_init(void) +{ + int i; @@ -940,25 +1083,24 @@ index 0000000..9b4e709 + printk("bcm2708.uart_clock = %d\n", uart_clock); + pm_power_off = bcm2708_power_off; + -+ if (uart_clock) -+ lookups[0].clk->rate = uart_clock; ++ bcm2708_init_clocks(); ++ bcm2708_dt_init(); + -+ for (i = 0; i < ARRAY_SIZE(lookups); i++) -+ clkdev_add(&lookups[i]); -+ -+ bcm_register_device(&bcm2708_dmaman_device); + bcm_register_device(&bcm2708_vcio_device); -+ bcm_register_device(&bcm2708_systemtimer_device); -+ bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device(&bcm2708_uart1_device); -+ bcm_register_device(&bcm2708_powerman_device); ++#ifdef CONFIG_BCM2708_GPIO ++ bcm_register_device_dt(&bcm2708_gpio_device); ++#endif ++ bcm_register_device_dt(&bcm2708_fb_device); ++ bcm_register_device_dt(&bcm2708_usb_device); + + bcm2708_init_led(); ++ bcm2708_init_uart1(); + -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); ++ if (!use_dt) { ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } + } + system_rev = boardrev; + system_serial_low = serial; @@ -1041,10 +1183,6 @@ index 0000000..9b4e709 + bcm2708_clocksource_init(); + + /* -+ * Initialise to a known state (all timers off) -+ */ -+ writel(0, __io_address(ARM_T_CONTROL)); -+ /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER3, &bcm2708_timer_irq); @@ -1091,9 +1229,9 @@ index 0000000..9b4e709 + +static void __init bcm2708_init_led(void) +{ -+ bcm2708_leds[0].gpio = disk_led_gpio; -+ bcm2708_leds[0].active_low = disk_led_active_low; -+ platform_device_register(&bcm2708_led_device); ++ bcm2708_leds[0].gpio = disk_led_gpio; ++ bcm2708_leds[0].active_low = disk_led_active_low; ++ bcm_register_device_dt(&bcm2708_led_device); +} +#else +static inline void bcm2708_init_led(void) @@ -1118,6 +1256,11 @@ index 0000000..9b4e709 +#endif +} + ++static const char * const bcm2708_compat[] = { ++ "brcm,bcm2708", ++ NULL ++}; ++ +MACHINE_START(BCM2708, "BCM2708") + /* Maintainer: Broadcom Europe Ltd. */ + .map_io = bcm2708_map_io, @@ -1127,6 +1270,7 @@ index 0000000..9b4e709 + .init_early = bcm2708_init_early, + .reserve = board_reserve, + .restart = bcm2708_restart, ++ .dt_compat = bcm2708_compat, +MACHINE_END + +module_param(boardrev, uint, 0644); @@ -1190,508 +1334,6 @@ index 0000000..e339a93 +} + +#endif -diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c -new file mode 100644 -index 0000000..4fc556e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/clock.c -@@ -0,0 +1,61 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clock.h" -+ -+int clk_enable(struct clk *clk) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(clk_enable); -+ -+void clk_disable(struct clk *clk) -+{ -+} -+EXPORT_SYMBOL(clk_disable); -+ -+unsigned long clk_get_rate(struct clk *clk) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_get_rate); -+ -+long clk_round_rate(struct clk *clk, unsigned long rate) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_round_rate); -+ -+int clk_set_rate(struct clk *clk, unsigned long rate) -+{ -+ return -EIO; -+} -+EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h -new file mode 100644 -index 0000000..5f9d725 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/clock.h -@@ -0,0 +1,24 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+struct module; -+ -+struct clk { -+ unsigned long rate; -+}; -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -new file mode 100644 -index 0000000..51d147a ---- /dev/null -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -0,0 +1,399 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/dma.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/*****************************************************************************\ -+ * * -+ * Configuration * -+ * * -+\*****************************************************************************/ -+ -+#define CACHE_LINE_MASK 31 -+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -+ -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -+ -+ -+/*****************************************************************************\ -+ * * -+ * DMA Auxilliary Functions * -+ * * -+\*****************************************************************************/ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+ -+extern int -+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void -+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+ -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int -+bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Device Methods * -+ * * -+\*****************************************************************************/ -+ -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+}; -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (chans) { -+ int chan = 0; -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ return chan; -+ } else -+ return -ENOMEM; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ else if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ else { -+ dmaman->chan_available |= (1 << chan); -+ return 0; -+ } -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA IRQs * -+ * * -+\*****************************************************************************/ -+ -+static unsigned char bcm_dma_irqs[] = { -+ IRQ_DMA0, -+ IRQ_DMA1, -+ IRQ_DMA2, -+ IRQ_DMA3, -+ IRQ_DMA4, -+ IRQ_DMA5, -+ IRQ_DMA6, -+ IRQ_DMA7, -+ IRQ_DMA8, -+ IRQ_DMA9, -+ IRQ_DMA10, -+ IRQ_DMA11, -+ IRQ_DMA12 -+}; -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Monitor * -+ * * -+\*****************************************************************************/ -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ if (!dmaman_dev) -+ return -ENODEV; -+ else { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (rc >= 0) { -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -+ rc); -+ *out_dma_irq = bcm_dma_irqs[rc]; -+ } -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ if (dmaman_dev) { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int dev_dmaman_register(const char *dev_name, struct device *dev) -+{ -+ int rc = dmaman_dev ? -EINVAL : 0; -+ dmaman_dev = dev; -+ return rc; -+} -+ -+static void dev_dmaman_deregister(const char *dev_name, struct device *dev) -+{ -+ dmaman_dev = NULL; -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA Device * -+ * * -+\*****************************************************************************/ -+ -+static int dmachans = -1; /* module parameter */ -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_dmaman *dmaman; -+ struct resource *dma_res = NULL; -+ void __iomem *dma_base = NULL; -+ int have_dma_region = 0; -+ -+ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -+ if (NULL == dmaman) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "DMA management memory\n"); -+ ret = -ENOMEM; -+ } else { -+ -+ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (dma_res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ } else if (!request_mem_region(dma_res->start, -+ resource_size(dma_res), -+ DRIVER_NAME)) { -+ dev_err(&pdev->dev, "cannot obtain DMA region\n"); -+ ret = -EBUSY; -+ } else { -+ have_dma_region = 1; -+ dma_base = ioremap(dma_res->start, -+ resource_size(dma_res)); -+ if (!dma_base) { -+ dev_err(&pdev->dev, "cannot map DMA region\n"); -+ ret = -ENOMEM; -+ } else { -+ /* use module parameter if one was provided */ -+ if (dmachans > 0) -+ vc_dmaman_init(dmaman, dma_base, -+ dmachans); -+ else -+ vc_dmaman_init(dmaman, dma_base, -+ DEFAULT_DMACHAN_BITMAP); -+ -+ platform_set_drvdata(pdev, dmaman); -+ dev_dmaman_register(DRIVER_NAME, &pdev->dev); -+ -+ printk(KERN_INFO DRIVER_NAME ": DMA manager " -+ "at %p\n", dma_base); -+ } -+ } -+ } -+ if (ret != 0) { -+ if (dma_base) -+ iounmap(dma_base); -+ if (dma_res && have_dma_region) -+ release_mem_region(dma_res->start, -+ resource_size(dma_res)); -+ if (dmaman) -+ kfree(dmaman); -+ } -+ return ret; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -+ kfree(dmaman); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_dmaman_driver = { -+ .probe = bcm_dmaman_probe, -+ .remove = bcm_dmaman_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+/*****************************************************************************\ -+ * * -+ * Driver init/exit * -+ * * -+\*****************************************************************************/ -+ -+static int __init bcm_dmaman_drv_init(void) -+{ -+ int ret; -+ -+ ret = platform_driver_register(&bcm_dmaman_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_dmaman_drv_exit(void) -+{ -+ platform_driver_unregister(&bcm_dmaman_driver); -+} -+ -+module_init(bcm_dmaman_drv_init); -+module_exit(bcm_dmaman_drv_exit); -+ -+module_param(dmachans, int, 0644); -+ -+MODULE_AUTHOR("Gray Girling "); -+MODULE_DESCRIPTION("DMA channel manager driver"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); diff --git a/arch/arm/mach-bcm2708/include/mach/arm_control.h b/arch/arm/mach-bcm2708/include/mach/arm_control.h new file mode 100644 index 0000000..a82bb92b @@ -2117,74 +1759,6 @@ index 0000000..a82bb92b +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h -new file mode 100644 -index 0000000..d3bf245 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/arm_power.h -@@ -0,0 +1,62 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _ARM_POWER_H -+#define _ARM_POWER_H -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/clkdev.h b/arch/arm/mach-bcm2708/include/mach/clkdev.h new file mode 100644 index 0000000..04b37a8 @@ -2226,100 +1800,6 @@ index 0000000..b24304a + .endm + +#include -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -new file mode 100644 -index 0000000..f2568d4 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -0,0 +1,88 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef _MACH_BCM2708_DMA_H -+#define _MACH_BCM2708_DMA_H -+ -+#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE (1 << 0) -+#define BCM2708_DMA_INT (1 << 2) -+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR (1 << 8) -+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN (1 << 0) -+#define BCM2708_DMA_TDMODE (1 << 1) -+#define BCM2708_DMA_WAIT_RESP (1 << 3) -+#define BCM2708_DMA_D_INC (1 << 4) -+#define BCM2708_DMA_D_WIDTH (1 << 5) -+#define BCM2708_DMA_D_DREQ (1 << 6) -+#define BCM2708_DMA_S_INC (1 << 8) -+#define BCM2708_DMA_S_WIDTH (1 << 9) -+#define BCM2708_DMA_S_DREQ (1 << 10) -+ -+#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block); -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_FAST (1< -+#include -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h new file mode 100644 index 0000000..2d0b821 @@ -3200,218 +2648,6 @@ index 0000000..d634813 + * nothing to do + */ +#define arch_decomp_wdog() -diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -new file mode 100644 -index 0000000..4a4a338 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#if !defined( VC_MEM_H ) -+#define VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -new file mode 100644 -index 0000000..8e11d67e ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -0,0 +1,165 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vcio.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef _MACH_BCM2708_VCIO_H -+#define _MACH_BCM2708_VCIO_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); -+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); -+extern int /*rc*/ bcm_mailbox_property(void *data, int size); -+ -+#include -+ -+/* -+ * The major device number. We can't rely on dynamic -+ * registration any more, because ioctls need to know -+ * it. -+ */ -+#define MAJOR_NUM 100 -+ -+/* -+ * Set the message of the device driver -+ */ -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+/* -+ * _IOWR means that we're creating an ioctl command -+ * number for passing information from a user process -+ * to the kernel module and from the kernel module to user process -+ * -+ * The first arguments, MAJOR_NUM, is the major device -+ * number we're using. -+ * -+ * The second argument is the number of the command -+ * (there could be several with different meanings). -+ * -+ * The third argument is the type we want to get from -+ * the process to the kernel. -+ */ -+ -+/* -+ * The name of the device file -+ */ -+#define DEVICE_FILE_NAME "vcio" -+ -+#endif diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h new file mode 100644 index 0000000..502c617 @@ -3438,1370 +2674,12 @@ index 0000000..502c617 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xe8000000) -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -new file mode 100644 -index 0000000..2696be9 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/power.c -@@ -0,0 +1,197 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+ -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+arch_initcall(bcm_power_init); /* Initialize early */ -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -new file mode 100644 -index 0000000..2982af7 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -0,0 +1,431 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_ARCH_KONA -+#include -+#elif CONFIG_ARCH_BCM2708 -+#else -+#include -+#endif -+ -+#include "mach/vc_mem.h" -+#include -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -new file mode 100644 -index 0000000..5e43e85 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -0,0 +1,474 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -+#define SUPPORT_SYSRQ -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+ -+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* offsets from a mail box base address */ -+#define MAIL_WRT 0x00 /* write - and next 4 words */ -+#define MAIL_RD 0x00 /* read - and next 4 words */ -+#define MAIL_POL 0x10 /* read without popping the fifo */ -+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL_STA 0x18 /* status */ -+#define MAIL_CNF 0x1C /* configuration */ -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+struct vc_mailbox { -+ struct device *dev; /* parent device */ -+ void __iomem *status; -+ void __iomem *config; -+ void __iomem *read; -+ void __iomem *write; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -+ uint32_t addr_mbox) -+{ -+ int i; -+ -+ mbox_out->dev = dev; -+ mbox_out->status = __io_address(addr_mbox + MAIL_STA); -+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -+ mbox_out->read = __io_address(addr_mbox + MAIL_RD); -+ /* Write to the other mailbox */ -+ mbox_out->write = -+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -+ MAIL_WRT); -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ rc = 0; -+ } -+ return rc; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ rc = 0; -+ } -+ return rc; -+} -+ -+static irqreturn_t mbox_irq(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ int status = readl(mbox->status); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->read); -+ int chan = MBOX_CHAN(msg); -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ /* Overflow */ -+ printk(KERN_ERR DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ printk(KERN_ERR DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->status); -+ } -+ return ret; -+} -+ -+static struct irqaction mbox_irqaction = { -+ .name = "ARM Mailbox IRQ", -+ .flags = IRQF_DISABLED | IRQF_IRQPOLL, -+ .handler = mbox_irq, -+}; -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox Methods -+ * -------------------------------------------------------------------- */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_write(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_read(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static void dev_mbox_register(const char *dev_name, struct device *dev) -+{ -+ mbox_dev = dev; -+} -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)src < TASK_SIZE) -+ { -+ return copy_from_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)dst < TASK_SIZE) -+ { -+ return copy_to_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) { -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ } -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* ---------------------------------------------------------------------- -+ * Platform Device for Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static int Device_Open = 0; -+ -+/* -+ * This is called whenever a process attempts to open the device file -+ */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* -+ * We don't want to talk to two processes at the same time -+ */ -+ if (Device_Open) -+ return -EBUSY; -+ -+ Device_Open++; -+ /* -+ * Initialize the message -+ */ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * We're now ready for our next caller -+ */ -+ Device_Open--; -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -+ unsigned int ioctl_num, /* number and param for ioctl */ -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ /* -+ * Switch according to the ioctl called -+ */ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ break; -+ default: -+ printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_mailbox *mailbox; -+ -+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -+ if (NULL == mailbox) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ ret = -ENOMEM; -+ } else { -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ kfree(mailbox); -+ } else { -+ /* should be based on the registers from res really */ -+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -+ -+ platform_set_drvdata(pdev, mailbox); -+ dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ -+ mbox_irqaction.dev_id = mailbox; -+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); -+ } -+ } -+ -+ if (ret == 0) { -+ /* -+ * Register the character device -+ */ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ -+ /* -+ * Negative values signify an error -+ */ -+ if (ret < 0) { -+ printk(KERN_ERR DRIVER_NAME -+ "Failed registering the character device %d\n", ret); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ kfree(mailbox); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ -+ ret = platform_driver_register(&bcm_mbox_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm-mbox"); -diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 9b4f29e5..0c5d4ac 100644 ---- a/arch/arm/mm/Kconfig -+++ b/arch/arm/mm/Kconfig -@@ -358,7 +358,7 @@ config CPU_PJ4B - - # ARMv6 - config CPU_V6 -- bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX) -+ bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708) - select CPU_32v6 - select CPU_ABRT_EV6 - select CPU_CACHE_V6 -diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S -index d0390f4..a042de8 100644 ---- a/arch/arm/mm/proc-v6.S -+++ b/arch/arm/mm/proc-v6.S -@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) - * - * IRQs are already disabled. - */ -+ -+/* See jira SW-5991 for details of this workaround */ - ENTRY(cpu_v6_do_idle) -- mov r1, #0 -- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode -- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt -+ .align 5 -+ mov r1, #2 -+1: subs r1, #1 -+ nop -+ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode -+ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt -+ nop -+ nop -+ nop -+ bne 1b - ret lr - - ENTRY(cpu_v6_dcache_clean_area) -diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index a10297d..c9ddd87 100644 ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -522,6 +522,7 @@ torbreck MACH_TORBRECK TORBRECK 3090 - prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 - paz00 MACH_PAZ00 PAZ00 3128 - acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 -+bcm2708 MACH_BCM2708 BCM2708 3138 - ag5evm MACH_AG5EVM AG5EVM 3189 - ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 - wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 8d94c19..16ca535 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -84,7 +84,7 @@ struct vendor_data { - - static unsigned int get_fifosize_arm(struct amba_device *dev) - { -- return amba_rev(dev) < 3 ? 16 : 32; -+ return 16; //TODO: fix: amba_rev(dev) < 3 ? 16 : 32; - } - - static struct vendor_data vendor_arm = { -diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 0c8cbe5..c3b84a2 100644 ---- a/include/linux/mmc/host.h -+++ b/include/linux/mmc/host.h -@@ -291,6 +291,7 @@ struct mmc_host { - MMC_CAP2_HS400_1_2V) - #define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) - #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) -+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ - - mmc_pm_flag_t pm_caps; /* supported pm features */ - - -From 6763b931593e5ce8e1b5e45de482527d61390f56 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 7 May 2013 14:32:27 +0100 -Subject: [PATCH 002/216] Add 2709 platform for Raspberry Pi 2 - ---- - arch/arm/Kconfig | 21 + - arch/arm/Makefile | 1 + - arch/arm/kernel/head.S | 8 + - arch/arm/mach-bcm2709/Kconfig | 49 + - arch/arm/mach-bcm2709/Makefile | 7 + - arch/arm/mach-bcm2709/Makefile.boot | 3 + - arch/arm/mach-bcm2709/armctrl.c | 361 +++++++ - arch/arm/mach-bcm2709/armctrl.h | 27 + - arch/arm/mach-bcm2709/bcm2708_gpio.c | 426 ++++++++ - arch/arm/mach-bcm2709/bcm2709.c | 1263 ++++++++++++++++++++++ - arch/arm/mach-bcm2709/bcm2709.h | 49 + - arch/arm/mach-bcm2709/clock.c | 61 ++ - arch/arm/mach-bcm2709/clock.h | 24 + - arch/arm/mach-bcm2709/delay.S | 21 + - arch/arm/mach-bcm2709/dma.c | 409 +++++++ - arch/arm/mach-bcm2709/include/mach/arm_control.h | 493 +++++++++ - arch/arm/mach-bcm2709/include/mach/arm_power.h | 62 ++ - arch/arm/mach-bcm2709/include/mach/barriers.h | 3 + - arch/arm/mach-bcm2709/include/mach/clkdev.h | 7 + - arch/arm/mach-bcm2709/include/mach/debug-macro.S | 22 + - arch/arm/mach-bcm2709/include/mach/dma.h | 94 ++ - arch/arm/mach-bcm2709/include/mach/entry-macro.S | 123 +++ - arch/arm/mach-bcm2709/include/mach/frc.h | 38 + - arch/arm/mach-bcm2709/include/mach/gpio.h | 17 + - arch/arm/mach-bcm2709/include/mach/hardware.h | 28 + - arch/arm/mach-bcm2709/include/mach/io.h | 27 + - arch/arm/mach-bcm2709/include/mach/irqs.h | 225 ++++ - arch/arm/mach-bcm2709/include/mach/memory.h | 57 + - arch/arm/mach-bcm2709/include/mach/platform.h | 225 ++++ - arch/arm/mach-bcm2709/include/mach/power.h | 26 + - arch/arm/mach-bcm2709/include/mach/system.h | 38 + - arch/arm/mach-bcm2709/include/mach/timex.h | 23 + - arch/arm/mach-bcm2709/include/mach/uncompress.h | 84 ++ - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 + - arch/arm/mach-bcm2709/include/mach/vc_support.h | 69 ++ - arch/arm/mach-bcm2709/include/mach/vcio.h | 165 +++ - arch/arm/mach-bcm2709/include/mach/vmalloc.h | 20 + - arch/arm/mach-bcm2709/power.c | 195 ++++ - arch/arm/mach-bcm2709/vc_mem.c | 431 ++++++++ - arch/arm/mach-bcm2709/vc_support.c | 318 ++++++ - arch/arm/mach-bcm2709/vcio.c | 474 ++++++++ - arch/arm/mm/proc-v7.S | 1 + - arch/arm/tools/mach-types | 1 + - drivers/clocksource/arm_arch_timer.c | 36 + - 44 files changed, 6067 insertions(+) - create mode 100644 arch/arm/mach-bcm2709/Kconfig - create mode 100644 arch/arm/mach-bcm2709/Makefile - create mode 100644 arch/arm/mach-bcm2709/Makefile.boot - create mode 100644 arch/arm/mach-bcm2709/armctrl.c - create mode 100644 arch/arm/mach-bcm2709/armctrl.h - create mode 100644 arch/arm/mach-bcm2709/bcm2708_gpio.c - create mode 100644 arch/arm/mach-bcm2709/bcm2709.c - create mode 100644 arch/arm/mach-bcm2709/bcm2709.h - create mode 100644 arch/arm/mach-bcm2709/clock.c - create mode 100644 arch/arm/mach-bcm2709/clock.h - create mode 100644 arch/arm/mach-bcm2709/delay.S - create mode 100644 arch/arm/mach-bcm2709/dma.c - create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_control.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/arm_power.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/barriers.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/clkdev.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/debug-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/dma.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/entry-macro.S - create mode 100644 arch/arm/mach-bcm2709/include/mach/frc.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/gpio.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/hardware.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/io.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/irqs.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/memory.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/platform.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/power.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/system.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/timex.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/uncompress.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - create mode 100755 arch/arm/mach-bcm2709/include/mach/vc_support.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vcio.h - create mode 100644 arch/arm/mach-bcm2709/include/mach/vmalloc.h - create mode 100644 arch/arm/mach-bcm2709/power.c - create mode 100644 arch/arm/mach-bcm2709/vc_mem.c - create mode 100755 arch/arm/mach-bcm2709/vc_support.c - create mode 100644 arch/arm/mach-bcm2709/vcio.c - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 6876ae8..4018fea 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -793,6 +793,26 @@ config ARCH_OMAP1 - help - Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx) - -+config ARCH_BCM2709 -+ bool "Broadcom BCM2709 family" -+ select ARCH_HAS_BARRIERS if SMP -+ select CPU_V7 -+ select HAVE_SMP -+ select ARM_AMBA -+ select MIGHT_HAVE_CACHE_L2X0 -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_MEMORY_H -+ select NEED_MACH_IO_H -+ select COMMON_CLK -+ select ARCH_HAS_CPUFREQ -+ select GENERIC_CLOCKEVENTS -+ select MACH_BCM2709 -+ select VC4 -+ select FIQ -+# select ZONE_DMA -+ help -+ This enables support for Broadcom BCM2709 boards. -+ - endchoice - - menu "Multiple platform selection" -@@ -984,6 +1004,7 @@ source "arch/arm/mach-vt8500/Kconfig" - - source "arch/arm/mach-w90x900/Kconfig" - source "arch/arm/mach-bcm2708/Kconfig" -+source "arch/arm/mach-bcm2709/Kconfig" - - source "arch/arm/mach-zynq/Kconfig" - -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 27c0f92..21ba7f3 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -147,6 +147,7 @@ machine-$(CONFIG_ARCH_AT91) += at91 - machine-$(CONFIG_ARCH_AXXIA) += axxia - machine-$(CONFIG_ARCH_BCM) += bcm - machine-$(CONFIG_ARCH_BCM2708) += bcm2708 -+machine-$(CONFIG_ARCH_BCM2709) += bcm2709 - machine-$(CONFIG_ARCH_BERLIN) += berlin - machine-$(CONFIG_ARCH_CLPS711X) += clps711x - machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx -diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S -index 0196327..e4d6030 100644 ---- a/arch/arm/kernel/head.S -+++ b/arch/arm/kernel/head.S -@@ -680,6 +680,14 @@ ARM_BE8(rev16 ip, ip) - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - ret lr -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - #endif - ENDPROC(__fixup_a_pv_table) - diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig new file mode 100644 -index 0000000..4fb6e1b +index 0000000..d61ade0 --- /dev/null +++ b/arch/arm/mach-bcm2709/Kconfig -@@ -0,0 +1,49 @@ +@@ -0,0 +1,42 @@ +menu "Broadcom BCM2709 Implementations" + depends on ARCH_BCM2709 + @@ -4829,13 +2707,6 @@ index 0000000..4fb6e1b + help + Include support for the Broadcom(R) BCM2709 gpio. + -+config BCM2708_VCMEM -+ bool "Videocore Memory" -+ depends on MACH_BCM2709 -+ default y -+ help -+ Helper for videocore memory access and total size allocation. -+ +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" + depends on MACH_BCM2709 @@ -4853,17 +2724,16 @@ index 0000000..4fb6e1b +endmenu diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile new file mode 100644 -index 0000000..2a803bb +index 0000000..1ae8b80 --- /dev/null +++ b/arch/arm/mach-bcm2709/Makefile -@@ -0,0 +1,7 @@ +@@ -0,0 +1,6 @@ +# +# Makefile for the linux kernel. +# + -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o dma.o ++obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o diff --git a/arch/arm/mach-bcm2709/Makefile.boot b/arch/arm/mach-bcm2709/Makefile.boot new file mode 100644 index 0000000..67039c3 @@ -4875,7 +2745,7 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c new file mode 100644 -index 0000000..2815b64 +index 0000000..2fcfab9 --- /dev/null +++ b/arch/arm/mach-bcm2709/armctrl.c @@ -0,0 +1,361 @@ @@ -5230,7 +3100,7 @@ index 0000000..2815b64 + set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); + } else { + irq_set_chip_and_handler(irq, &armctrl_chip, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + irq_set_chip_data(irq, (void *)data); + } @@ -5275,7 +3145,7 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2709/bcm2708_gpio.c b/arch/arm/mach-bcm2709/bcm2708_gpio.c new file mode 100644 -index 0000000..c1e9254 +index 0000000..e33265d --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2708_gpio.c @@ -0,0 +1,426 @@ @@ -5587,7 +3457,7 @@ index 0000000..c1e9254 + +static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, +}; + @@ -5707,10 +3577,10 @@ index 0000000..c1e9254 +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c new file mode 100644 -index 0000000..f8679bb +index 0000000..19d0601 --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -0,0 +1,1263 @@ +@@ -0,0 +1,801 @@ +/* + * linux/arch/arm/mach-bcm2709/bcm2709.c + * @@ -5747,9 +3617,7 @@ index 0000000..f8679bb +#include +#include +#include -+#include +#include -+#include + +#include +#include @@ -5768,8 +3636,6 @@ index 0000000..f8679bb +#include + +#include -+#include -+#include +#include + +#include @@ -5795,19 +3661,12 @@ index 0000000..f8679bb + */ +#define DMA_MASK_BITS_COMMON 32 + -+// use GPIO 4 for the one-wire GPIO pin, if enabled -+#define W1_GPIO 4 -+// ensure one-wire GPIO pullup is disabled by default -+#define W1_PULLUP -1 -+ +/* command line parameters */ +static unsigned boardrev, serial; +static unsigned uart_clock = UART0_CLOCK; +static unsigned disk_led_gpio = 16; +static unsigned disk_led_active_low = 1; +static unsigned reboot_part = 0; -+static unsigned w1_gpio_pin = W1_GPIO; -+static unsigned w1_gpio_pullup = W1_PULLUP; + +static unsigned use_dt = 0; + @@ -5953,6 +3812,7 @@ index 0000000..f8679bb + bcm2709_register_clkdev(clk, "dev:f1"); + + clk = bcm2709_clk_register("sdhost_clk", 250000000); ++ bcm2709_register_clkdev(clk, "mmc-bcm2835.0"); + bcm2709_register_clkdev(clk, "bcm2708_spi.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.1"); @@ -5967,35 +3827,6 @@ index 0000000..f8679bb + &uart0_device, +}; + -+static struct resource bcm2708_dmaman_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_dmaman_device = { -+ .name = BCM_DMAMAN_DRIVER_NAME, -+ .id = 0, /* first bcm2708_dma */ -+ .resource = bcm2708_dmaman_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), -+}; -+ -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+static struct w1_gpio_platform_data w1_gpio_pdata = { -+ .pin = W1_GPIO, -+ .ext_pullup_enable_pin = W1_PULLUP, -+ .is_open_drain = 0, -+}; -+ -+static struct platform_device w1_device = { -+ .name = "w1-gpio", -+ .id = -1, -+ .dev.platform_data = &w1_gpio_pdata, -+}; -+#endif -+ +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { @@ -6009,27 +3840,6 @@ index 0000000..f8679bb + }, +}; + -+static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -+ { -+ .mapbase = UART1_BASE + 0x40, -+ .irq = IRQ_AUX, -+ .uartclk = 125000000, -+ .regshift = 2, -+ .iotype = UPIO_MEM, -+ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_8250, -+ }, -+ {}, -+}; -+ -+static struct platform_device bcm2708_uart1_device = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = bcm2708_uart1_platform_data, -+ }, -+}; -+ +static struct resource bcm2708_usb_resources[] = { + [0] = { + .start = USB_BASE, @@ -6078,17 +3888,21 @@ index 0000000..f8679bb +}; + +static struct resource bcm2708_vcio_resources[] = { -+ [0] = { /* mailbox/semaphore/doorbell access */ -+ .start = MCORE_BASE, -+ .end = MCORE_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, ++ { ++ .start = ARMCTRL_0_MAIL0_BASE, ++ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_MAILBOX, ++ .end = IRQ_ARM_MAILBOX, ++ .flags = IORESOURCE_IRQ, ++ }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { -+ .name = BCM_VCIO_DRIVER_NAME, ++ .name = "bcm2708_vcio", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), @@ -6098,360 +3912,6 @@ index 0000000..f8679bb + }, +}; + -+#ifdef CONFIG_BCM2708_GPIO -+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" -+ -+static struct resource bcm2708_gpio_resources[] = { -+ [0] = { /* general purpose I/O */ -+ .start = GPIO_BASE, -+ .end = GPIO_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_gpio_device = { -+ .name = BCM_GPIO_DRIVER_NAME, -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_gpio_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), -+ .dev = { -+ .dma_mask = &gpio_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+#endif -+ -+#ifdef SYSTEM_TIMER -+static struct resource bcm2708_systemtimer_resources[] = { -+ [0] = { /* system timer access */ -+ .start = ST_BASE, -+ .end = ST_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IRQ_TIMER3, -+ .end = IRQ_TIMER3, -+ .flags = IORESOURCE_IRQ, -+ } -+ -+}; -+ -+static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_systemtimer_device = { -+ .name = "bcm2708_systemtimer", -+ .id = -1, /* only one VideoCore I/O area */ -+ .resource = bcm2708_systemtimer_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -+ .dev = { -+ .dma_mask = &systemtimer_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+#endif -+ -+#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ -+static struct resource bcm2835_emmc_resources[] = { -+ [0] = { -+ .start = EMMC_BASE, -+ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ -+ /* the memory map actually makes SZ_4K available */ -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_ARASANSDIO, -+ .end = IRQ_ARASANSDIO, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 bcm2835_emmc_dmamask = 0xffffffffUL; -+ -+struct platform_device bcm2835_emmc_device = { -+ .name = "mmc-bcm2835", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), -+ .resource = bcm2835_emmc_resources, -+ .dev = { -+ .dma_mask = &bcm2835_emmc_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+#endif /* CONFIG_MMC_BCM2835 */ -+ -+static struct resource bcm2708_powerman_resources[] = { -+ [0] = { -+ .start = PM_BASE, -+ .end = PM_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+struct platform_device bcm2708_powerman_device = { -+ .name = "bcm2708_powerman", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -+ .resource = bcm2708_powerman_resources, -+ .dev = { -+ .dma_mask = &powerman_dmamask, -+ .coherent_dma_mask = 0xffffffffUL}, -+}; -+ -+ -+static struct platform_device bcm2708_alsa_devices[] = { -+ [0] = { -+ .name = "bcm2835_AUD0", -+ .id = 0, /* first audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [1] = { -+ .name = "bcm2835_AUD1", -+ .id = 1, /* second audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [2] = { -+ .name = "bcm2835_AUD2", -+ .id = 2, /* third audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [3] = { -+ .name = "bcm2835_AUD3", -+ .id = 3, /* forth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [4] = { -+ .name = "bcm2835_AUD4", -+ .id = 4, /* fifth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [5] = { -+ .name = "bcm2835_AUD5", -+ .id = 5, /* sixth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [6] = { -+ .name = "bcm2835_AUD6", -+ .id = 6, /* seventh audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+ [7] = { -+ .name = "bcm2835_AUD7", -+ .id = 7, /* eighth audio device */ -+ .resource = 0, -+ .num_resources = 0, -+ }, -+}; -+ -+static struct resource bcm2708_spi_resources[] = { -+ { -+ .start = SPI0_BASE, -+ .end = SPI0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_SPI, -+ .end = IRQ_SPI, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+ -+static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+static struct platform_device bcm2708_spi_device = { -+ .name = "bcm2708_spi", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_spi_resources), -+ .resource = bcm2708_spi_resources, -+ .dev = { -+ .dma_mask = &bcm2708_spi_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, -+}; -+ -+#ifdef CONFIG_BCM2708_SPIDEV -+static struct spi_board_info bcm2708_spi_devices[] = { -+#ifdef CONFIG_SPI_SPIDEV -+ { -+ .modalias = "spidev", -+ .max_speed_hz = 500000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = SPI_MODE_0, -+ }, { -+ .modalias = "spidev", -+ .max_speed_hz = 500000, -+ .bus_num = 0, -+ .chip_select = 1, -+ .mode = SPI_MODE_0, -+ } -+#endif -+}; -+#endif -+ -+static struct resource bcm2708_bsc0_resources[] = { -+ { -+ .start = BSC0_BASE, -+ .end = BSC0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc0_device = { -+ .name = "bcm2708_i2c", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), -+ .resource = bcm2708_bsc0_resources, -+}; -+ -+ -+static struct resource bcm2708_bsc1_resources[] = { -+ { -+ .start = BSC1_BASE, -+ .end = BSC1_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc1_device = { -+ .name = "bcm2708_i2c", -+ .id = 1, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), -+ .resource = bcm2708_bsc1_resources, -+}; -+ -+static struct platform_device bcm2835_hwmon_device = { -+ .name = "bcm2835_hwmon", -+}; -+ -+static struct platform_device bcm2835_thermal_device = { -+ .name = "bcm2835_thermal", -+}; -+ -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+static struct resource bcm2708_i2s_resources[] = { -+ { -+ .start = I2S_BASE, -+ .end = I2S_BASE + 0x20, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = PCM_CLOCK_BASE, -+ .end = PCM_CLOCK_BASE + 0x02, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_i2s_device = { -+ .name = "bcm2708-i2s", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), -+ .resource = bcm2708_i2s_resources, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+static struct platform_device snd_hifiberry_dac_device = { -+ .name = "snd-hifiberry-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm5102a_codec_device = { -+ .name = "pcm5102a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+static struct platform_device snd_rpi_hifiberry_dacplus_device = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4d) -+ }, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+static struct platform_device snd_hifiberry_digi_device = { -+ .name = "snd-hifiberry-digi", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("wm8804", 0x3b) -+ }, -+}; -+ -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+static struct platform_device snd_hifiberry_amp_device = { -+ .name = "snd-hifiberry-amp", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("tas5713", 0x1b) -+ }, -+}; -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+static struct platform_device snd_rpi_dac_device = { -+ .name = "snd-rpi-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm1794a_codec_device = { -+ .name = "pcm1794a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+static struct platform_device snd_rpi_iqaudio_dac_device = { -+ .name = "snd-rpi-iqaudio-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+// Use the actual device name rather than generic driver name -+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4c) -+ }, -+}; -+#endif -+ +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; @@ -6539,6 +3999,17 @@ index 0000000..f8679bb + } +} + ++static void __init bcm2709_init_uart1(void) ++{ ++ struct device_node *np; ++ ++ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); ++ if (of_device_is_available(np)) { ++ pr_info("bcm2709: Mini UART enabled\n"); ++ writel(1, __io_address(UART1_BASE + 0x4)); ++ } ++} ++ +#ifdef CONFIG_OF +static void __init bcm2709_dt_init(void) +{ @@ -6570,85 +4041,24 @@ index 0000000..f8679bb + bcm2709_init_clocks(); + bcm2709_dt_init(); + -+ bcm_register_device(&bcm2708_dmaman_device); + bcm_register_device(&bcm2708_vcio_device); +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +#endif -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+ w1_gpio_pdata.pin = w1_gpio_pin; -+ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -+ bcm_register_device_dt(&w1_device); -+#endif -+#ifdef SYSTEM_TIMER -+ bcm_register_device(&bcm2708_systemtimer_device); -+#endif -+ bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device(&bcm2708_uart1_device); -+ bcm_register_device(&bcm2708_powerman_device); ++ bcm_register_device_dt(&bcm2708_fb_device); ++ bcm_register_device_dt(&bcm2708_usb_device); + -+#ifdef CONFIG_MMC_BCM2835 -+ bcm_register_device(&bcm2835_emmc_device); -+#endif -+ bcm2709_init_led(); -+ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -+ bcm_register_device(&bcm2708_alsa_devices[i]); ++ bcm2708_init_led(); ++ bcm2708_init_uart1(); + -+ bcm_register_device_dt(&bcm2708_spi_device); -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ bcm_register_device(&bcm2835_hwmon_device); -+ bcm_register_device(&bcm2835_thermal_device); -+ -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+ bcm_register_device_dt(&bcm2708_i2s_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_dac_device); -+ bcm_register_device_dt(&snd_pcm5102a_codec_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_digi_device); -+ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_amp_device); -+ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_dac_device); -+ bcm_register_device_dt(&snd_pcm1794a_codec_device); -+#endif -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); -+#endif -+ -+ -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); ++ if (!use_dt) { ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } + } + system_rev = boardrev; + system_serial_low = serial; -+ -+#ifdef CONFIG_BCM2708_SPIDEV -+ if (!use_dt) -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); -+#endif +} + +#ifdef SYSTEM_TIMER @@ -6972,8 +4382,6 @@ index 0000000..f8679bb +module_param(disk_led_gpio, uint, 0644); +module_param(disk_led_active_low, uint, 0644); +module_param(reboot_part, uint, 0644); -+module_param(w1_gpio_pin, uint, 0644); -+module_param(w1_gpio_pullup, uint, 0644); diff --git a/arch/arm/mach-bcm2709/bcm2709.h b/arch/arm/mach-bcm2709/bcm2709.h new file mode 100644 index 0000000..e339a93 @@ -7029,103 +4437,6 @@ index 0000000..e339a93 +} + +#endif -diff --git a/arch/arm/mach-bcm2709/clock.c b/arch/arm/mach-bcm2709/clock.c -new file mode 100644 -index 0000000..4fc556e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/clock.c -@@ -0,0 +1,61 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clock.h" -+ -+int clk_enable(struct clk *clk) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(clk_enable); -+ -+void clk_disable(struct clk *clk) -+{ -+} -+EXPORT_SYMBOL(clk_disable); -+ -+unsigned long clk_get_rate(struct clk *clk) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_get_rate); -+ -+long clk_round_rate(struct clk *clk, unsigned long rate) -+{ -+ return clk->rate; -+} -+EXPORT_SYMBOL(clk_round_rate); -+ -+int clk_set_rate(struct clk *clk, unsigned long rate) -+{ -+ return -EIO; -+} -+EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2709/clock.h b/arch/arm/mach-bcm2709/clock.h -new file mode 100644 -index 0000000..5f9d725 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/clock.h -@@ -0,0 +1,24 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/clock.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+struct module; -+ -+struct clk { -+ unsigned long rate; -+}; diff --git a/arch/arm/mach-bcm2709/delay.S b/arch/arm/mach-bcm2709/delay.S new file mode 100644 index 0000000..06f4780 @@ -7153,421 +4464,6 @@ index 0000000..06f4780 + bhi bcm2708_delay + mov pc, lr +ENDPROC(bcm2708_delay) -diff --git a/arch/arm/mach-bcm2709/dma.c b/arch/arm/mach-bcm2709/dma.c -new file mode 100644 -index 0000000..a5e58d1 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/dma.c -@@ -0,0 +1,409 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/dma.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/*****************************************************************************\ -+ * * -+ * Configuration * -+ * * -+\*****************************************************************************/ -+ -+#define CACHE_LINE_MASK 31 -+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -+ -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -+ -+ -+/*****************************************************************************\ -+ * * -+ * DMA Auxilliary Functions * -+ * * -+\*****************************************************************************/ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+ -+extern int -+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void -+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+ -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int -+bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Device Methods * -+ * * -+\*****************************************************************************/ -+ -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+}; -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (chans) { -+ int chan = 0; -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ return chan; -+ } else -+ return -ENOMEM; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ else if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ else { -+ dmaman->chan_available |= (1 << chan); -+ return 0; -+ } -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA IRQs * -+ * * -+\*****************************************************************************/ -+ -+static unsigned char bcm_dma_irqs[] = { -+ IRQ_DMA0, -+ IRQ_DMA1, -+ IRQ_DMA2, -+ IRQ_DMA3, -+ IRQ_DMA4, -+ IRQ_DMA5, -+ IRQ_DMA6, -+ IRQ_DMA7, -+ IRQ_DMA8, -+ IRQ_DMA9, -+ IRQ_DMA10, -+ IRQ_DMA11, -+ IRQ_DMA12 -+}; -+ -+ -+/***************************************************************************** \ -+ * * -+ * DMA Manager Monitor * -+ * * -+\*****************************************************************************/ -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ if (!dmaman_dev) -+ return -ENODEV; -+ else { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (rc >= 0) { -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -+ rc); -+ *out_dma_irq = bcm_dma_irqs[rc]; -+ } -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ if (dmaman_dev) { -+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -+ int rc; -+ -+ device_lock(dmaman_dev); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ device_unlock(dmaman_dev); -+ -+ return rc; -+ } else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int dev_dmaman_register(const char *dev_name, struct device *dev) -+{ -+ int rc = dmaman_dev ? -EINVAL : 0; -+ dmaman_dev = dev; -+ return rc; -+} -+ -+static void dev_dmaman_deregister(const char *dev_name, struct device *dev) -+{ -+ dmaman_dev = NULL; -+} -+ -+/*****************************************************************************\ -+ * * -+ * DMA Device * -+ * * -+\*****************************************************************************/ -+ -+static int dmachans = -1; /* module parameter */ -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_dmaman *dmaman; -+ struct resource *dma_res = NULL; -+ void __iomem *dma_base = NULL; -+ int have_dma_region = 0; -+ -+ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -+ if (NULL == dmaman) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "DMA management memory\n"); -+ ret = -ENOMEM; -+ } else { -+ -+ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (dma_res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ } else if (!request_mem_region(dma_res->start, -+ resource_size(dma_res), -+ DRIVER_NAME)) { -+ dev_err(&pdev->dev, "cannot obtain DMA region\n"); -+ ret = -EBUSY; -+ } else { -+ have_dma_region = 1; -+ dma_base = ioremap(dma_res->start, -+ resource_size(dma_res)); -+ if (!dma_base) { -+ dev_err(&pdev->dev, "cannot map DMA region\n"); -+ ret = -ENOMEM; -+ } else { -+ /* use module parameter if one was provided */ -+ if (dmachans > 0) -+ vc_dmaman_init(dmaman, dma_base, -+ dmachans); -+ else -+ vc_dmaman_init(dmaman, dma_base, -+ DEFAULT_DMACHAN_BITMAP); -+ -+ platform_set_drvdata(pdev, dmaman); -+ dev_dmaman_register(DRIVER_NAME, &pdev->dev); -+ -+ printk(KERN_INFO DRIVER_NAME ": DMA manager " -+ "at %p\n", dma_base); -+ } -+ } -+ } -+ if (ret != 0) { -+ if (dma_base) -+ iounmap(dma_base); -+ if (dma_res && have_dma_region) -+ release_mem_region(dma_res->start, -+ resource_size(dma_res)); -+ if (dmaman) -+ kfree(dmaman); -+ } -+ return ret; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -+ kfree(dmaman); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_dmaman_driver = { -+ .probe = bcm_dmaman_probe, -+ .remove = bcm_dmaman_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+/*****************************************************************************\ -+ * * -+ * Driver init/exit * -+ * * -+\*****************************************************************************/ -+ -+static int __init bcm_dmaman_drv_init(void) -+{ -+ int ret; -+ -+ ret = platform_driver_register(&bcm_dmaman_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_dmaman_drv_exit(void) -+{ -+ platform_driver_unregister(&bcm_dmaman_driver); -+} -+ -+module_init(bcm_dmaman_drv_init); -+module_exit(bcm_dmaman_drv_exit); -+ -+module_param(dmachans, int, 0644); -+ -+MODULE_AUTHOR("Gray Girling "); -+MODULE_DESCRIPTION("DMA channel manager driver"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); diff --git a/arch/arm/mach-bcm2709/include/mach/arm_control.h b/arch/arm/mach-bcm2709/include/mach/arm_control.h new file mode 100644 index 0000000..e346caf @@ -8067,74 +4963,6 @@ index 0000000..e346caf +#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) + +#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/arm_power.h b/arch/arm/mach-bcm2709/include/mach/arm_power.h -new file mode 100644 -index 0000000..d3bf245 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/arm_power.h -@@ -0,0 +1,62 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef _ARM_POWER_H -+#define _ARM_POWER_H -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/barriers.h b/arch/arm/mach-bcm2709/include/mach/barriers.h new file mode 100644 index 0000000..723cdad @@ -8185,106 +5013,6 @@ index 0000000..b24304a + .endm + +#include -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -new file mode 100644 -index 0000000..d03e7b5 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/dma.h -@@ -0,0 +1,94 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+#ifndef _MACH_BCM2708_DMA_H -+#define _MACH_BCM2708_DMA_H -+ -+#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE (1 << 0) -+#define BCM2708_DMA_INT (1 << 2) -+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR (1 << 8) -+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN (1 << 0) -+#define BCM2708_DMA_TDMODE (1 << 1) -+#define BCM2708_DMA_WAIT_RESP (1 << 3) -+#define BCM2708_DMA_D_INC (1 << 4) -+#define BCM2708_DMA_D_WIDTH (1 << 5) -+#define BCM2708_DMA_D_DREQ (1 << 6) -+#define BCM2708_DMA_S_INC (1 << 8) -+#define BCM2708_DMA_S_WIDTH (1 << 9) -+#define BCM2708_DMA_S_DREQ (1 << 10) -+ -+#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+struct scatterlist; -+ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block); -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); -+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 -+#define BCM_DMA_FEATURE_FAST (1< -+#include -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/system.h b/arch/arm/mach-bcm2709/include/mach/system.h new file mode 100644 index 0000000..2d0b821 @@ -9384,177 +6080,6 @@ index 0000000..70e809f + unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5); + +#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/vcio.h b/arch/arm/mach-bcm2709/include/mach/vcio.h -new file mode 100644 -index 0000000..8e11d67e ---- /dev/null -+++ b/arch/arm/mach-bcm2709/include/mach/vcio.h -@@ -0,0 +1,165 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vcio.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef _MACH_BCM2708_VCIO_H -+#define _MACH_BCM2708_VCIO_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); -+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); -+extern int /*rc*/ bcm_mailbox_property(void *data, int size); -+ -+#include -+ -+/* -+ * The major device number. We can't rely on dynamic -+ * registration any more, because ioctls need to know -+ * it. -+ */ -+#define MAJOR_NUM 100 -+ -+/* -+ * Set the message of the device driver -+ */ -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+/* -+ * _IOWR means that we're creating an ioctl command -+ * number for passing information from a user process -+ * to the kernel module and from the kernel module to user process -+ * -+ * The first arguments, MAJOR_NUM, is the major device -+ * number we're using. -+ * -+ * The second argument is the number of the command -+ * (there could be several with different meanings). -+ * -+ * The third argument is the type we want to get from -+ * the process to the kernel. -+ */ -+ -+/* -+ * The name of the device file -+ */ -+#define DEVICE_FILE_NAME "vcio" -+ -+#endif diff --git a/arch/arm/mach-bcm2709/include/mach/vmalloc.h b/arch/arm/mach-bcm2709/include/mach/vmalloc.h new file mode 100644 index 0000000..6aa6826 @@ -9581,210 +6106,9 @@ index 0000000..6aa6826 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xff000000) -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -new file mode 100644 -index 0000000..3421057 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/power.c -@@ -0,0 +1,195 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+arch_initcall(bcm_power_init); /* Initialize early */ -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c new file mode 100644 -index 0000000..ac578db +index 0000000..d2adfd1 --- /dev/null +++ b/arch/arm/mach-bcm2709/vc_mem.c @@ -0,0 +1,431 @@ @@ -9812,6 +6136,7 @@ index 0000000..ac578db +#include +#include +#include ++#include + +#ifdef CONFIG_ARCH_KONA +#include @@ -9821,7 +6146,6 @@ index 0000000..ac578db +#endif + +#include "mach/vc_mem.h" -+#include + +#define DRIVER_NAME "vc-mem" + @@ -10220,8 +6544,8 @@ index 0000000..ac578db +module_param(mem_size, uint, 0644); +module_param(mem_base, uint, 0644); diff --git a/arch/arm/mach-bcm2709/vc_support.c b/arch/arm/mach-bcm2709/vc_support.c -new file mode 100755 -index 0000000..0bc41c4 +new file mode 100644 +index 0000000..c4dc7d6 --- /dev/null +++ b/arch/arm/mach-bcm2709/vc_support.c @@ -0,0 +1,318 @@ @@ -10233,7 +6557,7 @@ index 0000000..0bc41c4 + */ + +#include -+#include ++#include + +#ifdef ECLIPSE_IGNORE + @@ -10543,491 +6867,51 @@ index 0000000..0bc41c4 + return 1; + } +} -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -new file mode 100644 -index 0000000..5e43e85 ---- /dev/null -+++ b/arch/arm/mach-bcm2709/vcio.c -@@ -0,0 +1,474 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -+#define SUPPORT_SYSRQ -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+ -+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* offsets from a mail box base address */ -+#define MAIL_WRT 0x00 /* write - and next 4 words */ -+#define MAIL_RD 0x00 /* read - and next 4 words */ -+#define MAIL_POL 0x10 /* read without popping the fifo */ -+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL_STA 0x18 /* status */ -+#define MAIL_CNF 0x1C /* configuration */ -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+struct vc_mailbox { -+ struct device *dev; /* parent device */ -+ void __iomem *status; -+ void __iomem *config; -+ void __iomem *read; -+ void __iomem *write; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -+ uint32_t addr_mbox) -+{ -+ int i; -+ -+ mbox_out->dev = dev; -+ mbox_out->status = __io_address(addr_mbox + MAIL_STA); -+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -+ mbox_out->read = __io_address(addr_mbox + MAIL_RD); -+ /* Write to the other mailbox */ -+ mbox_out->write = -+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -+ MAIL_WRT); -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ rc = 0; -+ } -+ return rc; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ rc = 0; -+ } -+ return rc; -+} -+ -+static irqreturn_t mbox_irq(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ int status = readl(mbox->status); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->read); -+ int chan = MBOX_CHAN(msg); -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ /* Overflow */ -+ printk(KERN_ERR DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ printk(KERN_ERR DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->status); -+ } -+ return ret; -+} -+ -+static struct irqaction mbox_irqaction = { -+ .name = "ARM Mailbox IRQ", -+ .flags = IRQF_DISABLED | IRQF_IRQPOLL, -+ .handler = mbox_irq, -+}; -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox Methods -+ * -------------------------------------------------------------------- */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_write(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_read(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static void dev_mbox_register(const char *dev_name, struct device *dev) -+{ -+ mbox_dev = dev; -+} -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)src < TASK_SIZE) -+ { -+ return copy_from_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ( (uint32_t)dst < TASK_SIZE) -+ { -+ return copy_to_user(dst, src, size); -+ } -+ else -+ { -+ memcpy( dst, src, size ); -+ return 0; -+ } -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) { -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ } -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* ---------------------------------------------------------------------- -+ * Platform Device for Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static int Device_Open = 0; -+ -+/* -+ * This is called whenever a process attempts to open the device file -+ */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* -+ * We don't want to talk to two processes at the same time -+ */ -+ if (Device_Open) -+ return -EBUSY; -+ -+ Device_Open++; -+ /* -+ * Initialize the message -+ */ -+ try_module_get(THIS_MODULE); -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * We're now ready for our next caller -+ */ -+ Device_Open--; -+ -+ module_put(THIS_MODULE); -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -+ unsigned int ioctl_num, /* number and param for ioctl */ -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ /* -+ * Switch according to the ioctl called -+ */ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ break; -+ default: -+ printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_mailbox *mailbox; -+ -+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -+ if (NULL == mailbox) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ ret = -ENOMEM; -+ } else { -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ kfree(mailbox); -+ } else { -+ /* should be based on the registers from res really */ -+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -+ -+ platform_set_drvdata(pdev, mailbox); -+ dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ -+ mbox_irqaction.dev_id = mailbox; -+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); -+ } -+ } -+ -+ if (ret == 0) { -+ /* -+ * Register the character device -+ */ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ -+ /* -+ * Negative values signify an error -+ */ -+ if (ret < 0) { -+ printk(KERN_ERR DRIVER_NAME -+ "Failed registering the character device %d\n", ret); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ kfree(mailbox); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ -+ ret = platform_driver_register(&bcm_mbox_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm-mbox"); +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index b4f92b9..bb263d8 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -358,7 +358,7 @@ config CPU_PJ4B + + # ARMv6 + config CPU_V6 +- bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX) ++ bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708) + select CPU_32v6 + select CPU_ABRT_EV6 + select CPU_CACHE_V6 +diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S +index 06d890a..30d96e8 100644 +--- a/arch/arm/mm/proc-v6.S ++++ b/arch/arm/mm/proc-v6.S +@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) + * + * IRQs are already disabled. + */ ++ ++/* See jira SW-5991 for details of this workaround */ + ENTRY(cpu_v6_do_idle) +- mov r1, #0 +- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode +- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ .align 5 ++ mov r1, #2 ++1: subs r1, #1 ++ nop ++ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode ++ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ nop ++ nop ++ nop ++ bne 1b + ret lr + + ENTRY(cpu_v6_dcache_clean_area) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S -index 8b4ee5e..80fa74b 100644 +index 3d1054f..7615bbf 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S -@@ -441,6 +441,7 @@ __v7_setup: +@@ -456,6 +456,7 @@ __v7_setup: orr r0, r0, r6 @ set them THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions ret lr @ return to head.S:__ret @@ -11036,25 +6920,26 @@ index 8b4ee5e..80fa74b 100644 .align 2 diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index c9ddd87..bfc397c 100644 +index 2ed1b8a..b52d949 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types -@@ -523,6 +523,7 @@ prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 +@@ -522,6 +522,8 @@ torbreck MACH_TORBRECK TORBRECK 3090 + prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 - bcm2708 MACH_BCM2708 BCM2708 3138 ++bcm2708 MACH_BCM2708 BCM2708 3138 +bcm2709 MACH_BCM2709 BCM2709 3139 ag5evm MACH_AG5EVM AG5EVM 3189 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c -index a3025e7..4a2a601 100644 +index 0aa135d..89dbcb9 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c -@@ -804,3 +804,39 @@ static void __init arch_timer_mem_init(struct device_node *np) +@@ -882,3 +882,39 @@ void __init acpi_generic_timer_init(void) + acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); } - CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", - arch_timer_mem_init); + #endif + +int __init dc4_arch_timer_init(void) +{ @@ -11091,11 +6976,396 @@ index a3025e7..4a2a601 100644 + arch_timer_common_init(); + return 0; +} +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 763eb20..ad45801 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -85,7 +85,7 @@ struct vendor_data { + + static unsigned int get_fifosize_arm(struct amba_device *dev) + { +- return amba_rev(dev) < 3 ? 16 : 32; ++ return 16; //TODO: fix: amba_rev(dev) < 3 ? 16 : 32; + } + + static struct vendor_data vendor_arm = { +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index b5bedae..b0258e8 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -285,6 +285,7 @@ struct mmc_host { + MMC_CAP2_HS400_1_2V) + #define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) + #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) ++#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ + + mmc_pm_flag_t pm_caps; /* supported pm features */ + -From ade70caa2a108d3a2257a32ce6873758ae968f97 Mon Sep 17 00:00:00 2001 +From aa090a771afa15310eb10d3209c190441f3ecefd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 16 Jun 2015 23:48:09 +0100 +Subject: [PATCH 02/77] power: Add power driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +BCM270x: power: Change initcall level to subsys + +Load ordering of modules are determined by the initcall used. +If it's the same initcall level, makefile ordering decides. +Now that the mailbox driver is being moved, it's no longer +placed before the power driver by the linker. +So use a later initcall level to let the mailbox driver +load first. + +Signed-off-by: Noralf Trønnes + +BCM270x: Move power module + +Make the power module available on ARCH_BCM2835 by moving it. +The module turns on USB power making it possible to boot +ARCH_BCM2835 directly with the VC bootloader. + +Signed-off-by: Noralf Trønnes +--- + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/bcm2835/Kconfig | 9 ++ + drivers/soc/bcm2835/Makefile | 1 + + drivers/soc/bcm2835/bcm2708-power.c | 200 ++++++++++++++++++++++++++++++++++++ + include/soc/bcm2835/power.h | 61 +++++++++++ + 6 files changed, 273 insertions(+) + create mode 100644 drivers/soc/bcm2835/Kconfig + create mode 100644 drivers/soc/bcm2835/Makefile + create mode 100644 drivers/soc/bcm2835/bcm2708-power.c + create mode 100644 include/soc/bcm2835/power.h + +diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig +index d8bde82..595c9cd 100644 +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -1,5 +1,6 @@ + menu "SOC (System On Chip) specific Drivers" + ++source "drivers/soc/bcm2835/Kconfig" + source "drivers/soc/mediatek/Kconfig" + source "drivers/soc/qcom/Kconfig" + source "drivers/soc/ti/Kconfig" +diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile +index 70042b2..9ad449c 100644 +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -2,6 +2,7 @@ + # Makefile for the Linux Kernel SOC specific device drivers. + # + ++obj-y += bcm2835/ + obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ + obj-$(CONFIG_ARCH_QCOM) += qcom/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ +diff --git a/drivers/soc/bcm2835/Kconfig b/drivers/soc/bcm2835/Kconfig +new file mode 100644 +index 0000000..c2980f3 +--- /dev/null ++++ b/drivers/soc/bcm2835/Kconfig +@@ -0,0 +1,9 @@ ++# ++# BCM2835 Soc drivers ++# ++config BCM2708_POWER ++ tristate "BCM2708 legacy power driver" ++ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX ++ default y ++ help ++ Turns on USB power and provides an API for controlling power. +diff --git a/drivers/soc/bcm2835/Makefile b/drivers/soc/bcm2835/Makefile +new file mode 100644 +index 0000000..3614ad9 +--- /dev/null ++++ b/drivers/soc/bcm2835/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_BCM2708_POWER) += bcm2708-power.o +diff --git a/drivers/soc/bcm2835/bcm2708-power.c b/drivers/soc/bcm2835/bcm2708-power.c +new file mode 100644 +index 0000000..e7931a9 +--- /dev/null ++++ b/drivers/soc/bcm2835/bcm2708-power.c +@@ -0,0 +1,200 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/power.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "bcm2708_power" ++ ++#define BCM_POWER_MAXCLIENTS 4 ++#define BCM_POWER_NOCLIENT (1<<31) ++ ++/* Some drivers expect there devices to be permanently powered */ ++ ++#ifdef CONFIG_USB ++#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) ++#endif ++ ++#if 1 ++#define DPRINTK printk ++#else ++#define DPRINTK if (0) printk ++#endif ++ ++struct state_struct { ++ uint32_t global_request; ++ uint32_t client_request[BCM_POWER_MAXCLIENTS]; ++ struct semaphore client_mutex; ++ struct semaphore mutex; ++} g_state; ++ ++int bcm_power_open(BCM_POWER_HANDLE_T *handle) ++{ ++ BCM_POWER_HANDLE_T i; ++ int ret = -EBUSY; ++ ++ down(&g_state.client_mutex); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { ++ g_state.client_request[i] = BCM_POWER_NONE; ++ *handle = i; ++ ret = 0; ++ break; ++ } ++ } ++ ++ up(&g_state.client_mutex); ++ ++ DPRINTK("bcm_power_open() -> %d\n", *handle); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(bcm_power_open); ++ ++int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) ++{ ++ int rc = 0; ++ ++ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); ++ ++ if ((handle < BCM_POWER_MAXCLIENTS) && ++ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { ++ if (down_interruptible(&g_state.mutex) != 0) { ++ DPRINTK("bcm_power_request -> interrupted\n"); ++ return -EINTR; ++ } ++ ++ if (request != g_state.client_request[handle]) { ++ uint32_t others_request = 0; ++ uint32_t global_request; ++ BCM_POWER_HANDLE_T i; ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (i != handle) ++ others_request |= ++ g_state.client_request[i]; ++ } ++ others_request &= ~BCM_POWER_NOCLIENT; ++ ++ global_request = request | others_request; ++ if (global_request != g_state.global_request) { ++ uint32_t actual; ++ ++ /* Send a request to VideoCore */ ++ bcm_mailbox_write(MBOX_CHAN_POWER, ++ global_request << 4); ++ ++ /* Wait for a response during power-up */ ++ if (global_request & ~g_state.global_request) { ++ rc = bcm_mailbox_read(MBOX_CHAN_POWER, ++ &actual); ++ DPRINTK ++ ("bcm_mailbox_read -> %08x, %d\n", ++ actual, rc); ++ actual >>= 4; ++ } else { ++ rc = 0; ++ actual = global_request; ++ } ++ ++ if (rc == 0) { ++ if (actual != global_request) { ++ printk(KERN_ERR ++ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", ++ __func__, ++ g_state.global_request, ++ global_request, actual, request, others_request); ++ /* A failure */ ++ BUG_ON((others_request & actual) ++ != others_request); ++ request &= actual; ++ rc = -EIO; ++ } ++ ++ g_state.global_request = actual; ++ g_state.client_request[handle] = ++ request; ++ } ++ } ++ } ++ up(&g_state.mutex); ++ } else { ++ rc = -EINVAL; ++ } ++ DPRINTK("bcm_power_request -> %d\n", rc); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_request); ++ ++int bcm_power_close(BCM_POWER_HANDLE_T handle) ++{ ++ int rc; ++ ++ DPRINTK("bcm_power_close(%d)\n", handle); ++ ++ rc = bcm_power_request(handle, BCM_POWER_NONE); ++ if (rc == 0) ++ g_state.client_request[handle] = BCM_POWER_NOCLIENT; ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_close); ++ ++static int __init bcm_power_init(void) ++{ ++#if defined(BCM_POWER_ALWAYS_ON) ++ BCM_POWER_HANDLE_T always_on_handle; ++#endif ++ int rc = 0; ++ int i; ++ ++ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); ++ bcm_mailbox_write(MBOX_CHAN_POWER, 0); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) ++ g_state.client_request[i] = BCM_POWER_NOCLIENT; ++ ++ sema_init(&g_state.client_mutex, 1); ++ sema_init(&g_state.mutex, 1); ++ ++ g_state.global_request = 0; ++ ++#if defined(BCM_POWER_ALWAYS_ON) ++ if (BCM_POWER_ALWAYS_ON) { ++ bcm_power_open(&always_on_handle); ++ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); ++ } ++#endif ++ ++ return rc; ++} ++ ++static void __exit bcm_power_exit(void) ++{ ++ bcm_mailbox_write(MBOX_CHAN_POWER, 0); ++} ++ ++/* ++ * Load after the mailbox driver is initialized (arch_initcall), ++ * but before depending drivers (module_init). ++ */ ++subsys_initcall(bcm_power_init); ++module_exit(bcm_power_exit); ++ ++MODULE_AUTHOR("Phil Elwell"); ++MODULE_DESCRIPTION("Interface to BCM2708 power management"); ++MODULE_LICENSE("GPL"); +diff --git a/include/soc/bcm2835/power.h b/include/soc/bcm2835/power.h +new file mode 100644 +index 0000000..bf22b26 +--- /dev/null ++++ b/include/soc/bcm2835/power.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#ifndef _BCM2708_POWER_H ++#define _BCM2708_POWER_H ++ ++#include ++ ++/* Use meaningful names on each side */ ++#ifdef __VIDEOCORE__ ++#define PREFIX(x) ARM_##x ++#else ++#define PREFIX(x) BCM_##x ++#endif ++ ++enum { ++ PREFIX(POWER_SDCARD_BIT), ++ PREFIX(POWER_UART_BIT), ++ PREFIX(POWER_MINIUART_BIT), ++ PREFIX(POWER_USB_BIT), ++ PREFIX(POWER_I2C0_BIT), ++ PREFIX(POWER_I2C1_BIT), ++ PREFIX(POWER_I2C2_BIT), ++ PREFIX(POWER_SPI_BIT), ++ PREFIX(POWER_CCP2TX_BIT), ++ PREFIX(POWER_DSI_BIT), ++ ++ PREFIX(POWER_MAX) ++}; ++ ++enum { ++ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), ++ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), ++ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), ++ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), ++ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), ++ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), ++ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), ++ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), ++ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), ++ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), ++ ++ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, ++ PREFIX(POWER_NONE) = 0 ++}; ++ ++typedef unsigned int BCM_POWER_HANDLE_T; ++ ++extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); ++extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); ++extern int bcm_power_close(BCM_POWER_HANDLE_T handle); ++ ++#endif + +From 9409d45ef7d82d4f0677ea1a16bb6e87d41ed8de Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 Oct 2014 18:50:05 +0100 -Subject: [PATCH 003/216] Add bcm2708_gpio driver +Subject: [PATCH 03/77] Add bcm2708_gpio driver Signed-off-by: popcornmix @@ -11130,22 +7400,23 @@ Issue: linux #760 --- arch/arm/mach-bcm2708/Kconfig | 8 + arch/arm/mach-bcm2708/Makefile | 1 + - arch/arm/mach-bcm2708/bcm2708.c | 28 ++ + arch/arm/mach-bcm2708/bcm2708.c | 25 ++ arch/arm/mach-bcm2708/bcm2708_gpio.c | 426 ++++++++++++++++++++++++++++++ arch/arm/mach-bcm2708/include/mach/gpio.h | 17 ++ + arch/arm/mach-bcm2709/bcm2709.c | 25 ++ include/linux/platform_data/bcm2708.h | 23 ++ - 6 files changed, 503 insertions(+) + 7 files changed, 525 insertions(+) create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h create mode 100644 include/linux/platform_data/bcm2708.h diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 1f11478..9355841 100644 +index 4955422..4cbda0c 100644 --- a/arch/arm/mach-bcm2708/Kconfig +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -9,6 +9,14 @@ config MACH_BCM2708 +@@ -20,6 +20,14 @@ config BCM2708_DT help - Include support for the Broadcom(R) BCM2708 platform. + Enable Device Tree support for BCM2708 +config BCM2708_GPIO + bool "BCM2708 gpio support" @@ -11155,24 +7426,23 @@ index 1f11478..9355841 100644 + help + Include support for the Broadcom(R) BCM2708 gpio. + - config BCM2708_VCMEM - bool "Videocore Memory" + config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" depends on MACH_BCM2708 diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index c76f39bc..a722f3f 100644 +index e7d5a29..5120994 100644 --- a/arch/arm/mach-bcm2708/Makefile +++ b/arch/arm/mach-bcm2708/Makefile -@@ -3,4 +3,5 @@ +@@ -3,3 +3,4 @@ # - obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o + obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 9b4e709..7503649 100644 +index d6659b0..c606853 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -331,6 +331,31 @@ static struct platform_device bcm2708_vcio_device = { +@@ -298,6 +298,31 @@ static struct platform_device bcm2708_vcio_device = { }, }; @@ -11201,19 +7471,9 @@ index 9b4e709..7503649 100644 +}; +#endif + - static struct resource bcm2708_systemtimer_resources[] = { - [0] = { /* system timer access */ - .start = ST_BASE, -@@ -473,6 +498,9 @@ void __init bcm2708_init(void) - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_vcio_device); -+#ifdef CONFIG_BCM2708_GPIO -+ bcm_register_device(&bcm2708_gpio_device); -+#endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c new file mode 100644 index 0000000..c1e9254 @@ -11669,6 +7929,42 @@ index 0000000..7965a97 +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START) + +#endif +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 19d0601..6060a0d 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -329,6 +329,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++#ifdef CONFIG_BCM2708_GPIO ++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" ++ ++static struct resource bcm2708_gpio_resources[] = { ++ [0] = { /* general purpose I/O */ ++ .start = GPIO_BASE, ++ .end = GPIO_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_gpio_device = { ++ .name = BCM_GPIO_DRIVER_NAME, ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_gpio_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), ++ .dev = { ++ .dma_mask = &gpio_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; diff --git a/include/linux/platform_data/bcm2708.h b/include/linux/platform_data/bcm2708.h new file mode 100644 index 0000000..fb69624 @@ -11699,10 +7995,647 @@ index 0000000..fb69624 + +#endif -From 2ca472651d3e308f62709f5e2536eaba99944b11 Mon Sep 17 00:00:00 2001 +From 4b9ec02bb6738a9c29f6308c55cbcab58c2c88a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Fri, 1 May 2015 19:11:03 +0200 +Subject: [PATCH 04/77] mailbox: bcm2708: Add bcm2708-vcio +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +Copy the arch vcio.c driver to drivers/mailbox. +This is done to make it available on ARCH_BCM2835. + +Signed-off-by: Noralf Trønnes + +mailbox: bcm2708-vcio: Allocation does not need to be atomic + +No need to do atomic allocation in a context that can sleep. + +Signed-off-by: Noralf Trønnes + +mailbox: bcm2708-vcio: Check the correct status register before writing + +With the VC reader blocked and the ARM writing, MAIL0_STA reads +empty permanently while MAIL1_STA goes from empty (0x40000000) +to non-empty (0x00000001-0x00000007) to full (0x80000008). + +Suggested-by: Phil Elwell +Signed-off-by: Noralf Trønnes +--- + drivers/mailbox/Kconfig | 6 + + drivers/mailbox/Makefile | 2 + + drivers/mailbox/bcm2708-vcio.c | 427 ++++++++++++++++++++++++++ + include/linux/platform_data/mailbox-bcm2708.h | 126 ++++++++ + 4 files changed, 561 insertions(+) + create mode 100644 drivers/mailbox/bcm2708-vcio.c + create mode 100644 include/linux/platform_data/mailbox-bcm2708.h + +diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig +index 84b0a2d..7f19cb4 100644 +--- a/drivers/mailbox/Kconfig ++++ b/drivers/mailbox/Kconfig +@@ -7,6 +7,12 @@ menuconfig MAILBOX + + if MAILBOX + ++config BCM2708_MBOX ++ bool "Broadcom BCM2708 Mailbox (vcio)" ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ help ++ Broadcom BCM2708 Mailbox (vcio) ++ + config ARM_MHU + tristate "ARM MHU Mailbox" + depends on ARM_AMBA +diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile +index b18201e..cecfad3 100644 +--- a/drivers/mailbox/Makefile ++++ b/drivers/mailbox/Makefile +@@ -2,6 +2,8 @@ + + obj-$(CONFIG_MAILBOX) += mailbox.o + ++obj-$(CONFIG_BCM2708_MBOX) += bcm2708-vcio.o ++ + obj-$(CONFIG_ARM_MHU) += arm_mhu.o + + obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o +diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c +new file mode 100644 +index 0000000..d91672b +--- /dev/null ++++ b/drivers/mailbox/bcm2708-vcio.c +@@ -0,0 +1,427 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/vcio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for writing to the mailboxes, ++ * semaphores, doorbells etc. that are shared between the ARM and the ++ * VideoCore processor ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "bcm2708_vcio" ++#define DEVICE_FILE_NAME "vcio" ++ ++/* offsets from a mail box base address */ ++#define MAIL0_RD 0x00 /* read - and next 4 words */ ++#define MAIL0_POL 0x10 /* read without popping the fifo */ ++#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ ++#define MAIL0_STA 0x18 /* status */ ++#define MAIL0_CNF 0x1C /* configuration */ ++#define MAIL1_WRT 0x20 /* write - and next 4 words */ ++#define MAIL1_STA 0x38 /* status */ ++ ++/* On MACH_BCM270x these come through (arm_control.h ) */ ++#ifndef ARM_MS_EMPTY ++#define ARM_MS_EMPTY BIT(30) ++#define ARM_MS_FULL BIT(31) ++ ++#define ARM_MC_IHAVEDATAIRQEN BIT(0) ++#endif ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) ++ ++#define MBOX_MAGIC 0xd0d0c0de ++ ++#define MAJOR_NUM 100 ++#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) ++ ++static struct class *vcio_class; ++ ++struct vc_mailbox { ++ void __iomem *regs; ++ uint32_t msg[MBOX_CHAN_COUNT]; ++ struct semaphore sema[MBOX_CHAN_COUNT]; ++ uint32_t magic; ++}; ++ ++static void mbox_init(struct vc_mailbox *mbox_out) ++{ ++ int i; ++ ++ for (i = 0; i < MBOX_CHAN_COUNT; i++) { ++ mbox_out->msg[i] = 0; ++ sema_init(&mbox_out->sema[i], 0); ++ } ++ ++ /* Enable the interrupt on data reception */ ++ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); ++ ++ mbox_out->magic = MBOX_MAGIC; ++} ++ ++static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) ++{ ++ if (mbox->magic != MBOX_MAGIC) ++ return -EINVAL; ++ ++ /* wait for the mailbox FIFO to have some space in it */ ++ while (0 != (readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL)) ++ cpu_relax(); ++ ++ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); ++ ++ return 0; ++} ++ ++static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) ++{ ++ if (mbox->magic != MBOX_MAGIC) ++ return -EINVAL; ++ ++ down(&mbox->sema[chan]); ++ *data28 = MBOX_DATA28(mbox->msg[chan]); ++ mbox->msg[chan] = 0; ++ ++ return 0; ++} ++ ++static irqreturn_t mbox_irq_handler(int irq, void *dev_id) ++{ ++ /* wait for the mailbox FIFO to have some data in it */ ++ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; ++ int status = readl(mbox->regs + MAIL0_STA); ++ int ret = IRQ_NONE; ++ ++ while (!(status & ARM_MS_EMPTY)) { ++ uint32_t msg = readl(mbox->regs + MAIL0_RD); ++ int chan = MBOX_CHAN(msg); ++ ++ if (chan < MBOX_CHAN_COUNT) { ++ if (mbox->msg[chan]) { ++ pr_err(DRIVER_NAME ++ ": mbox chan %d overflow - drop %08x\n", ++ chan, msg); ++ } else { ++ mbox->msg[chan] = (msg | 0xf); ++ up(&mbox->sema[chan]); ++ } ++ } else { ++ pr_err(DRIVER_NAME ++ ": invalid channel selector (msg %08x)\n", msg); ++ } ++ ret = IRQ_HANDLED; ++ status = readl(mbox->regs + MAIL0_STA); ++ } ++ return ret; ++} ++ ++/* Mailbox Methods */ ++ ++static struct device *mbox_dev; /* we assume there's only one! */ ++ ++static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) ++{ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ int rc; ++ ++ device_lock(dev); ++ rc = mbox_write(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) ++{ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ int rc; ++ ++ device_lock(dev); ++ rc = mbox_read(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++extern int bcm_mailbox_write(unsigned chan, uint32_t data28) ++{ ++ if (!mbox_dev) ++ return -ENODEV; ++ ++ return dev_mbox_write(mbox_dev, chan, data28); ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_write); ++ ++extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) ++{ ++ if (!mbox_dev) ++ return -ENODEV; ++ ++ return dev_mbox_read(mbox_dev, chan, data28); ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_read); ++ ++static int mbox_copy_from_user(void *dst, const void *src, int size) ++{ ++ if ((uint32_t)src < TASK_SIZE) ++ return copy_from_user(dst, src, size); ++ ++ memcpy(dst, src, size); ++ ++ return 0; ++} ++ ++static int mbox_copy_to_user(void *dst, const void *src, int size) ++{ ++ if ((uint32_t)dst < TASK_SIZE) ++ return copy_to_user(dst, src, size); ++ ++ memcpy(dst, src, size); ++ ++ return 0; ++} ++ ++static DEFINE_MUTEX(mailbox_lock); ++extern int bcm_mailbox_property(void *data, int size) ++{ ++ uint32_t success; ++ dma_addr_t mem_bus; /* the memory address accessed from videocore */ ++ void *mem_kern; /* the memory address accessed from driver */ ++ int s = 0; ++ ++ mutex_lock(&mailbox_lock); ++ /* allocate some memory for the messages communicating with GPU */ ++ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, ++ GFP_KERNEL); ++ if (mem_kern) { ++ /* create the message */ ++ mbox_copy_from_user(mem_kern, data, size); ++ ++ /* send the message */ ++ wmb(); ++ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); ++ if (s == 0) ++ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); ++ if (s == 0) { ++ /* copy the response */ ++ rmb(); ++ mbox_copy_to_user(data, mem_kern, size); ++ } ++ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); ++ } else { ++ s = -ENOMEM; ++ } ++ if (s != 0) ++ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); ++ ++ mutex_unlock(&mailbox_lock); ++ return s; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_property); ++ ++/* Platform Device for Mailbox */ ++ ++/* ++ * Is the device open right now? Used to prevent ++ * concurent access into the same device ++ */ ++static bool device_is_open; ++ ++/* This is called whenever a process attempts to open the device file */ ++static int device_open(struct inode *inode, struct file *file) ++{ ++ /* We don't want to talk to two processes at the same time */ ++ if (device_is_open) ++ return -EBUSY; ++ ++ device_is_open = true; ++ try_module_get(THIS_MODULE); ++ ++ return 0; ++} ++ ++static int device_release(struct inode *inode, struct file *file) ++{ ++ /* We're now ready for our next caller */ ++ device_is_open = false; ++ ++ module_put(THIS_MODULE); ++ ++ return 0; ++} ++ ++/* ++ * This function is called whenever a process tries to do an ioctl on our ++ * device file. We get two extra parameters (additional to the inode and file ++ * structures, which all device functions get): the number of the ioctl called ++ * and the parameter given to the ioctl function. ++ * ++ * If the ioctl is write or read/write (meaning output is returned to the ++ * calling process), the ioctl call returns the output of this function. ++ * ++ */ ++static long device_ioctl(struct file *file, unsigned int ioctl_num, ++ unsigned long ioctl_param) ++{ ++ unsigned size; ++ ++ switch (ioctl_num) { ++ case IOCTL_MBOX_PROPERTY: ++ /* ++ * Receive a pointer to a message (in user space) and set that ++ * to be the device's message. Get the parameter given to ++ * ioctl by the process. ++ */ ++ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); ++ return bcm_mailbox_property((void *)ioctl_param, size); ++ default: ++ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Module Declarations */ ++ ++/* ++ * This structure will hold the functions to be called ++ * when a process does something to the device we ++ * created. Since a pointer to this structure is kept in ++ * the devices table, it can't be local to ++ * init_module. NULL is for unimplemented functios. ++ */ ++const struct file_operations fops = { ++ .unlocked_ioctl = device_ioctl, ++ .open = device_open, ++ .release = device_release, /* a.k.a. close */ ++}; ++ ++static int bcm_vcio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device *vdev; ++ struct vc_mailbox *mailbox; ++ struct resource *res; ++ int irq, ret; ++ ++ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); ++ if (!mailbox) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ mailbox->regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(mailbox->regs)) ++ return PTR_ERR(mailbox->regs); ++ ++ irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(dev, irq, mbox_irq_handler, ++ IRQF_IRQPOLL, ++ dev_name(dev), mailbox); ++ if (ret) { ++ dev_err(dev, "Interrupt request failed %d\n", ret); ++ return ret; ++ } ++ ++ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); ++ if (ret < 0) { ++ pr_err("Character device registration failed %d\n", ret); ++ return ret; ++ } ++ ++ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); ++ if (IS_ERR(vcio_class)) { ++ ret = PTR_ERR(vcio_class); ++ pr_err("Class creation failed %d\n", ret); ++ goto err_class; ++ } ++ ++ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, ++ "vcio"); ++ if (IS_ERR(vdev)) { ++ ret = PTR_ERR(vdev); ++ pr_err("Device creation failed %d\n", ret); ++ goto err_dev; ++ } ++ ++ mbox_init(mailbox); ++ platform_set_drvdata(pdev, mailbox); ++ mbox_dev = dev; ++ ++ dev_info(dev, "mailbox at %p\n", mailbox->regs); ++ ++ return 0; ++ ++err_dev: ++ class_destroy(vcio_class); ++err_class: ++ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); ++ ++ return ret; ++} ++ ++static int bcm_vcio_remove(struct platform_device *pdev) ++{ ++ mbox_dev = NULL; ++ platform_set_drvdata(pdev, NULL); ++ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); ++ class_destroy(vcio_class); ++ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm_vcio_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-vcio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); ++ ++static struct platform_driver bcm_mbox_driver = { ++ .probe = bcm_vcio_probe, ++ .remove = bcm_vcio_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_vcio_of_match_table, ++ }, ++}; ++ ++static int __init bcm_mbox_init(void) ++{ ++ return platform_driver_register(&bcm_mbox_driver); ++} ++ ++static void __exit bcm_mbox_exit(void) ++{ ++ platform_driver_unregister(&bcm_mbox_driver); ++} ++ ++arch_initcall(bcm_mbox_init); /* Initialize early */ ++module_exit(bcm_mbox_exit); ++ ++MODULE_AUTHOR("Gray Girling"); ++MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/platform_data/mailbox-bcm2708.h b/include/linux/platform_data/mailbox-bcm2708.h +new file mode 100644 +index 0000000..cc284ed +--- /dev/null ++++ b/include/linux/platform_data/mailbox-bcm2708.h +@@ -0,0 +1,126 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef _PLAT_MAILBOX_BCM2708_H ++#define _PLAT_MAILBOX_BCM2708_H ++ ++/* Routines to handle I/O via the VideoCore "ARM control" registers ++ * (semaphores, doorbells, mailboxes) ++ */ ++ ++/* Constants shared with the ARM identifying separate mailbox channels */ ++#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ ++#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ ++#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ ++#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ ++#define MBOX_CHAN_COUNT 9 ++ ++enum { ++ VCMSG_PROCESS_REQUEST = 0x00000000 ++}; ++ ++enum { ++ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, ++ VCMSG_REQUEST_FAILED = 0x80000001 ++}; ++ ++/* Mailbox property tags */ ++enum { ++ VCMSG_PROPERTY_END = 0x00000000, ++ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, ++ VCMSG_GET_BOARD_MODEL = 0x00010001, ++ VCMSG_GET_BOARD_REVISION = 0x00010002, ++ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, ++ VCMSG_GET_BOARD_SERIAL = 0x00010004, ++ VCMSG_GET_ARM_MEMORY = 0x00010005, ++ VCMSG_GET_VC_MEMORY = 0x00010006, ++ VCMSG_GET_CLOCKS = 0x00010007, ++ VCMSG_GET_COMMAND_LINE = 0x00050001, ++ VCMSG_GET_DMA_CHANNELS = 0x00060001, ++ VCMSG_GET_POWER_STATE = 0x00020001, ++ VCMSG_GET_TIMING = 0x00020002, ++ VCMSG_SET_POWER_STATE = 0x00028001, ++ VCMSG_GET_CLOCK_STATE = 0x00030001, ++ VCMSG_SET_CLOCK_STATE = 0x00038001, ++ VCMSG_GET_CLOCK_RATE = 0x00030002, ++ VCMSG_SET_CLOCK_RATE = 0x00038002, ++ VCMSG_GET_VOLTAGE = 0x00030003, ++ VCMSG_SET_VOLTAGE = 0x00038003, ++ VCMSG_GET_MAX_CLOCK = 0x00030004, ++ VCMSG_GET_MAX_VOLTAGE = 0x00030005, ++ VCMSG_GET_TEMPERATURE = 0x00030006, ++ VCMSG_GET_MIN_CLOCK = 0x00030007, ++ VCMSG_GET_MIN_VOLTAGE = 0x00030008, ++ VCMSG_GET_TURBO = 0x00030009, ++ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, ++ VCMSG_GET_STC = 0x0003000b, ++ VCMSG_SET_TURBO = 0x00038009, ++ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, ++ VCMSG_SET_LOCK_MEM = 0x0003000d, ++ VCMSG_SET_UNLOCK_MEM = 0x0003000e, ++ VCMSG_SET_RELEASE_MEM = 0x0003000f, ++ VCMSG_SET_EXECUTE_CODE = 0x00030010, ++ VCMSG_SET_EXECUTE_QPU = 0x00030011, ++ VCMSG_SET_ENABLE_QPU = 0x00030012, ++ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, ++ VCMSG_GET_EDID_BLOCK = 0x00030020, ++ VCMSG_GET_CUSTOMER_OTP = 0x00030021, ++ VCMSG_SET_CUSTOMER_OTP = 0x00038021, ++ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, ++ VCMSG_SET_RELEASE_BUFFER = 0x00048001, ++ VCMSG_SET_BLANK_SCREEN = 0x00040002, ++ VCMSG_TST_BLANK_SCREEN = 0x00044002, ++ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, ++ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, ++ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, ++ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, ++ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, ++ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, ++ VCMSG_GET_DEPTH = 0x00040005, ++ VCMSG_TST_DEPTH = 0x00044005, ++ VCMSG_SET_DEPTH = 0x00048005, ++ VCMSG_GET_PIXEL_ORDER = 0x00040006, ++ VCMSG_TST_PIXEL_ORDER = 0x00044006, ++ VCMSG_SET_PIXEL_ORDER = 0x00048006, ++ VCMSG_GET_ALPHA_MODE = 0x00040007, ++ VCMSG_TST_ALPHA_MODE = 0x00044007, ++ VCMSG_SET_ALPHA_MODE = 0x00048007, ++ VCMSG_GET_PITCH = 0x00040008, ++ VCMSG_TST_PITCH = 0x00044008, ++ VCMSG_SET_PITCH = 0x00048008, ++ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, ++ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, ++ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, ++ VCMSG_GET_OVERSCAN = 0x0004000a, ++ VCMSG_TST_OVERSCAN = 0x0004400a, ++ VCMSG_SET_OVERSCAN = 0x0004800a, ++ VCMSG_GET_PALETTE = 0x0004000b, ++ VCMSG_TST_PALETTE = 0x0004400b, ++ VCMSG_SET_PALETTE = 0x0004800b, ++ VCMSG_GET_LAYER = 0x0004000c, ++ VCMSG_TST_LAYER = 0x0004400c, ++ VCMSG_SET_LAYER = 0x0004800c, ++ VCMSG_GET_TRANSFORM = 0x0004000d, ++ VCMSG_TST_TRANSFORM = 0x0004400d, ++ VCMSG_SET_TRANSFORM = 0x0004800d, ++ VCMSG_TST_VSYNC = 0x0004400e, ++ VCMSG_SET_VSYNC = 0x0004800e, ++ VCMSG_SET_CURSOR_INFO = 0x00008010, ++ VCMSG_SET_CURSOR_STATE = 0x00008011, ++}; ++ ++int bcm_mailbox_read(unsigned chan, uint32_t *data28); ++int bcm_mailbox_write(unsigned chan, uint32_t data28); ++int bcm_mailbox_property(void *data, int size); ++ ++#endif + +From c921ec1cd21e8a8eb4e453834a205e9da5dff30a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 004/216] Add dwc_otg driver +Subject: [PATCH 05/77] Add dwc_otg driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -12117,16 +9050,38 @@ in the middle of a transaction. Make the effects less severe. Also get rid of the useless return value. squash: dwc_otg: Allow to build without SMP + +usb: core: make overcurrent messages more prominent + +Hub overcurrent messages are more serious than "debug". Increase loglevel. + +usb: dwc_otg: Don't use dma_to_virt() + +Commit 6ce0d20 changes dma_to_virt() which breaks this driver. +Open code the old dma_to_virt() implementation to work around this. + +Limit the use of __bus_to_virt() to cases where transfer_buffer_length +is set and transfer_buffer is not set. This is done to increase the +chance that this driver will also work on ARCH_BCM2835. + +transfer_buffer should not be NULL if the length is set, but the +comment in the code indicates that there are situations where this +might happen. drivers/usb/isp1760/isp1760-hcd.c also has a similar +comment pointing to a possible: 'usb storage / SCSI bug'. + +Signed-off-by: Noralf Trønnes + +dwc_otg: Fix crash when fiq_enable=0 --- - arch/arm/Kconfig | 1 + arch/arm/include/asm/irqflags.h | 16 +- arch/arm/kernel/fiqasm.S | 4 + arch/arm/mach-bcm2708/armctrl.c | 19 +- - arch/arm/mach-bcm2708/bcm2708.c | 15 +- + arch/arm/mach-bcm2708/bcm2708.c | 11 + arch/arm/mach-bcm2708/include/mach/irqs.h | 153 +- arch/arm/mach-bcm2709/armctrl.c | 10 +- drivers/usb/Makefile | 1 + drivers/usb/core/generic.c | 1 + + drivers/usb/core/hub.c | 2 +- drivers/usb/core/message.c | 79 + drivers/usb/core/otg_whitelist.h | 114 +- drivers/usb/gadget/file_storage.c | 3676 ++++++++++ @@ -12169,7 +9124,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1594 +++++ drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 705 ++ drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 117 + - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1749 +++++ + drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1756 +++++ drivers/usb/host/dwc_otg/dwc_otg_driver.h | 86 + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 1346 ++++ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 367 + @@ -12179,7 +9134,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1132 ++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 ++ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2713 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 994 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 995 +++ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 957 +++ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2712 ++++++++ @@ -12192,7 +9147,7 @@ squash: dwc_otg: Allow to build without SMP drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 74 files changed, 60026 insertions(+), 97 deletions(-) + 74 files changed, 60032 insertions(+), 96 deletions(-) create mode 100644 drivers/usb/gadget/file_storage.c create mode 100644 drivers/usb/host/dwc_common_port/Makefile create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd @@ -12255,18 +9210,6 @@ squash: dwc_otg: Allow to build without SMP create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 4018fea..ee1bb5e 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -382,6 +382,7 @@ config ARCH_BCM2708 - select ARM_ERRATA_411920 - select MACH_BCM2708 - select VC4 -+ select FIQ - help - This enables support for Broadcom BCM2708 boards. - diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h index 3b763d6..5770408 100644 --- a/arch/arm/include/asm/irqflags.h @@ -12310,10 +9253,10 @@ index 8dd26e1..eef4847 100644 + mov pc, r8 +ENDPROC(__FIQ_Branch) diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index ef1c8d5..96fa9b9 100644 +index cd252fa..74bacb3 100644 --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_data *d) +@@ -54,8 +54,12 @@ static void armctrl_mask_irq(struct irq_data *d) 0 }; @@ -12328,7 +9271,7 @@ index ef1c8d5..96fa9b9 100644 } static void armctrl_unmask_irq(struct irq_data *d) -@@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct irq_data *d) +@@ -67,8 +71,14 @@ static void armctrl_unmask_irq(struct irq_data *d) 0 }; @@ -12344,38 +9287,37 @@ index ef1c8d5..96fa9b9 100644 + } } - #if defined(CONFIG_PM) -@@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, + #ifdef CONFIG_OF +@@ -299,6 +309,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, } armctrl_pm_register(base, irq_start, resume_sources); + init_FIQ(FIQ_START); + armctrl_dt_init(); return 0; } diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7503649..d9db081 100644 +index c606853..4455f34 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -291,12 +291,23 @@ static struct resource bcm2708_usb_resources[] = { - .flags = IORESOURCE_MEM, - }, +@@ -254,12 +254,23 @@ static struct resource bcm2708_usb_resources[] = { + .flags = IORESOURCE_MEM, + }, [1] = { -- .start = IRQ_USB, -- .end = IRQ_USB, + .start = MPHI_BASE, + .end = MPHI_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, -+ }, ++ }, + [2] = { -+ .start = IRQ_HOSTPORT, -+ .end = IRQ_HOSTPORT, - .flags = IORESOURCE_IRQ, - }, ++ .start = IRQ_HOSTPORT, ++ .end = IRQ_HOSTPORT, ++ .flags = IORESOURCE_IRQ, ++ }, + [3] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, -+ .flags = IORESOURCE_IRQ, -+ }, + .start = IRQ_USB, + .end = IRQ_USB, + .flags = IORESOURCE_IRQ, + }, }; + @@ -12553,7 +9495,7 @@ index 3a88a1a..45152ed 100644 #define SPARE_ALLOC_IRQS 64 #define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS) diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c -index 2815b64..fc6cb8b 100644 +index 2fcfab9..a366275 100644 --- a/arch/arm/mach-bcm2709/armctrl.c +++ b/arch/arm/mach-bcm2709/armctrl.c @@ -91,7 +91,15 @@ static void armctrl_unmask_irq(struct irq_data *d) @@ -12574,12 +9516,12 @@ index 2815b64..fc6cb8b 100644 } else if (d->irq >= IRQ_ARM_LOCAL_CNTPSIRQ && d->irq < IRQ_ARM_LOCAL_CNTPSIRQ + 4) { #if 1 diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile -index 2f1e2aa..887ca56 100644 +index d8926c6..0607af9 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile -@@ -6,6 +6,7 @@ - +@@ -7,6 +7,7 @@ obj-$(CONFIG_USB) += core/ + obj-$(CONFIG_USB_SUPPORT) += phy/ +obj-$(CONFIG_USB_DWCOTG) += host/ obj-$(CONFIG_USB_DWC3) += dwc3/ @@ -12597,6 +9539,19 @@ index 358ca8d..abaac7c 100644 } return i; } +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 3b71516..8324c14 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4922,7 +4922,7 @@ static void port_event(struct usb_hub *hub, int port1) + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + u16 status = 0, unused; + +- dev_dbg(&port_dev->dev, "over-current change\n"); ++ dev_notice(&port_dev->dev, "over-current change\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_OVER_CURRENT); + msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f368d20..2f6e3fe 100644 --- a/drivers/usb/core/message.c @@ -16527,7 +13482,7 @@ index 0000000..a896d73 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 5ad60e4..fb5b986 100644 +index 197a6a3..5496cd0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -738,6 +738,19 @@ config USB_HWA_HCD @@ -44589,10 +41544,10 @@ index 0000000..ccc24e0 +#endif diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c new file mode 100644 -index 0000000..dc7cd32 +index 0000000..53307f0 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -0,0 +1,1749 @@ +@@ -0,0 +1,1756 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ + * $Revision: #92 $ @@ -45638,9 +42593,16 @@ index 0000000..dc7cd32 +}; +MODULE_DEVICE_TABLE(platform, platform_ids); + ++static const struct of_device_id dwc_otg_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-usb", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dwc_otg_of_match_table); ++ +static struct platform_driver dwc_otg_driver = { + .driver = { + .name = (char *)dwc_driver_name, ++ .of_match_table = dwc_otg_of_match_table, + }, + .id_table = platform_ids, + @@ -48247,7 +45209,7 @@ index 0000000..ffa8d21 +END(_dwc_otg_fiq_stub) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c new file mode 100644 -index 0000000..6c53d2c +index 0000000..4d7c7bb --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -0,0 +1,4252 @@ @@ -50273,7 +47235,7 @@ index 0000000..6c53d2c + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed + * cheeky devices that just hold off using NAKs + */ -+ if (nak_holdoff && qh->do_split) { ++ if (fiq_enable && nak_holdoff && qh->do_split) { + if (qh->nak_frame != 0xffff) { + uint16_t next_frame = dwc_frame_num_inc(qh->nak_frame, (qh->ep_type == UE_BULK) ? nak_holdoff : 8); + uint16_t frame = dwc_otg_hcd_get_frame_number(hcd); @@ -57653,10 +54615,10 @@ index 0000000..8a31562 +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c new file mode 100644 -index 0000000..1d28459 +index 0000000..0f4ebcd --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -0,0 +1,994 @@ +@@ -0,0 +1,995 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ @@ -58195,9 +55157,9 @@ index 0000000..1d28459 + * IRQ line, and calls hcd_start method. + */ +#ifdef PLATFORM_INTERFACE -+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED | IRQF_DISABLED); ++ retval = usb_add_hcd(hcd, platform_get_irq(_dev, fiq_enable ? 0 : 1), IRQF_SHARED); +#else -+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); +#endif + if (retval < 0) { + goto error2; @@ -58425,16 +55387,17 @@ index 0000000..1d28459 + !(usb_pipein(urb->pipe)))); + + buf = urb->transfer_buffer; -+ if (hcd->self.uses_dma) { ++ if (hcd->self.uses_dma && !buf && urb->transfer_buffer_length) { + /* + * Calculate virtual address from physical address, + * because some class driver may not fill transfer_buffer. + * In Buffer DMA mode virual address is used, + * when handling non DWORD aligned buffers. + */ -+ //buf = phys_to_virt(urb->transfer_dma); -+ // DMA addresses are bus addresses not physical addresses! -+ buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); ++ buf = (void *)__bus_to_virt((unsigned long)urb->transfer_dma); ++ dev_warn_once(&urb->dev->dev, ++ "USB transfer_buffer was NULL, will use __bus_to_virt(%pad)=%p\n", ++ &urb->transfer_dma, buf); + } + + if (!(urb->transfer_flags & URB_NO_INTERRUPT)) @@ -72943,24 +69906,24 @@ index 0000000..cdc9963 +test_main(); +0; -From 0876a9278a3227e3f8924b6e04c1af6c18d4e1e7 Mon Sep 17 00:00:00 2001 +From 560486db654a651cebb107628426d1705ef4cc20 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 005/216] bcm2708 watchdog driver +Subject: [PATCH 06/77] bcm2708 watchdog driver Signed-off-by: popcornmix --- - drivers/watchdog/Kconfig | 6 + + drivers/watchdog/Kconfig | 8 +- drivers/watchdog/Makefile | 1 + drivers/watchdog/bcm2708_wdog.c | 382 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 389 insertions(+) + 3 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 drivers/watchdog/bcm2708_wdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 16f2023..ca7d6463 100644 +index e5e7c55..b9c1ed5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -452,6 +452,12 @@ config RETU_WATCHDOG +@@ -451,6 +451,12 @@ config RETU_WATCHDOG To compile this driver as a module, choose M here: the module will be called retu_wdt. @@ -72973,6 +69936,15 @@ index 16f2023..ca7d6463 100644 config MOXART_WDT tristate "MOXART watchdog" depends on ARCH_MOXART +@@ -1216,7 +1222,7 @@ config BCM63XX_WDT + + config BCM2835_WDT + tristate "Broadcom BCM2835 hardware watchdog" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + select WATCHDOG_CORE + help + Watchdog driver for the built in watchdog hardware in Broadcom diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5c19294..aac60bd 100644 --- a/drivers/watchdog/Makefile @@ -73374,10 +70346,13 @@ index 0000000..8a27d68 +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); -From e32648d3db67d9954ee0a8bc13ab3f81345c50af Mon Sep 17 00:00:00 2001 +From 7014dbd386a6ce510bd6b9fa3a3fcfc2bd89d237 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 006/216] bcm2708 framebuffer driver +Date: Wed, 17 Jun 2015 17:06:34 +0100 +Subject: [PATCH 07/77] bcm2708 framebuffer driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -73423,55 +70398,40 @@ transfers, busy-waiting is still likely to be faster. Signed-off-by: Luke Diamand bcm2708: Make ioctl logging quieter + +video: fbdev: bcm2708_fb: Don't panic on error + +No need to panic the kernel if the video driver fails. +Just print a message and return an error. + +Signed-off-by: Noralf Trønnes + +fbdev: bcm2708_fb: Add ARCH_BCM2835 support + +Add Device Tree support. +Pass the device to dma_alloc_coherent() in order to get the +correct bus address on ARCH_BCM2835. +Use the new DMA legacy API header file. +Including is not necessary. + +Signed-off-by: Noralf Trønnes + +BCM270x_DT: Add bcm2708-fb device + +Add bcm2708-fb to Device Tree and don't add the +platform device when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/dma.c | 8 + - arch/arm/mach-bcm2708/include/mach/dma.h | 2 + drivers/video/fbdev/Kconfig | 14 + drivers/video/fbdev/Makefile | 1 + - drivers/video/fbdev/bcm2708_fb.c | 818 ++++++++++ + drivers/video/fbdev/bcm2708_fb.c | 824 ++++++++++ drivers/video/logo/logo_linux_clut224.ppm | 2483 ++++++++++------------------- - 6 files changed, 1724 insertions(+), 1602 deletions(-) + 4 files changed, 1720 insertions(+), 1602 deletions(-) create mode 100644 drivers/video/fbdev/bcm2708_fb.c -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -index 51d147a..1da2413 100644 ---- a/arch/arm/mach-bcm2708/dma.c -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -83,6 +83,14 @@ extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) - - EXPORT_SYMBOL_GPL(bcm_dma_start); - -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ - /* Complete an ongoing DMA (assuming its results are to be ignored) - Does nothing if there is no DMA in progress. - This routine waits for the current AXI transfer to complete before -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index f2568d4..a4aac4c 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -64,11 +64,13 @@ struct bcm2708_dma_cb { - unsigned long next; - unsigned long pad[2]; - }; -+struct scatterlist; - - extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); - extern void bcm_dma_start(void __iomem *dma_chan_base, - dma_addr_t control_block); - extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); - extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); - - /* When listing features we can ask for when allocating DMA channels give diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index b3dd417..b3768b4 100644 +index 1094623..42e6c3b 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -224,6 +224,20 @@ config FB_TILEBLITTING @@ -73480,7 +70440,7 @@ index b3dd417..b3768b4 100644 +config FB_BCM2708 + tristate "BCM2708 framebuffer support" -+ depends on FB && ARM ++ depends on FB && ARM && BCM2708_MBOX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT @@ -73509,10 +70469,10 @@ index 1979aff..57181ad 100644 obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c new file mode 100644 -index 0000000..9179291 +index 0000000..f6ac7da --- /dev/null +++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -0,0 +1,818 @@ +@@ -0,0 +1,824 @@ +/* + * linux/drivers/video/bcm2708_fb.c + * @@ -73539,16 +70499,13 @@ index 0000000..9179291 +#include +#include +#include ++#include ++#include +#include +#include +#include +#include +#include -+ -+#include -+#include -+#include -+ +#include +#include +#include @@ -73840,8 +70797,8 @@ index 0000000..9179291 + /* the console may currently be locked */ + console_trylock(); + console_unlock(); -+ -+ BUG(); /* what can we do here */ ++ pr_err("bcm2708_fb_set_par: Failed to set screen_base\n"); ++ return -EIO; + } + } + print_debug @@ -74143,7 +71100,7 @@ index 0000000..9179291 + void *mem; + + mem = -+ dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma, ++ dma_alloc_coherent(&fb->dev->dev, PAGE_ALIGN(sizeof(*fb->info)), &dma, + GFP_KERNEL); + + if (NULL == mem) { @@ -74192,7 +71149,9 @@ index 0000000..9179291 + */ + + fb_set_var(&fb->fb, &fb->fb.var); -+ bcm2708_fb_set_par(&fb->fb); ++ ret = bcm2708_fb_set_par(&fb->fb); ++ if (ret) ++ return ret; + + print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth, + fbheight, fbdepth, fbswap); @@ -74296,12 +71255,19 @@ index 0000000..9179291 + return 0; +} + ++static const struct of_device_id bcm2708_fb_of_match_table[] = { ++ { .compatible = "brcm,bcm2708-fb", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_fb_of_match_table); ++ +static struct platform_driver bcm2708_fb_driver = { + .probe = bcm2708_fb_probe, + .remove = bcm2708_fb_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = bcm2708_fb_of_match_table, + }, +}; + @@ -76822,10 +73788,10 @@ index 3c14e43..7626beb6a 100644 +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 31a44367b5b2a156b2a45d34a1e6b65c55fe8c96 Mon Sep 17 00:00:00 2001 +From 5efe288a95d60bd10a162be79442d04b6f1d4079 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 007/216] dmaengine: Add support for BCM2708 +Subject: [PATCH 08/77] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -76874,116 +73840,277 @@ Add Device Tree support to the non ARCH_BCM2835 case. Use the same driver name regardless of architecture. Signed-off-by: Noralf Trønnes + +BCM270x_DT: add bcm2835-dma entry + +Add Device Tree entry for bcm2835-dma. +The entry doesn't contain any resources since they are handled +by the arch/arm/mach-bcm270x/dma.c driver. +In non-DT mode, don't add the device in the board file. + +Signed-off-by: Noralf Trønnes + +bcm2708-dmaengine: Add debug options + +BCM270x: Add memory and irq resources to dmaengine device and DT + +Prepare for merging of the legacy DMA API arch driver dma.c +with bcm2708-dmaengine by adding memory and irq resources both +to platform file device and Device Tree node. +Don't use BCM_DMAMAN_DRIVER_NAME so we don't have to include mach/dma.h + +Signed-off-by: Noralf Trønnes + +dmaengine: bcm2708: Merge with arch dma.c driver and disable dma.c + +Merge the legacy DMA API driver with bcm2708-dmaengine. +This is done so we can use bcm2708_fb on ARCH_BCM2835 (mailbox +driver is also needed). + +Changes to the dma.c code: +- Use BIT() macro. +- Cutdown some comments to one line. +- Add mutex to vc_dmaman and use this, since the dev lock is locked + during probing of the engine part. +- Add global g_dmaman variable since drvdata is used by the engine part. +- Restructure for readability: + vc_dmaman_chan_alloc() + vc_dmaman_chan_free() + bcm_dma_chan_free() +- Restructure bcm_dma_chan_alloc() to simplify error handling. +- Use device irq resources instead of hardcoded bcm_dma_irqs table. +- Remove dev_dmaman_register() and code it directly. +- Remove dev_dmaman_deregister() and code it directly. +- Simplify bcm_dmaman_probe() using devm_* functions. +- Get dmachans from DT if available. +- Keep 'dma.dmachans' module argument name for backwards compatibility. + +Make it available on ARCH_BCM2835 as well. + +Signed-off-by: Noralf Trønnes + +dmaengine: bcm2708: set residue_granularity field + +bcm2708-dmaengine supports residue reporting at burst level +but didn't report this via the residue_granularity field. + +Without this field set properly we get playback issues with I2S cards. --- - arch/arm/mach-bcm2708/bcm2708.c | 6 + - arch/arm/mach-bcm2708/dma.c | 2 + - arch/arm/mach-bcm2708/include/mach/dma.h | 6 +- - arch/arm/mach-bcm2709/bcm2709.c | 6 + - drivers/dma/Kconfig | 6 + - drivers/dma/Makefile | 1 + - drivers/dma/bcm2708-dmaengine.c | 989 +++++++++++++++++++++++++++++++ - 7 files changed, 1015 insertions(+), 1 deletion(-) + arch/arm/mach-bcm2708/bcm2708.c | 68 ++ + arch/arm/mach-bcm2709/bcm2709.c | 68 ++ + drivers/dma/Kconfig | 13 +- + drivers/dma/Makefile | 1 + + drivers/dma/bcm2708-dmaengine.c | 1298 +++++++++++++++++++++++++++++ + include/linux/platform_data/dma-bcm2708.h | 127 +++ + 6 files changed, 1574 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/bcm2708-dmaengine.c + create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d9db081..5d8657b 100644 +index 4455f34..6b0b6c4 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -250,6 +250,11 @@ static struct platform_device bcm2708_dmaman_device = { - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), +@@ -234,6 +234,73 @@ static struct amba_device *amba_devs[] __initdata = { + &uart0_device, }; ++static struct resource bcm2708_dmaengine_resources[] = { ++ { ++ .start = DMA_BASE, ++ .end = DMA_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_DMA0, ++ .end = IRQ_DMA0, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA1, ++ .end = IRQ_DMA1, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA2, ++ .end = IRQ_DMA2, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA3, ++ .end = IRQ_DMA3, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA4, ++ .end = IRQ_DMA4, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA5, ++ .end = IRQ_DMA5, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA6, ++ .end = IRQ_DMA6, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA7, ++ .end = IRQ_DMA7, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA8, ++ .end = IRQ_DMA8, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA9, ++ .end = IRQ_DMA9, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA10, ++ .end = IRQ_DMA10, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA11, ++ .end = IRQ_DMA11, ++ .flags = IORESOURCE_IRQ, ++ }, { ++ .start = IRQ_DMA12, ++ .end = IRQ_DMA12, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ +static struct platform_device bcm2708_dmaengine_device = { + .name = "bcm2708-dmaengine", + .id = -1, ++ .resource = bcm2708_dmaengine_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), +}; + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); static struct platform_device bcm2708_fb_device = { -@@ -508,6 +513,7 @@ void __init bcm2708_init(void) - clkdev_add(&lookups[i]); +@@ -463,6 +530,7 @@ void __init bcm2708_init(void) + bcm2708_init_clocks(); + bcm2708_dt_init(); - bcm_register_device(&bcm2708_dmaman_device); -+ bcm_register_device(&bcm2708_dmaengine_device); ++ bcm_register_device_dt(&bcm2708_dmaengine_device); bcm_register_device(&bcm2708_vcio_device); #ifdef CONFIG_BCM2708_GPIO - bcm_register_device(&bcm2708_gpio_device); -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -index 1da2413..a5e58d1 100644 ---- a/arch/arm/mach-bcm2708/dma.c -+++ b/arch/arm/mach-bcm2708/dma.c -@@ -156,6 +156,8 @@ static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, - dmaman->chan_available = chans_available; - dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ - dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ - } - - static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index a4aac4c..d03e7b5 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -77,9 +77,13 @@ extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); - those with higher priority smaller ordinal numbers */ - #define BCM_DMA_FEATURE_FAST_ORD 0 - #define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 - #define BCM_DMA_FEATURE_FAST (1< +#include +#include ++#include +#include +#include +#include +#include -+ -+#ifndef CONFIG_ARCH_BCM2835 -+ -+/* dma manager */ -+#include -+ -+//#define DMA_COMPLETE DMA_SUCCESS -+ -+#endif -+ +#include +#include + +#include "virt-dma.h" + ++static unsigned dma_debug; ++ ++/* ++ * Legacy DMA API ++ */ ++ ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++ ++#define CACHE_LINE_MASK 31 ++#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ ++ ++/* valid only for channels 0 - 14, 15 has its own base address */ ++#define BCM2708_DMA_CHAN(n) ((n) << 8) /* base address */ ++#define BCM2708_DMA_CHANIO(dma_base, n) \ ++ ((void __iomem *)((char *)(dma_base) + BCM2708_DMA_CHAN(n))) ++ ++struct vc_dmaman { ++ void __iomem *dma_base; ++ u32 chan_available; /* bitmap of available channels */ ++ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ ++ struct mutex lock; ++}; ++ ++static struct device *dmaman_dev; /* we assume there's only one! */ ++static struct vc_dmaman *g_dmaman; /* DMA manager */ ++static int dmachans = -1; /* module parameter */ ++ ++/* DMA Auxiliary Functions */ ++ ++/* A DMA buffer on an arbitrary boundary may separate a cache line into a ++ section inside the DMA buffer and another section outside it. ++ Even if we flush DMA buffers from the cache there is always the chance that ++ during a DMA someone will access the part of a cache line that is outside ++ the DMA buffer - which will then bring in unwelcome data. ++ Without being able to dictate our own buffer pools we must insist that ++ DMA buffers consist of a whole number of cache lines. ++*/ ++extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) ++{ ++ int i; ++ ++ for (i = 0; i < sg_len; i++) { ++ if (sg_ptr[i].offset & CACHE_LINE_MASK || ++ sg_ptr[i].length & CACHE_LINE_MASK) ++ return 0; ++ } ++ ++ return 1; ++} ++EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); ++ ++extern void bcm_dma_start(void __iomem *dma_chan_base, ++ dma_addr_t control_block) ++{ ++ dsb(); /* ARM data synchronization (push) operation */ ++ ++ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); ++ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); ++} ++EXPORT_SYMBOL_GPL(bcm_dma_start); ++ ++extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ /* ugly busy wait only option for now */ ++ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) ++ cpu_relax(); ++} ++EXPORT_SYMBOL_GPL(bcm_dma_wait_idle); ++ ++extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_is_busy); ++ ++/* Complete an ongoing DMA (assuming its results are to be ignored) ++ Does nothing if there is no DMA in progress. ++ This routine waits for the current AXI transfer to complete before ++ terminating the current DMA. If the current transfer is hung on a DREQ used ++ by an uncooperative peripheral the AXI transfer may never complete. In this ++ case the routine times out and return a non-zero error code. ++ Use of this routine doesn't guarantee that the ongoing or aborted DMA ++ does not produce an interrupt. ++*/ ++extern int bcm_dma_abort(void __iomem *dma_chan_base) ++{ ++ unsigned long int cs; ++ int rc = 0; ++ ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (BCM2708_DMA_ACTIVE & cs) { ++ long int timeout = 10000; ++ ++ /* write 0 to the active bit - pause the DMA */ ++ writel(0, dma_chan_base + BCM2708_DMA_CS); ++ ++ /* wait for any current AXI transfer to complete */ ++ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { ++ /* we'll un-pause when we set of our next DMA */ ++ rc = -ETIMEDOUT; ++ ++ } else if (BCM2708_DMA_ACTIVE & cs) { ++ /* terminate the control block chain */ ++ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); ++ ++ /* abort the whole DMA */ ++ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, ++ dma_chan_base + BCM2708_DMA_CS); ++ } ++ } ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_abort); ++ ++ /* DMA Manager Device Methods */ ++ ++static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, ++ u32 chans_available) ++{ ++ dmaman->dma_base = dma_base; ++ dmaman->chan_available = chans_available; ++ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* 2 & 3 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* 0 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* 1 to 7 */ ++ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* 8 to 14 */ ++} ++ ++static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, ++ unsigned preferred_feature_set) ++{ ++ u32 chans; ++ int chan = 0; ++ int feature; ++ ++ chans = dmaman->chan_available; ++ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) ++ /* select the subset of available channels with the desired ++ feature so long as some of the candidate channels have that ++ feature */ ++ if ((preferred_feature_set & (1 << feature)) && ++ (chans & dmaman->has_feature[feature])) ++ chans &= dmaman->has_feature[feature]; ++ ++ if (!chans) ++ return -ENOENT; ++ ++ /* return the ordinal of the first channel in the bitmap */ ++ while (chans != 0 && (chans & 1) == 0) { ++ chans >>= 1; ++ chan++; ++ } ++ /* claim the channel */ ++ dmaman->chan_available &= ~(1 << chan); ++ ++ return chan; ++} ++ ++static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) ++{ ++ if (chan < 0) ++ return -EINVAL; ++ ++ if ((1 << chan) & dmaman->chan_available) ++ return -EIDRM; ++ ++ dmaman->chan_available |= (1 << chan); ++ ++ return 0; ++} ++ ++/* DMA Manager Monitor */ ++ ++extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, int *out_dma_irq) ++{ ++ struct vc_dmaman *dmaman = g_dmaman; ++ struct platform_device *pdev = to_platform_device(dmaman_dev); ++ struct resource *r; ++ int chan; ++ ++ if (!dmaman_dev) ++ return -ENODEV; ++ ++ mutex_lock(&dmaman->lock); ++ chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); ++ if (chan < 0) ++ goto out; ++ ++ r = platform_get_resource(pdev, IORESOURCE_IRQ, (unsigned int)chan); ++ if (!r) { ++ dev_err(dmaman_dev, "failed to get irq for DMA channel %d\n", ++ chan); ++ vc_dmaman_chan_free(dmaman, chan); ++ chan = -ENOENT; ++ goto out; ++ } ++ ++ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, chan); ++ *out_dma_irq = r->start; ++ dev_dbg(dmaman_dev, ++ "Legacy API allocated channel=%d, base=%p, irq=%i\n", ++ chan, *out_dma_base, *out_dma_irq); ++ ++out: ++ mutex_unlock(&dmaman->lock); ++ ++ return chan; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); ++ ++extern int bcm_dma_chan_free(int channel) ++{ ++ struct vc_dmaman *dmaman = g_dmaman; ++ int rc; ++ ++ if (!dmaman_dev) ++ return -ENODEV; ++ ++ mutex_lock(&dmaman->lock); ++ rc = vc_dmaman_chan_free(dmaman, channel); ++ mutex_unlock(&dmaman->lock); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_free); ++ ++static int bcm_dmaman_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct vc_dmaman *dmaman; ++ struct resource *r; ++ void __iomem *dma_base; ++ uint32_t val; ++ ++ if (!of_property_read_u32(dev->of_node, ++ "brcm,dma-channel-mask", &val)) ++ dmachans = val; ++ else if (dmachans == -1) ++ dmachans = DEFAULT_DMACHAN_BITMAP; ++ ++ dmaman = devm_kzalloc(dev, sizeof(*dmaman), GFP_KERNEL); ++ if (!dmaman) ++ return -ENOMEM; ++ ++ mutex_init(&dmaman->lock); ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ dma_base = devm_ioremap_resource(dev, r); ++ if (IS_ERR(dma_base)) ++ return PTR_ERR(dma_base); ++ ++ vc_dmaman_init(dmaman, dma_base, dmachans); ++ g_dmaman = dmaman; ++ dmaman_dev = dev; ++ ++ dev_info(dev, "DMA legacy API manager at %p, dmachans=0x%x\n", ++ dma_base, dmachans); ++ ++ return 0; ++} ++ ++static int bcm_dmaman_remove(struct platform_device *pdev) ++{ ++ dmaman_dev = NULL; ++ ++ return 0; ++} ++ ++#else /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++static int bcm_dmaman_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++#endif /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++/* ++ * DMA engine ++ */ + +struct bcm2835_dmadev { + struct dma_device ddev; @@ -77602,7 +75008,10 @@ index 0000000..6150b8f + } + + /* Common part */ -+ control_block->info |= BCM2835_DMA_WAITS(SDHCI_BCM_DMA_WAITS); ++ u32 waits = SDHCI_BCM_DMA_WAITS; ++ if ((dma_debug >> 0) & 0x1f) ++ waits = (dma_debug >> 0) & 0x1f; ++ control_block->info |= BCM2835_DMA_WAITS(waits); + control_block->info |= BCM2835_DMA_WAIT_RESP; + + /* Enable */ @@ -77707,7 +75116,7 @@ index 0000000..6150b8f + return 0; +} + -+#ifdef CONFIG_ARCH_BCM2835 ++#ifndef CONFIG_DMA_BCM2708_LEGACY +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) +{ + struct bcm2835_chan *c; @@ -77785,7 +75194,7 @@ index 0000000..6150b8f +static int bcm2835_dma_probe(struct platform_device *pdev) +{ + struct bcm2835_dmadev *od; -+#ifdef CONFIG_ARCH_BCM2835 ++#ifndef CONFIG_DMA_BCM2708_LEGACY + struct resource *res; + void __iomem *base; + uint32_t chans_available; @@ -77798,10 +75207,7 @@ index 0000000..6150b8f + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + -+ /* If CONFIG_ARCH_BCM2835 is selected, device tree is used */ -+ /* hence the difference between probing */ -+ -+#ifndef CONFIG_ARCH_BCM2835 ++#ifdef CONFIG_DMA_BCM2708_LEGACY + + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) @@ -77813,6 +75219,10 @@ index 0000000..6150b8f + if (!od) + return -ENOMEM; + ++ rc = bcm_dmaman_probe(pdev); ++ if (rc) ++ return rc; ++ + pdev->dev.dma_parms = &od->dma_parms; + dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); + @@ -77831,6 +75241,7 @@ index 0000000..6150b8f + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); @@ -77899,6 +75310,7 @@ index 0000000..6150b8f + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); @@ -77954,6 +75366,7 @@ index 0000000..6150b8f + } + + dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n"); ++ dev_info(&pdev->dev, "dma_debug:%x\n", dma_debug); + + return 0; + @@ -77968,6 +75381,7 @@ index 0000000..6150b8f + + dma_async_device_unregister(&od->ddev); + bcm2835_dma_free(od); ++ bcm_dmaman_remove(pdev); + + return 0; +} @@ -77982,18 +75396,173 @@ index 0000000..6150b8f + }, +}; + -+module_platform_driver(bcm2835_dma_driver); ++static int bcm2835_init(void) ++{ ++ return platform_driver_register(&bcm2835_dma_driver); ++} + ++static void bcm2835_exit(void) ++{ ++ platform_driver_unregister(&bcm2835_dma_driver); ++} ++ ++/* ++ * Load after serial driver (arch_initcall) so we see the messages if it fails, ++ * but before drivers (module_init) that need a DMA channel. ++ */ ++subsys_initcall(bcm2835_init); ++module_exit(bcm2835_exit); ++ ++module_param(dma_debug, uint, 0644); ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++/* Keep backward compatibility: dma.dmachans= */ ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "dma." ++module_param(dmachans, int, 0644); ++#endif +MODULE_ALIAS("platform:bcm2835-dma"); +MODULE_DESCRIPTION("BCM2835 DMA engine driver"); +MODULE_AUTHOR("Florian Meier "); +MODULE_AUTHOR("Gellert Weisz "); +MODULE_LICENSE("GPL v2"); +diff --git a/include/linux/platform_data/dma-bcm2708.h b/include/linux/platform_data/dma-bcm2708.h +new file mode 100644 +index 0000000..2310e34 +--- /dev/null ++++ b/include/linux/platform_data/dma-bcm2708.h +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _PLAT_BCM2708_DMA_H ++#define _PLAT_BCM2708_DMA_H ++ ++/* DMA CS Control and Status bits */ ++#define BCM2708_DMA_ACTIVE BIT(0) ++#define BCM2708_DMA_INT BIT(2) ++#define BCM2708_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ ++#define BCM2708_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ ++#define BCM2708_DMA_ERR BIT(8) ++#define BCM2708_DMA_ABORT BIT(30) /* stop current CB, go to next, WO */ ++#define BCM2708_DMA_RESET BIT(31) /* WO, self clearing */ ++ ++/* DMA control block "info" field bits */ ++#define BCM2708_DMA_INT_EN BIT(0) ++#define BCM2708_DMA_TDMODE BIT(1) ++#define BCM2708_DMA_WAIT_RESP BIT(3) ++#define BCM2708_DMA_D_INC BIT(4) ++#define BCM2708_DMA_D_WIDTH BIT(5) ++#define BCM2708_DMA_D_DREQ BIT(6) ++#define BCM2708_DMA_S_INC BIT(8) ++#define BCM2708_DMA_S_WIDTH BIT(9) ++#define BCM2708_DMA_S_DREQ BIT(10) ++ ++#define BCM2708_DMA_BURST(x) (((x) & 0xf) << 12) ++#define BCM2708_DMA_PER_MAP(x) ((x) << 16) ++#define BCM2708_DMA_WAITS(x) (((x) & 0x1f) << 21) ++ ++#define BCM2708_DMA_DREQ_EMMC 11 ++#define BCM2708_DMA_DREQ_SDHOST 13 ++ ++#define BCM2708_DMA_CS 0x00 /* Control and Status */ ++#define BCM2708_DMA_ADDR 0x04 ++/* the current control block appears in the following registers - read only */ ++#define BCM2708_DMA_INFO 0x08 ++#define BCM2708_DMA_SOURCE_AD 0x0c ++#define BCM2708_DMA_DEST_AD 0x10 ++#define BCM2708_DMA_NEXTCB 0x1C ++#define BCM2708_DMA_DEBUG 0x20 ++ ++#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4) + BCM2708_DMA_CS) ++#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4) + BCM2708_DMA_ADDR) ++ ++#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) ++ ++/* When listing features we can ask for when allocating DMA channels give ++ those with higher priority smaller ordinal numbers */ ++#define BCM_DMA_FEATURE_FAST_ORD 0 ++#define BCM_DMA_FEATURE_BULK_ORD 1 ++#define BCM_DMA_FEATURE_NORMAL_ORD 2 ++#define BCM_DMA_FEATURE_LITE_ORD 3 ++#define BCM_DMA_FEATURE_FAST BIT(BCM_DMA_FEATURE_FAST_ORD) ++#define BCM_DMA_FEATURE_BULK BIT(BCM_DMA_FEATURE_BULK_ORD) ++#define BCM_DMA_FEATURE_NORMAL BIT(BCM_DMA_FEATURE_NORMAL_ORD) ++#define BCM_DMA_FEATURE_LITE BIT(BCM_DMA_FEATURE_LITE_ORD) ++#define BCM_DMA_FEATURE_COUNT 4 ++ ++struct bcm2708_dma_cb { ++ unsigned long info; ++ unsigned long src; ++ unsigned long dst; ++ unsigned long length; ++ unsigned long stride; ++ unsigned long next; ++ unsigned long pad[2]; ++}; ++ ++struct scatterlist; ++ ++#ifdef CONFIG_DMA_BCM2708_LEGACY ++ ++int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); ++void bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block); ++void bcm_dma_wait_idle(void __iomem *dma_chan_base); ++bool bcm_dma_is_busy(void __iomem *dma_chan_base); ++int bcm_dma_abort(void __iomem *dma_chan_base); ++ ++/* return channel no or -ve error */ ++int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, int *out_dma_irq); ++int bcm_dma_chan_free(int channel); ++ ++#else /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++static inline int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, ++ int sg_len) ++{ ++ return 0; ++} ++ ++static inline void bcm_dma_start(void __iomem *dma_chan_base, ++ dma_addr_t control_block) { } ++ ++static inline void bcm_dma_wait_idle(void __iomem *dma_chan_base) { } ++ ++static inline bool bcm_dma_is_busy(void __iomem *dma_chan_base) ++{ ++ return false; ++} ++ ++static inline int bcm_dma_abort(void __iomem *dma_chan_base) ++{ ++ return -EINVAL; ++} ++ ++static inline int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, ++ int *out_dma_irq) ++{ ++ return -EINVAL; ++} ++ ++static inline int bcm_dma_chan_free(int channel) ++{ ++ return -EINVAL; ++} ++ ++#endif /* CONFIG_DMA_BCM2708_LEGACY */ ++ ++#endif /* _PLAT_BCM2708_DMA_H */ -From 7ec18e818133424bf20d58993fa6822dd241e096 Mon Sep 17 00:00:00 2001 +From be30ad8849aa9fd6ffbe6f8198a5af4bb62c465f Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 008/216] MMC: added alternative MMC driver +Subject: [PATCH 09/77] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78019,23 +75588,61 @@ Probe error handling is broken in several places. Simplify error handling by using device managed functions. Replace pr_{err,info} with dev_{err,info}. +Signed-off-by: Noralf Trønnes + +bcm2835-mmc: Add locks when accessing sdhost registers + +bcm2835-mmc: Add range of debug options for slowing things down + +bcm2835-mmc: Add option to disable some delays + +bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23 + +bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23 + +bcm2835-mmc: Adding overclocking option + +Allow a different clock speed to be substitued for a requested 50MHz. +This option is exposed using the "overclock_50" DT parameter. +Note that the mmc interface is restricted to EVEN integer divisions of +250MHz, and the highest sensible option is 63 (250/4 = 62.5), the +next being 125 (250/2) which is much too high. + +Use at your own risk. + +bcm2835-mmc: Round up the overclock, so 62 works for 62.5Mhz + +Also only warn once for each overclock setting. + +mmc: bcm2835-mmc: Make available on ARCH_BCM2835 + +Make the bcm2835-mmc driver available for use on ARCH_BCM2835. + +Signed-off-by: Noralf Trønnes + +BCM270x_DT: add bcm2835-mmc entry + +Add Device Tree entry for bcm2835-mmc. +In non-DT mode, don't add the device in the board file. + Signed-off-by: Noralf Trønnes --- arch/arm/mach-bcm2708/bcm2708.c | 31 + - drivers/mmc/core/quirks.c | 4 + + arch/arm/mach-bcm2709/bcm2709.c | 35 +- + drivers/mmc/core/quirks.c | 6 + drivers/mmc/host/Kconfig | 29 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-mmc.c | 1506 +++++++++++++++++++++++++++++++++++++++ - 5 files changed, 1571 insertions(+) + drivers/mmc/host/bcm2835-mmc.c | 1558 +++++++++++++++++++++++++++++++++++++++ + 6 files changed, 1658 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5d8657b..d1308ed 100644 +index 6b0b6c4..5b10802 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -399,6 +399,34 @@ static struct platform_device bcm2708_systemtimer_device = { - }, +@@ -401,6 +401,34 @@ static struct platform_device bcm2708_gpio_device = { }; + #endif +#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ +static struct resource bcm2835_emmc_resources[] = { @@ -78065,35 +75672,97 @@ index 5d8657b..d1308ed 100644 +}; +#endif /* CONFIG_MMC_BCM2835 */ + - static struct resource bcm2708_powerman_resources[] = { - [0] = { - .start = PM_BASE, -@@ -524,6 +552,9 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -538,6 +566,9 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); +#ifdef CONFIG_MMC_BCM2835 -+ bcm_register_device(&bcm2835_emmc_device); ++ bcm_register_device_dt(&bcm2835_emmc_device); +#endif bcm2708_init_led(); + bcm2708_init_uart1(); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 86ebfbe..54c5444 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -421,6 +421,34 @@ static struct platform_device bcm2708_gpio_device = { + }; + #endif + ++#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ ++static struct resource bcm2835_emmc_resources[] = { ++ [0] = { ++ .start = EMMC_BASE, ++ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ ++ /* the memory map actually makes SZ_4K available */ ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_ARASANSDIO, ++ .end = IRQ_ARASANSDIO, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 bcm2835_emmc_dmamask = 0xffffffffUL; ++ ++struct platform_device bcm2835_emmc_device = { ++ .name = "mmc-bcm2835", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), ++ .resource = bcm2835_emmc_resources, ++ .dev = { ++ .dma_mask = &bcm2835_emmc_dmamask, ++ .coherent_dma_mask = 0xffffffffUL}, ++}; ++#endif /* CONFIG_MMC_BCM2835 */ ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -558,8 +586,11 @@ void __init bcm2709_init(void) + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +- bcm2708_init_led(); +- bcm2708_init_uart1(); ++#ifdef CONFIG_MMC_BCM2835 ++ bcm_register_device_dt(&bcm2835_emmc_device); ++#endif ++ bcm2709_init_led(); ++ bcm2709_init_uart1(); + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c -index dd1d1e0..f472082 100644 +index dd1d1e0..bc3bbad 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c -@@ -95,5 +95,9 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) +@@ -71,6 +71,7 @@ static const struct mmc_fixup mmc_fixup_methods[] = { + + void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) + { ++ extern unsigned mmc_debug; + const struct mmc_fixup *f; + u64 rev = cid_rev_card(card); + +@@ -95,5 +96,10 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) f->vendor_fixup(card, f->data); } } + /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail. + * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers). + */ ++ if (mmc_debug & (1<<13)) + card->quirks |= MMC_QUIRK_BLK_NO_CMD23; } EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 61ac63a..7c093a6 100644 +index b1f837e..0ef7417 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -4,6 +4,35 @@ @@ -78102,7 +75771,7 @@ index 61ac63a..7c093a6 100644 +config MMC_BCM2835 + tristate "MMC support on BCM2835" -+ depends on (MACH_BCM2708 || MACH_BCM2709) ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 + help + This selects the MMC Interface on BCM2835. + @@ -78133,7 +75802,7 @@ index 61ac63a..7c093a6 100644 tristate "ARM AMBA Multimedia Card Interface support" depends on ARM_AMBA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 6a7cfe0..9d41de9 100644 +index e3ab5b9..f1ee1f7 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o @@ -78146,10 +75815,10 @@ index 6a7cfe0..9d41de9 100644 obj-$(CONFIG_MMC_OMAP) += omap.o diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c new file mode 100644 -index 0000000..eef0d351 +index 0000000..b7c4883 --- /dev/null +++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -0,0 +1,1506 @@ +@@ -0,0 +1,1558 @@ +/* + * BCM2835 MMC host driver. + * @@ -78223,6 +75892,9 @@ index 0000000..eef0d351 +#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) + + ++unsigned mmc_debug; ++unsigned mmc_debug2; ++ +struct bcm2835_host { + spinlock_t lock; + @@ -78280,22 +75952,38 @@ index 0000000..eef0d351 +#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ +#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ +#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ ++ ++ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ ++ u32 max_overclock; /* Highest reported */ +}; + + -+static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) ++static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from) +{ ++ unsigned delay; ++ lockdep_assert_held_once(&host->lock); + writel(val, host->ioaddr + reg); + udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); ++ ++ delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf); ++ if (delay && !((1<lock); + writel(val, host->ioaddr + reg); ++ ++ delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf); ++ if (delay) ++ udelay(delay); +} + +static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) +{ ++ lockdep_assert_held_once(&host->lock); + return readl(host->ioaddr + reg); +} + @@ -78311,7 +75999,7 @@ index 0000000..eef0d351 + if (reg == SDHCI_TRANSFER_MODE) + host->shadow = newval; + else -+ bcm2835_mmc_writel(host, newval, reg & ~3); ++ bcm2835_mmc_writel(host, newval, reg & ~3, 0); + +} + @@ -78323,7 +76011,7 @@ index 0000000..eef0d351 + u32 mask = 0xff << byte_shift; + u32 newval = (oldval & ~mask) | (val << byte_shift); + -+ bcm2835_mmc_writel(host, newval, reg & ~3); ++ bcm2835_mmc_writel(host, newval, reg & ~3, 1); +} + + @@ -78355,7 +76043,7 @@ index 0000000..eef0d351 + ier &= ~clear; + /* change which requests generate IRQs - makes no difference to + the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ -+ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2); +} + + @@ -78407,7 +76095,9 @@ index 0000000..eef0d351 +static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) +{ + unsigned long timeout; ++ unsigned long flags; + ++ spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET); + + if (mask & SDHCI_RESET_ALL) @@ -78425,19 +76115,23 @@ index 0000000..eef0d351 + return; + } + timeout--; ++ spin_unlock_irqrestore(&host->lock, flags); + mdelay(1); ++ spin_lock_irqsave(&host->lock, flags); + } + + if (100-timeout > 10 && 100-timeout > host->max_delay) { + host->max_delay = 100-timeout; + pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay); + } ++ spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + +static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) +{ ++ unsigned long flags; + if (soft) + bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); + else @@ -78449,8 +76143,10 @@ index 0000000..eef0d351 + SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | + SDHCI_INT_RESPONSE; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ spin_lock_irqsave(&host->lock, flags); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3); ++ spin_unlock_irqrestore(&host->lock, flags); + + if (soft) { + /* force clock reconfiguration */ @@ -78649,11 +76345,14 @@ index 0000000..eef0d351 + dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); + } + if (desc) { ++ unsigned long flags; ++ spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + host->tx_desc = desc; + desc->callback = bcm2835_mmc_dma_complete; + desc->callback_param = host; ++ spin_unlock_irqrestore(&host->lock, flags); + dmaengine_submit(desc); + dma_async_issue_pending(dma_chan); + } @@ -78672,8 +76371,8 @@ index 0000000..eef0d351 + else + host->ier = (host->ier & ~dma_irqs) | pio_irqs; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4); +} + + @@ -78755,7 +76454,7 @@ index 0000000..eef0d351 + mode |= SDHCI_TRNS_AUTO_CMD12; + else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { + mode |= SDHCI_TRNS_AUTO_CMD23; -+ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); ++ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5); + } + } + @@ -78818,7 +76517,7 @@ index 0000000..eef0d351 + + bcm2835_mmc_prepare_data(host, cmd); + -+ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT); ++ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6); + + bcm2835_mmc_set_transfer_mode(host, cmd); + @@ -78975,8 +76674,8 @@ index 0000000..eef0d351 + else + host->ier &= ~SDHCI_INT_CARD_INT; + -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7); ++ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7); + mmiowb(); + } +} @@ -79123,7 +76822,7 @@ index 0000000..eef0d351 + /* Clear selected interrupts. */ + mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | + SDHCI_INT_BUS_POWER); -+ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS); ++ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8); + + + if (intmask & SDHCI_INT_CMD_MASK) @@ -79153,7 +76852,7 @@ index 0000000..eef0d351 + + if (intmask) { + unexpected |= intmask; -+ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS); ++ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9); + } + + if (result == IRQ_NONE) @@ -79211,7 +76910,10 @@ index 0000000..eef0d351 + int real_div = div, clk_mul = 1; + u16 clk = 0; + unsigned long timeout; ++ unsigned int input_clock = clock; + ++ if (host->overclock_50 && (clock == 50000000)) ++ clock = host->overclock_50 * 1000000 + 999999; + + host->mmc->actual_clock = 0; + @@ -79235,7 +76937,14 @@ index 0000000..eef0d351 + div >>= 1; + + if (real_div) -+ host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; ++ clock = (host->max_clk * clk_mul) / real_div; ++ host->mmc->actual_clock = clock; ++ ++ if ((clock > input_clock) && (clock > host->max_overclock)) { ++ pr_warn("%s: Overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->max_overclock = clock; ++ } + + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) @@ -79302,6 +77011,9 @@ index 0000000..eef0d351 + u8 ctrl; + u16 clk, ctrl_2; + ++ pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); + + spin_lock_irqsave(&host->lock, flags); + @@ -79395,8 +77107,10 @@ index 0000000..eef0d351 + (mrq->data && (mrq->data->error || + (mrq->data->stop && mrq->data->stop->error))))) { + ++ spin_unlock_irqrestore(&host->lock, flags); + bcm2835_mmc_reset(host, SDHCI_RESET_CMD); + bcm2835_mmc_reset(host, SDHCI_RESET_DATA); ++ spin_lock_irqsave(&host->lock, flags); + } + + host->mrq = NULL; @@ -79411,7 +77125,7 @@ index 0000000..eef0d351 + + + -+int bcm2835_mmc_add_host(struct bcm2835_host *host) ++static int bcm2835_mmc_add_host(struct bcm2835_host *host) +{ + struct mmc_host *mmc = host->mmc; + struct device *dev = mmc->parent; @@ -79439,8 +77153,7 @@ index 0000000..eef0d351 + + host->flags = SDHCI_AUTO_CMD23; + -+ spin_lock_init(&host->lock); -+ ++ dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2); +#ifdef FORCE_PIO + dev_info(dev, "Forcing PIO mode\n"); + host->have_dma = false; @@ -79568,10 +77281,16 @@ index 0000000..eef0d351 + goto err; + } + -+ if (node) ++ if (node) { + mmc_of_parse(mmc); -+ else ++ ++ /* Read any custom properties */ ++ of_property_read_u32(node, ++ "brcm,overclock-50", ++ &host->overclock_50); ++ } else { + mmc->caps |= MMC_CAP_4_BIT_DATA; ++ } + + ret = bcm2835_mmc_add_host(host); + if (ret) @@ -79652,15 +77371,1790 @@ index 0000000..eef0d351 +}; +module_platform_driver(bcm2835_mmc_driver); + ++module_param(mmc_debug, uint, 0644); ++module_param(mmc_debug2, uint, 0644); +MODULE_ALIAS("platform:mmc-bcm2835"); +MODULE_DESCRIPTION("BCM2835 SDHCI driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 97f9d94720b108ba3e793621d4a500cc593fc775 Mon Sep 17 00:00:00 2001 +From 81cff325dce6ba8765e23e542a219d3c9103a70b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 25 Mar 2015 17:49:47 +0000 +Subject: [PATCH 10/77] Adding bcm2835-sdhost driver, and an overlay to enable + it + +BCM2835 has two SD card interfaces. This driver uses the other one. + +bcm2835-sdhost: Error handling fix, and code clarification + +bcm2835-sdhost: Adding overclocking option + +Allow a different clock speed to be substitued for a requested 50MHz. +This option is exposed using the "overclock_50" DT parameter. +Note that the sdhost interface is restricted to integer divisions of +core_freq, and the highest sensible option for a core_freq of 250MHz +is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too +high. + +Use at your own risk. + +bcm2835-sdhost: Round up the overclock, so 62 works for 62.5Mhz + +Also only warn once for each overclock setting. +--- + drivers/mmc/host/Kconfig | 10 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/bcm2835-sdhost.c | 1702 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 1713 insertions(+) + create mode 100644 drivers/mmc/host/bcm2835-sdhost.c + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 0ef7417..1af139a 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER + + If unsure, say 2 here. + ++config MMC_BCM2835_SDHOST ++ tristate "Support for the SDHost controller on BCM2708/9" ++ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ help ++ This selects the SDHost controller on BCM2835/6. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_ARMMMCI + tristate "ARM AMBA Multimedia Card Interface support" + depends on ARM_AMBA +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index f1ee1f7..8c656a5 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o + obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o + obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o + obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o ++obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o + obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o + obj-$(CONFIG_MMC_WBSD) += wbsd.o + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +new file mode 100644 +index 0000000..eef8a24 +--- /dev/null ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -0,0 +1,1702 @@ ++/* ++ * BCM2835 SD host driver. ++ * ++ * Author: Phil Elwell ++ * Copyright 2015 ++ * ++ * Based on ++ * mmc-bcm2835.c by Gellert Weisz ++ * which is, in turn, based on ++ * sdhci-bcm2708.c by Broadcom ++ * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko ++ * sdhci.c and sdhci-pci.c by Pierre Ossman ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#define SAFE_READ_THRESHOLD 4 ++#define SAFE_WRITE_THRESHOLD 4 ++#define ALLOW_DMA 1 ++#define ALLOW_CMD23 0 ++#define ALLOW_FAST 1 ++#define USE_BLOCK_IRQ 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "sdhost-bcm2835" ++ ++#define SDCMD 0x00 /* Command to SD card - 16 R/W */ ++#define SDARG 0x04 /* Argument to SD card - 32 R/W */ ++#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ ++#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ ++#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ ++#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ ++#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ ++#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ ++#define SDHSTS 0x20 /* SD host status - 11 R */ ++#define SDVDD 0x30 /* SD card power control - 1 R/W */ ++#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ ++#define SDHCFG 0x38 /* Host configuration - 2 R/W */ ++#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ ++#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ ++#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ ++ ++#define SDCMD_NEW_FLAG 0x8000 ++#define SDCMD_FAIL_FLAG 0x4000 ++#define SDCMD_BUSYWAIT 0x800 ++#define SDCMD_NO_RESPONSE 0x400 ++#define SDCMD_LONG_RESPONSE 0x200 ++#define SDCMD_WRITE_CMD 0x80 ++#define SDCMD_READ_CMD 0x40 ++#define SDCMD_CMD_MASK 0x3f ++ ++#define SDCDIV_MAX_CDIV 0x7ff ++ ++#define SDHSTS_BUSY_IRPT 0x400 ++#define SDHSTS_BLOCK_IRPT 0x200 ++#define SDHSTS_SDIO_IRPT 0x100 ++#define SDHSTS_REW_TIME_OUT 0x80 ++#define SDHSTS_CMD_TIME_OUT 0x40 ++#define SDHSTS_CRC16_ERROR 0x20 ++#define SDHSTS_CRC7_ERROR 0x10 ++#define SDHSTS_FIFO_ERROR 0x08 ++/* Reserved */ ++/* Reserved */ ++#define SDHSTS_DATA_FLAG 0x01 ++ ++#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) ++#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) ++/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ ++ ++#define SDHCFG_BUSY_IRPT_EN (1<<10) ++#define SDHCFG_BLOCK_IRPT_EN (1<<8) ++#define SDHCFG_SDIO_IRPT_EN (1<<5) ++#define SDHCFG_DATA_IRPT_EN (1<<4) ++#define SDHCFG_SLOW_CARD (1<<3) ++#define SDHCFG_WIDE_EXT_BUS (1<<2) ++#define SDHCFG_WIDE_INT_BUS (1<<1) ++#define SDHCFG_REL_CMD_LINE (1<<0) ++ ++#define SDEDM_FORCE_DATA_MODE (1<<19) ++#define SDEDM_CLOCK_PULSE (1<<20) ++#define SDEDM_BYPASS (1<<21) ++ ++#define SDEDM_WRITE_THRESHOLD_SHIFT 9 ++#define SDEDM_READ_THRESHOLD_SHIFT 14 ++#define SDEDM_THRESHOLD_MASK 0x1f ++ ++/* the inclusive limit in bytes under which PIO will be used instead of DMA */ ++#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER ++#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER ++#else ++#define PIO_DMA_BARRIER 0 ++#endif ++ ++#define MIN_FREQ 400000 ++#define TIMEOUT_VAL 0xE ++#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) ++ ++#ifndef BCM2708_PERI_BASE ++ #define BCM2708_PERI_BASE 0x20000000 ++#endif ++ ++/* FIXME: Needs IOMMU support */ ++#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) ++ ++ ++struct bcm2835_host { ++ spinlock_t lock; ++ ++ void __iomem *ioaddr; ++ u32 phys_addr; ++ ++ struct mmc_host *mmc; ++ ++ u32 timeout; ++ ++ int clock; /* Current clock speed */ ++ ++ bool slow_card; /* Force 11-bit divisor */ ++ ++ unsigned int max_clk; /* Max possible freq */ ++ unsigned int timeout_clk; /* Timeout freq (KHz) */ ++ ++ struct tasklet_struct finish_tasklet; /* Tasklet structures */ ++ ++ struct timer_list timer; /* Timer for timeouts */ ++ ++ struct sg_mapping_iter sg_miter; /* SG state for PIO */ ++ unsigned int blocks; /* remaining PIO blocks */ ++ ++ int irq; /* Device IRQ */ ++ ++ ++ /* cached registers */ ++ u32 hcfg; ++ u32 cdiv; ++ ++ struct mmc_request *mrq; /* Current request */ ++ struct mmc_command *cmd; /* Current command */ ++ struct mmc_data *data; /* Current data request */ ++ unsigned int data_complete:1; /* Data finished before cmd */ ++ ++ unsigned int flush_fifo:1; /* Drain the fifo when finishing */ ++ ++ unsigned int use_busy:1; /* Wait for busy interrupt */ ++ ++ u32 thread_isr; ++ ++ /*DMA part*/ ++ struct dma_chan *dma_chan_rx; /* DMA channel for reads */ ++ struct dma_chan *dma_chan_tx; /* DMA channel for writes */ ++ ++ bool allow_dma; ++ bool have_dma; ++ bool use_dma; ++ /*end of DMA part*/ ++ ++ int max_delay; /* maximum length of time spent waiting */ ++ struct timeval stop_time; /* when the last stop was issued */ ++ u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ ++ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ ++ u32 max_overclock; /* Highest reported */ ++}; ++ ++ ++static inline void bcm2835_sdhost_write(struct bcm2835_host *host, u32 val, int reg) ++{ ++ writel(val, host->ioaddr + reg); ++} ++ ++static inline u32 bcm2835_sdhost_read(struct bcm2835_host *host, int reg) ++{ ++ return readl(host->ioaddr + reg); ++} ++ ++static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg) ++{ ++ return readl_relaxed(host->ioaddr + reg); ++} ++ ++static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) ++{ ++ pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", ++ mmc_hostname(host->mmc)); ++ ++ pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", ++ bcm2835_sdhost_read(host, SDCMD)); ++ pr_info(DRIVER_NAME ": SDARG 0x%08x\n", ++ bcm2835_sdhost_read(host, SDARG)); ++ pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", ++ bcm2835_sdhost_read(host, SDTOUT)); ++ pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", ++ bcm2835_sdhost_read(host, SDCDIV)); ++ pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP0)); ++ pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP1)); ++ pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP2)); ++ pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", ++ bcm2835_sdhost_read(host, SDRSP3)); ++ pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHSTS)); ++ pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", ++ bcm2835_sdhost_read(host, SDVDD)); ++ pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", ++ bcm2835_sdhost_read(host, SDEDM)); ++ pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHCFG)); ++ pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHBCT)); ++ pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", ++ bcm2835_sdhost_read(host, SDHBLC)); ++ ++ pr_debug(DRIVER_NAME ": ===========================================\n"); ++} ++ ++ ++static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) ++{ ++ bcm2835_sdhost_write(host, on ? 1 : 0, SDVDD); ++} ++ ++ ++static void bcm2835_sdhost_reset(struct bcm2835_host *host) ++{ ++ u32 temp; ++ ++ pr_debug("bcm2835_sdhost_reset\n"); ++ ++ bcm2835_sdhost_set_power(host, false); ++ ++ bcm2835_sdhost_write(host, 0, SDCMD); ++ bcm2835_sdhost_write(host, 0, SDARG); ++ bcm2835_sdhost_write(host, 0xf00000, SDTOUT); ++ bcm2835_sdhost_write(host, 0, SDCDIV); ++ bcm2835_sdhost_write(host, 0x7f8, SDHSTS); /* Write 1s to clear */ ++ bcm2835_sdhost_write(host, 0, SDHCFG); ++ bcm2835_sdhost_write(host, 0, SDHBCT); ++ bcm2835_sdhost_write(host, 0, SDHBLC); ++ ++ /* Limit fifo usage due to silicon bug */ ++ temp = bcm2835_sdhost_read(host, SDEDM); ++ temp &= ~((SDEDM_THRESHOLD_MASK<clock = 0; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ mmiowb(); ++} ++ ++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); ++ ++static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) ++{ ++ pr_debug("bcm2835_sdhost_init(%d)\n", soft); ++ ++ /* Set interrupt enables */ ++ host->hcfg = SDHCFG_BUSY_IRPT_EN; ++ ++ bcm2835_sdhost_reset(host); ++ ++ if (soft) { ++ /* force clock reconfiguration */ ++ host->clock = 0; ++ bcm2835_sdhost_set_ios(host->mmc, &host->mmc->ios); ++ } ++} ++ ++static bool bcm2835_sdhost_is_write_complete(struct bcm2835_host *host) ++{ ++ bool write_complete = ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1); ++ ++ if (!write_complete) { ++ /* Request an IRQ for the last block */ ++ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ if ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1) { ++ /* The write has now completed. Disable the interrupt ++ and clear the status flag */ ++ host->hcfg &= ~SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ bcm2835_sdhost_write(host, SDHSTS_BLOCK_IRPT, SDHSTS); ++ write_complete = true; ++ } ++ } ++ ++ return write_complete; ++} ++ ++static void bcm2835_sdhost_wait_write_complete(struct bcm2835_host *host) ++{ ++ int timediff; ++#ifdef DEBUG ++ static struct timeval start_time; ++ static int max_stall_time = 0; ++ static int total_stall_time = 0; ++ struct timeval before, after; ++ ++ do_gettimeofday(&before); ++ if (max_stall_time == 0) ++ start_time = before; ++#endif ++ ++ timediff = 0; ++ ++ while (1) { ++ u32 edm = bcm2835_sdhost_read(host, SDEDM); ++ if ((edm & 0xf) == 1) ++ break; ++ timediff++; ++ if (timediff > 5000000) { ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + ++ (after.tv_usec - before.tv_usec); ++ ++ pr_err(" wait_write_complete - still waiting after %dus\n", ++ timediff); ++#else ++ pr_err(" wait_write_complete - still waiting after %d retries\n", ++ timediff); ++#endif ++ bcm2835_sdhost_dumpregs(host); ++ host->data->error = -ETIMEDOUT; ++ return; ++ } ++ } ++ ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + (after.tv_usec - before.tv_usec); ++ ++ total_stall_time += timediff; ++ if (timediff > max_stall_time) ++ max_stall_time = timediff; ++ ++ if ((after.tv_sec - start_time.tv_sec) > 10) { ++ pr_debug(" wait_write_complete - max wait %dus, total %dus\n", ++ max_stall_time, total_stall_time); ++ start_time = after; ++ max_stall_time = 0; ++ total_stall_time = 0; ++ } ++#endif ++} ++ ++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host); ++ ++static void bcm2835_sdhost_dma_complete(void *param) ++{ ++ struct bcm2835_host *host = param; ++ struct dma_chan *dma_chan; ++ unsigned long flags; ++ u32 dir_data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->data) { ++ bool write_complete; ++ if (USE_BLOCK_IRQ) ++ write_complete = bcm2835_sdhost_is_write_complete(host); ++ else { ++ bcm2835_sdhost_wait_write_complete(host); ++ write_complete = true; ++ } ++ pr_debug("dma_complete() - write_complete=%d\n", ++ write_complete); ++ ++ if (write_complete || (host->data->flags & MMC_DATA_READ)) ++ { ++ if (write_complete) { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ } else { ++ dma_chan = host->dma_chan_rx; ++ dir_data = DMA_FROM_DEVICE; ++ } ++ ++ dma_unmap_sg(dma_chan->device->dev, ++ host->data->sg, host->data->sg_len, ++ dir_data); ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) ++{ ++ unsigned long flags; ++ size_t blksize, len; ++ u32 *buf; ++ ++ blksize = host->data->blksz; ++ ++ local_irq_save(flags); ++ ++ while (blksize) { ++ if (!sg_miter_next(&host->sg_miter)) ++ BUG(); ++ ++ len = min(host->sg_miter.length, blksize); ++ BUG_ON(len % 4); ++ ++ blksize -= len; ++ host->sg_miter.consumed = len; ++ ++ buf = (u32 *)host->sg_miter.addr; ++ ++ while (len) { ++ while (1) { ++ u32 hsts; ++ hsts = bcm2835_sdhost_read(host, SDHSTS); ++ if (hsts & SDHSTS_DATA_FLAG) ++ break; ++ ++ if (hsts & SDHSTS_ERROR_MASK) { ++ pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", ++ mmc_hostname(host->mmc), ++ hsts, ++ bcm2835_sdhost_read(host, SDHBCT), ++ blksize + len); ++ if (hsts & SDHSTS_REW_TIME_OUT) ++ host->data->error = -ETIMEDOUT; ++ else if (hsts & (SDHSTS_CRC16_ERROR || ++ SDHSTS_CRC7_ERROR)) ++ host->data->error = -EILSEQ; ++ else { ++ pr_err("%s: unexpected data error\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ } ++ } ++ } ++ ++ *(buf++) = bcm2835_sdhost_read(host, SDDATA); ++ len -= 4; ++ } ++ } ++ ++ sg_miter_stop(&host->sg_miter); ++ ++ local_irq_restore(flags); ++} ++ ++static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) ++{ ++ unsigned long flags; ++ size_t blksize, len; ++ u32 *buf; ++ ++ blksize = host->data->blksz; ++ ++ local_irq_save(flags); ++ ++ while (blksize) { ++ if (!sg_miter_next(&host->sg_miter)) ++ BUG(); ++ ++ len = min(host->sg_miter.length, blksize); ++ BUG_ON(len % 4); ++ ++ blksize -= len; ++ host->sg_miter.consumed = len; ++ ++ buf = host->sg_miter.addr; ++ ++ while (len) { ++ while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) ++ continue; ++ bcm2835_sdhost_write(host, *(buf++), SDDATA); ++ len -= 4; ++ } ++ } ++ ++ sg_miter_stop(&host->sg_miter); ++ ++ local_irq_restore(flags); ++} ++ ++ ++static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) ++{ ++ BUG_ON(!host->data); ++ ++ if (host->data->flags & MMC_DATA_READ) ++ bcm2835_sdhost_read_block_pio(host); ++ else ++ bcm2835_sdhost_write_block_pio(host); ++} ++ ++ ++static void bcm2835_sdhost_transfer_dma(struct bcm2835_host *host) ++{ ++ u32 len, dir_data, dir_slave; ++ struct dma_async_tx_descriptor *desc = NULL; ++ struct dma_chan *dma_chan; ++ ++ pr_debug("bcm2835_sdhost_transfer_dma()\n"); ++ ++ WARN_ON(!host->data); ++ ++ if (!host->data) ++ return; ++ ++ if (host->data->flags & MMC_DATA_READ) { ++ dma_chan = host->dma_chan_rx; ++ dir_data = DMA_FROM_DEVICE; ++ dir_slave = DMA_DEV_TO_MEM; ++ } else { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ dir_slave = DMA_MEM_TO_DEV; ++ } ++ ++ BUG_ON(!dma_chan->device); ++ BUG_ON(!dma_chan->device->dev); ++ BUG_ON(!host->data->sg); ++ ++ len = dma_map_sg(dma_chan->device->dev, host->data->sg, ++ host->data->sg_len, dir_data); ++ if (len > 0) { ++ desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg, ++ len, dir_slave, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ } else { ++ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); ++ } ++ if (desc) { ++ desc->callback = bcm2835_sdhost_dma_complete; ++ desc->callback_param = host; ++ dmaengine_submit(desc); ++ dma_async_issue_pending(dma_chan); ++ } ++ ++} ++ ++ ++static void bcm2835_sdhost_set_transfer_irqs(struct bcm2835_host *host) ++{ ++ u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN | ++ SDHCFG_BUSY_IRPT_EN; ++ if (host->use_dma) ++ host->hcfg = (host->hcfg & ~all_irqs) | ++ SDHCFG_BUSY_IRPT_EN; ++ else ++ host->hcfg = (host->hcfg & ~all_irqs) | ++ SDHCFG_DATA_IRPT_EN | ++ SDHCFG_BUSY_IRPT_EN; ++ ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++} ++ ++ ++static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd) ++{ ++ struct mmc_data *data = cmd->data; ++ ++ WARN_ON(host->data); ++ ++ if (!data) ++ return; ++ ++ /* Sanity checks */ ++ BUG_ON(data->blksz * data->blocks > 524288); ++ BUG_ON(data->blksz > host->mmc->max_blk_size); ++ BUG_ON(data->blocks > 65535); ++ ++ host->data = data; ++ host->data_complete = 0; ++ host->flush_fifo = 0; ++ host->data->bytes_xfered = 0; ++ ++ if (!host->use_dma) { ++ int flags; ++ ++ flags = SG_MITER_ATOMIC; ++ if (data->flags & MMC_DATA_READ) ++ flags |= SG_MITER_TO_SG; ++ else ++ flags |= SG_MITER_FROM_SG; ++ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); ++ host->blocks = data->blocks; ++ } ++ ++ host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; ++ ++ bcm2835_sdhost_set_transfer_irqs(host); ++ ++ bcm2835_sdhost_write(host, data->blksz, SDHBCT); ++ if (host->use_dma) ++ bcm2835_sdhost_write(host, data->blocks, SDHBLC); ++ ++ BUG_ON(!host->data); ++} ++ ++ ++void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd) ++{ ++ u32 sdcmd; ++ unsigned long timeout; ++ ++ WARN_ON(host->cmd); ++ ++ if (1) { ++ pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", ++ cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); ++ if (cmd->data) ++ pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ } ++ ++ /* Wait max 10 ms */ ++ timeout = 1000; ++ ++ while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { ++ if (timeout == 0) { ++ pr_err("%s: Previous command never completed.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ timeout--; ++ udelay(10); ++ } ++ ++ if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { ++ host->max_delay = (1000-timeout)/100; ++ pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); ++ } ++ ++ timeout = jiffies; ++#ifdef CONFIG_ARCH_BCM2835 ++ if (!cmd->data && cmd->busy_timeout > 9000) ++ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; ++ else ++#endif ++ timeout += 10 * HZ; ++ mod_timer(&host->timer, timeout); ++ ++ host->cmd = cmd; ++ ++ bcm2835_sdhost_prepare_data(host, cmd); ++ ++ bcm2835_sdhost_write(host, cmd->arg, SDARG); ++ ++ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { ++ pr_err("%s: Unsupported response type!\n", ++ mmc_hostname(host->mmc)); ++ cmd->error = -EINVAL; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ sdcmd = cmd->opcode & SDCMD_CMD_MASK; ++ ++ if (!(cmd->flags & MMC_RSP_PRESENT)) ++ sdcmd |= SDCMD_NO_RESPONSE; ++ else { ++ if (cmd->flags & MMC_RSP_136) ++ sdcmd |= SDCMD_LONG_RESPONSE; ++ if (cmd->flags & MMC_RSP_BUSY) { ++ sdcmd |= SDCMD_BUSYWAIT; ++ host->use_busy = 1; ++ } ++ } ++ ++ if (cmd->data) { ++ if (host->delay_after_stop) { ++ struct timeval now; ++ int time_since_stop; ++ do_gettimeofday(&now); ++ time_since_stop = (now.tv_sec - host->stop_time.tv_sec); ++ if (time_since_stop < 2) { ++ /* Possibly less than one second */ ++ time_since_stop = time_since_stop * 1000000 + ++ (now.tv_usec - host->stop_time.tv_usec); ++ if (time_since_stop < host->delay_after_stop) ++ udelay(host->delay_after_stop - ++ time_since_stop); ++ } ++ } ++ ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ sdcmd |= SDCMD_WRITE_CMD; ++ if (cmd->data->flags & MMC_DATA_READ) ++ sdcmd |= SDCMD_READ_CMD; ++ } ++ ++ bcm2835_sdhost_write(host, sdcmd | SDCMD_NEW_FLAG, SDCMD); ++} ++ ++ ++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host); ++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host); ++ ++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host) ++{ ++ struct mmc_data *data; ++ ++ data = host->data; ++ BUG_ON(!data); ++ ++ pr_debug("finish_data(error %d, stop %d, sbc %d)\n", ++ data->error, data->stop ? 1 : 0, ++ host->mrq->sbc ? 1 : 0); ++ ++ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ ++ if (data->error) { ++ data->bytes_xfered = 0; ++ } else ++ data->bytes_xfered = data->blksz * data->blocks; ++ ++ host->data_complete = 1; ++ ++ if (host->cmd) { ++ /* ++ * Data managed to finish before the ++ * command completed. Make sure we do ++ * things in the proper order. ++ */ ++ pr_debug("Finished early - HSTS %x\n", ++ bcm2835_sdhost_read(host, SDHSTS)); ++ } ++ else ++ bcm2835_sdhost_transfer_complete(host); ++} ++ ++ ++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) ++{ ++ struct mmc_data *data; ++ ++ BUG_ON(host->cmd); ++ BUG_ON(!host->data); ++ BUG_ON(!host->data_complete); ++ ++ data = host->data; ++ host->data = NULL; ++ ++ pr_debug("transfer_complete(error %d, stop %d)\n", ++ data->error, data->stop ? 1 : 0); ++ ++ if (data->error) ++ /* ++ * The controller needs a reset of internal state machines ++ * upon error conditions. ++ */ ++ bcm2835_sdhost_reset(host); ++ ++ /* ++ * Need to send CMD12 if - ++ * a) open-ended multiblock transfer (no CMD23) ++ * b) error in multiblock transfer ++ */ ++ if (data->stop && ++ (data->error || ++ !host->mrq->sbc)) { ++ host->flush_fifo = 1; ++ bcm2835_sdhost_send_command(host, data->stop); ++ if (host->delay_after_stop) ++ do_gettimeofday(&host->stop_time); ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++ } else { ++ tasklet_schedule(&host->finish_tasklet); ++ } ++} ++ ++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) ++{ ++ u32 sdcmd; ++ int timeout = 1000; ++#ifdef DEBUG ++ struct timeval before, after; ++ int timediff = 0; ++#endif ++ ++ pr_debug("finish_command(%x)\n", bcm2835_sdhost_read(host, SDCMD)); ++ ++ BUG_ON(!host->cmd || !host->mrq); ++ ++#ifdef DEBUG ++ do_gettimeofday(&before); ++#endif ++ for (sdcmd = bcm2835_sdhost_read(host, SDCMD); ++ (sdcmd & SDCMD_NEW_FLAG) && timeout; ++ timeout--) { ++ if (host->flush_fifo) { ++ while (bcm2835_sdhost_read(host, SDHSTS) & ++ SDHSTS_DATA_FLAG) ++ (void)bcm2835_sdhost_read(host, SDDATA); ++ } ++ udelay(10); ++ sdcmd = bcm2835_sdhost_read(host, SDCMD); ++ } ++#ifdef DEBUG ++ do_gettimeofday(&after); ++ timediff = (after.tv_sec - before.tv_sec)*1000000 + ++ (after.tv_usec - before.tv_usec); ++ ++ pr_debug(" finish_command - waited %dus\n", timediff); ++#endif ++ ++ if (timeout == 0) { ++ pr_err("%s: Command never completed.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ if (host->flush_fifo) { ++ for (timeout = 100; ++ (bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG) && timeout; ++ timeout--) { ++ (void)bcm2835_sdhost_read(host, SDDATA); ++ } ++ host->flush_fifo = 0; ++ if (timeout == 0) { ++ pr_err("%s: FIFO never drained.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ } ++ ++ /* Check for errors */ ++ if (sdcmd & SDCMD_FAIL_FLAG) ++ { ++ u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); ++ ++ pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", ++ mmc_hostname(host->mmc), sdcmd, sdhsts, ++ bcm2835_sdhost_read(host, SDEDM)); ++ ++ if (sdhsts & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else ++ { ++ pr_err("%s: unexpected command error\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ host->cmd->error = -EIO; ++ } ++ tasklet_schedule(&host->finish_tasklet); ++ return; ++ } ++ ++ if (host->cmd->flags & MMC_RSP_PRESENT) { ++ if (host->cmd->flags & MMC_RSP_136) { ++ int i; ++ for (i = 0; i < 4; i++) ++ host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); ++ pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", ++ host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); ++ } else { ++ host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); ++ pr_debug("bcm2835_sdhost_finish_command: %08x\n", ++ host->cmd->resp[0]); ++ } ++ } ++ ++ host->cmd->error = 0; ++ ++ if (host->cmd == host->mrq->sbc) { ++ /* Finished CMD23, now send actual command. */ ++ host->cmd = NULL; ++ bcm2835_sdhost_send_command(host, host->mrq->cmd); ++ ++ if (host->cmd->data && host->use_dma) ++ /* DMA transfer starts now, PIO starts after irq */ ++ bcm2835_sdhost_transfer_dma(host); ++ ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++ } else if (host->cmd == host->mrq->stop) ++ /* Finished CMD12 */ ++ tasklet_schedule(&host->finish_tasklet); ++ else { ++ /* Processed actual command. */ ++ host->cmd = NULL; ++ if (!host->data) ++ tasklet_schedule(&host->finish_tasklet); ++ else if (host->data_complete) ++ bcm2835_sdhost_transfer_complete(host); ++ } ++} ++ ++static void bcm2835_sdhost_timeout_timer(unsigned long data) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ host = (struct bcm2835_host *)data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->mrq) { ++ pr_err("%s: Timeout waiting for hardware interrupt.\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ ++ if (host->data) { ++ host->data->error = -ETIMEDOUT; ++ bcm2835_sdhost_finish_data(host); ++ } else { ++ if (host->cmd) ++ host->cmd->error = -ETIMEDOUT; ++ else ++ host->mrq->cmd->error = -ETIMEDOUT; ++ ++ pr_debug("timeout_timer tasklet_schedule\n"); ++ tasklet_schedule(&host->finish_tasklet); ++ } ++ } ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) ++{ ++ if (enable) ++ host->hcfg |= SDHCFG_SDIO_IRPT_EN; ++ else ++ host->hcfg &= ~SDHCFG_SDIO_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ mmiowb(); ++} ++ ++static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ ++ pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); ++ spin_lock_irqsave(&host->lock, flags); ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ if (!host->cmd) { ++ pr_err("%s: Got command busy interrupt 0x%08x even " ++ "though no command operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return 0; ++ } ++ ++ if (!host->use_busy) { ++ pr_err("%s: Got command busy interrupt 0x%08x even " ++ "though not expecting one.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return 0; ++ } ++ host->use_busy = 0; ++ ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->cmd->error = -EILSEQ; ++ ++ if (host->cmd->error) ++ tasklet_schedule(&host->finish_tasklet); ++ else ++ bcm2835_sdhost_finish_command(host); ++ ++ return handled; ++} ++ ++static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ /* There are no dedicated data/space available interrupt ++ status bits, so it is necessary to use the single shared ++ data/space available FIFO status bits. It is therefore not ++ an error to get here when there is no data transfer in ++ progress. */ ++ if (!host->data) ++ return 0; ++ ++ // XXX FIFO_ERROR ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && ++ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) ++ != MMC_BUS_TEST_R)) ++ host->cmd->error = -EILSEQ; ++ ++ /* Use the block interrupt for writes after the first block */ ++ if (host->data->flags & MMC_DATA_WRITE) { ++ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); ++ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ if (host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ else ++ bcm2835_sdhost_transfer_pio(host); ++ } else { ++ if (!host->data->error) { ++ bcm2835_sdhost_transfer_pio(host); ++ host->blocks--; ++ } ++ if ((host->blocks == 0) || host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ return handled; ++} ++ ++static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) ++{ ++ struct dma_chan *dma_chan; ++ u32 dir_data; ++ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ ++ if (!host->data) { ++ pr_err("%s: Got block interrupt 0x%08x even " ++ "though no data operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ bcm2835_sdhost_dumpregs(host); ++ return handled; ++ } ++ ++ if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; ++ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && ++ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) ++ != MMC_BUS_TEST_R)) ++ host->cmd->error = -EILSEQ; ++ ++ if (!host->use_dma) { ++ BUG_ON(!host->blocks); ++ host->blocks--; ++ if ((host->blocks == 0) || host->data->error) ++ bcm2835_sdhost_finish_data(host); ++ else ++ bcm2835_sdhost_transfer_pio(host); ++ } else if (host->data->flags & MMC_DATA_WRITE) { ++ dma_chan = host->dma_chan_tx; ++ dir_data = DMA_TO_DEVICE; ++ dma_unmap_sg(dma_chan->device->dev, ++ host->data->sg, host->data->sg_len, ++ dir_data); ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ return handled; ++} ++ ++ ++static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) ++{ ++ irqreturn_t result = IRQ_NONE; ++ struct bcm2835_host *host = dev_id; ++ u32 unexpected = 0, early = 0; ++ int loops = 0; ++#ifndef CONFIG_ARCH_BCM2835 ++ int cardint = 0; ++#endif ++ spin_lock(&host->lock); ++ ++ for (loops = 0; loops < 1; loops++) { ++ u32 intmask, handled; ++ ++ intmask = bcm2835_sdhost_read(host, SDHSTS); ++ handled = intmask & (SDHSTS_BUSY_IRPT | ++ SDHSTS_BLOCK_IRPT | ++ SDHSTS_SDIO_IRPT | ++ SDHSTS_DATA_FLAG); ++ if ((handled == SDHSTS_DATA_FLAG) && // XXX ++ (loops == 0) && !host->data) { ++ pr_err("%s: sdhost_irq data interrupt 0x%08x even " ++ "though no data operation was in progress.\n", ++ mmc_hostname(host->mmc), ++ (unsigned)intmask); ++ ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++ if (!handled) ++ break; ++ ++ if (loops) ++ early |= handled; ++ ++ result = IRQ_HANDLED; ++ ++ /* Clear all interrupts and notifications */ ++ bcm2835_sdhost_write(host, intmask, SDHSTS); ++ ++ if (intmask & SDHSTS_BUSY_IRPT) ++ handled |= bcm2835_sdhost_busy_irq(host, intmask); ++ ++ /* There is no true data interrupt status bit, so it is ++ necessary to qualify the data flag with the interrupt ++ enable bit */ ++ if ((intmask & SDHSTS_DATA_FLAG) && ++ (host->hcfg & SDHCFG_DATA_IRPT_EN)) ++ handled |= bcm2835_sdhost_data_irq(host, intmask); ++ ++ if (intmask & SDHSTS_BLOCK_IRPT) ++ handled |= bcm2835_sdhost_block_irq(host, intmask); ++ ++ if (intmask & SDHSTS_SDIO_IRPT) { ++#ifndef CONFIG_ARCH_BCM2835 ++ cardint = 1; ++#else ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, false); ++ host->thread_isr |= SDHSTS_SDIO_IRPT; ++ result = IRQ_WAKE_THREAD; ++#endif ++ } ++ ++ unexpected |= (intmask & ~handled); ++ } ++ ++ mmiowb(); ++ ++ spin_unlock(&host->lock); ++ ++ if (early) ++ pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); ++ ++ if (unexpected) { ++ pr_err("%s: Unexpected interrupt 0x%08x.\n", ++ mmc_hostname(host->mmc), unexpected); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++#ifndef CONFIG_ARCH_BCM2835 ++ if (cardint) ++ mmc_signal_sdio_irq(host->mmc); ++#endif ++ ++ return result; ++} ++ ++#ifdef CONFIG_ARCH_BCM2835 ++static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) ++{ ++ struct bcm2835_host *host = dev_id; ++ unsigned long flags; ++ u32 isr; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ isr = host->thread_isr; ++ host->thread_isr = 0; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (isr & SDHSTS_SDIO_IRPT) { ++ sdio_run_irqs(host->mmc); ++ ++/* Is this necessary? Why re-enable an interrupt which is enabled? ++ spin_lock_irqsave(&host->lock, flags); ++ if (host->flags & SDHSTS_SDIO_IRPT_ENABLED) ++ bcm2835_sdhost_enable_sdio_irq_nolock(host, true); ++ spin_unlock_irqrestore(&host->lock, flags); ++*/ ++ } ++ ++ return isr ? IRQ_HANDLED : IRQ_NONE; ++} ++#endif ++ ++ ++ ++void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) ++{ ++ int div = 0; /* Initialized for compiler warning */ ++ unsigned int input_clock = clock; ++ ++ if (host->overclock_50 && (clock == 50000000)) ++ clock = host->overclock_50 * 1000000 + 999999; ++ ++ /* The SDCDIV register has 11 bits, and holds (div - 2). ++ But in data mode the max is 50MHz wihout a minimum, and only the ++ bottom 3 bits are used. Since the switch over is automatic (unless ++ we have marked the card as slow...), chosen values have to make ++ sense in both modes. ++ Ident mode must be 100-400KHz, so can range check the requested ++ clock. CMD15 must be used to return to data mode, so this can be ++ monitored. ++ ++ clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz ++ 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz ++ ++ 623->400KHz/27.8MHz ++ reset value (507)->491159/50MHz ++ ++ BUT, the 3-bit clock divisor in data mode is too small if the ++ core clock is higher than 250MHz, so instead use the SLOW_CARD ++ configuration bit to force the use of the ident clock divisor ++ at all times. ++ */ ++ ++ host->mmc->actual_clock = 0; ++ ++ if (clock < 100000) { ++ /* Can't stop the clock, but make it as slow as possible ++ * to show willing ++ */ ++ host->cdiv = SDCDIV_MAX_CDIV; ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ return; ++ } ++ ++ div = host->max_clk / clock; ++ if (div < 2) ++ div = 2; ++ if ((host->max_clk / div) > clock) ++ div++; ++ div -= 2; ++ ++ if (div > SDCDIV_MAX_CDIV) ++ div = SDCDIV_MAX_CDIV; ++ ++ clock = host->max_clk / (div + 2); ++ host->mmc->actual_clock = clock; ++ ++ if ((clock > input_clock) && (clock > host->max_overclock)) { ++ pr_warn("%s: Overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->max_overclock = clock; ++ } ++ ++ host->cdiv = div; ++ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); ++ ++ pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", ++ input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); ++} ++ ++static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ if (1) { ++ struct mmc_command *cmd = mrq->cmd; ++ const char *src = "cmd"; ++ BUG_ON(!cmd); ++ pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", ++ src, cmd->opcode, cmd->arg, cmd->flags); ++ if (cmd->data) ++ pr_debug("bcm2835_sdhost_request: %s %d*%d\n", ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ } ++ ++ if (mrq->data && !is_power_of_2(mrq->data->blksz)) { ++ pr_err("%s: Unsupported block size (%d bytes)\n", ++ mmc_hostname(mmc), mrq->data->blksz); ++ mrq->cmd->error = -EINVAL; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ host = mmc_priv(mmc); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ WARN_ON(host->mrq != NULL); ++ ++ host->mrq = mrq; ++ ++ if (mrq->sbc) ++ bcm2835_sdhost_send_command(host, mrq->sbc); ++ else ++ bcm2835_sdhost_send_command(host, mrq->cmd); ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (!mrq->sbc && mrq->cmd->data && host->use_dma) ++ /* DMA transfer starts now, PIO starts after irq */ ++ bcm2835_sdhost_transfer_dma(host); ++ ++ if (!host->use_busy) ++ bcm2835_sdhost_finish_command(host); ++} ++ ++ ++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ ++ pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (!ios->clock || ios->clock != host->clock) { ++ bcm2835_sdhost_set_clock(host, ios->clock); ++ host->clock = ios->clock; ++ } ++ ++ /* set bus width */ ++ host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; ++ if (ios->bus_width == MMC_BUS_WIDTH_4) ++ host->hcfg |= SDHCFG_WIDE_EXT_BUS; ++ ++ host->hcfg |= SDHCFG_WIDE_INT_BUS; ++ ++ /* Disable clever clock switching, to cope with fast core clocks */ ++ host->hcfg |= SDHCFG_SLOW_CARD; ++ ++ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); ++ ++ mmiowb(); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static int bcm2835_sdhost_multi_io_quirk(struct mmc_card *card, ++ unsigned int direction, ++ u32 blk_pos, int blk_size) ++{ ++ /* There is a bug in the host controller hardware that makes ++ reading the final sector of the card as part of a multiple read ++ problematic. Detect that case and shorten the read accordingly. ++ */ ++ /* csd.capacity is in weird units - convert to sectors */ ++ u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9)); ++ ++ if ((direction == MMC_DATA_READ) && ++ ((blk_pos + blk_size) == card_sectors)) ++ blk_size--; ++ ++ return blk_size; ++} ++ ++ ++static struct mmc_host_ops bcm2835_sdhost_ops = { ++ .request = bcm2835_sdhost_request, ++ .set_ios = bcm2835_sdhost_set_ios, ++ .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, ++ .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, ++}; ++ ++ ++static void bcm2835_sdhost_tasklet_finish(unsigned long param) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ struct mmc_request *mrq; ++ ++ host = (struct bcm2835_host *)param; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ /* ++ * If this tasklet gets rescheduled while running, it will ++ * be run again afterwards but without any active request. ++ */ ++ if (!host->mrq) { ++ spin_unlock_irqrestore(&host->lock, flags); ++ return; ++ } ++ ++ del_timer(&host->timer); ++ ++ mrq = host->mrq; ++ ++ /* ++ * The controller needs a reset of internal state machines ++ * upon error conditions. ++ */ ++ if (((mrq->cmd && mrq->cmd->error) || ++ (mrq->data && (mrq->data->error || ++ (mrq->data->stop && mrq->data->stop->error))))) { ++ ++ bcm2835_sdhost_reset(host); ++ } ++ ++ host->mrq = NULL; ++ host->cmd = NULL; ++ host->data = NULL; ++ ++ mmiowb(); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ mmc_request_done(host->mmc, mrq); ++} ++ ++ ++ ++int bcm2835_sdhost_add_host(struct bcm2835_host *host) ++{ ++ struct mmc_host *mmc; ++ struct dma_slave_config cfg; ++ int ret; ++ ++ mmc = host->mmc; ++ ++ bcm2835_sdhost_reset(host); ++ ++ mmc->f_max = host->max_clk; ++ mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; ++ ++ /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ ++ host->timeout_clk = mmc->f_max / 1000; ++#ifdef CONFIG_ARCH_BCM2835 ++ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; ++#endif ++ /* host controller capabilities */ ++ mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | ++ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | ++ MMC_CAP_NEEDS_POLL | ++ (ALLOW_CMD23 * MMC_CAP_CMD23); ++ ++ spin_lock_init(&host->lock); ++ ++ if (host->allow_dma) { ++ if (!host->dma_chan_tx || !host->dma_chan_rx || ++ IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { ++ pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); ++ host->have_dma = false; ++ } else { ++ pr_info("DMA channels allocated for the SDHost driver"); ++ host->have_dma = true; ++ ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.slave_id = 13; /* DREQ channel */ ++ ++ cfg.direction = DMA_MEM_TO_DEV; ++ cfg.src_addr = 0; ++ cfg.dst_addr = host->phys_addr + SDDATA; ++ ret = dmaengine_slave_config(host->dma_chan_tx, &cfg); ++ ++ cfg.direction = DMA_DEV_TO_MEM; ++ cfg.src_addr = host->phys_addr + SDDATA; ++ cfg.dst_addr = 0; ++ ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); ++ } ++ } else { ++ pr_info("Forcing PIO mode\n"); ++ host->have_dma = false; ++ } ++ ++ mmc->max_segs = 128; ++ mmc->max_req_size = 524288; ++ mmc->max_seg_size = mmc->max_req_size; ++ mmc->max_blk_size = 512; ++ mmc->max_blk_count = 65535; ++ ++ /* report supported voltage ranges */ ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ tasklet_init(&host->finish_tasklet, ++ bcm2835_sdhost_tasklet_finish, (unsigned long)host); ++ ++ setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); ++ ++ bcm2835_sdhost_init(host, 0); ++#ifndef CONFIG_ARCH_BCM2835 ++ ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, ++ mmc_hostname(mmc), host); ++#else ++ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, ++ IRQF_SHARED, mmc_hostname(mmc), host); ++#endif ++ if (ret) { ++ pr_err("%s: Failed to request IRQ %d: %d\n", ++ mmc_hostname(mmc), host->irq, ret); ++ goto untasklet; ++ } ++ ++ mmiowb(); ++ mmc_add_host(mmc); ++ ++ pr_info("Load BCM2835 SDHost driver\n"); ++ if (host->delay_after_stop) ++ pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", ++ host->delay_after_stop); ++ ++ return 0; ++ ++untasklet: ++ tasklet_kill(&host->finish_tasklet); ++ ++ return ret; ++} ++ ++static int bcm2835_sdhost_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct clk *clk; ++ struct resource *iomem; ++ struct bcm2835_host *host; ++ struct mmc_host *mmc; ++ int ret; ++ ++ pr_debug("bcm2835_sdhost_probe\n"); ++ mmc = mmc_alloc_host(sizeof(*host), dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ mmc->ops = &bcm2835_sdhost_ops; ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ host->timeout = msecs_to_jiffies(1000); ++ spin_lock_init(&host->lock); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ host->ioaddr = devm_ioremap_resource(dev, iomem); ++ if (IS_ERR(host->ioaddr)) { ++ ret = PTR_ERR(host->ioaddr); ++ goto err; ++ } ++ ++ host->phys_addr = iomem->start + BCM2835_VCMMU_SHIFT; ++ pr_debug(" - ioaddr %lx, iomem->start %lx, phys_addr %lx\n", ++ (unsigned long)host->ioaddr, ++ (unsigned long)iomem->start, ++ (unsigned long)host->phys_addr); ++ ++ host->allow_dma = ALLOW_DMA; ++ ++ if (node) { ++ /* Read any custom properties */ ++ of_property_read_u32(node, ++ "brcm,delay-after-stop", ++ &host->delay_after_stop); ++ of_property_read_u32(node, ++ "brcm,overclock-50", ++ &host->overclock_50); ++ host->allow_dma = ALLOW_DMA && ++ !of_property_read_bool(node, "brcm,force-pio"); ++ } ++ ++ if (host->allow_dma) { ++ if (node) { ++ host->dma_chan_tx = ++ dma_request_slave_channel(dev, "tx"); ++ host->dma_chan_rx = ++ dma_request_slave_channel(dev, "rx"); ++ } else { ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ /* we don't care about the channel, any would work */ ++ dma_cap_set(DMA_SLAVE, mask); ++ host->dma_chan_tx = ++ dma_request_channel(mask, NULL, NULL); ++ host->dma_chan_rx = ++ dma_request_channel(mask, NULL, NULL); ++ } ++ } ++ ++ clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(dev, "could not get clk\n"); ++ ret = PTR_ERR(clk); ++ goto err; ++ } ++ ++ host->max_clk = clk_get_rate(clk); ++ ++ host->irq = platform_get_irq(pdev, 0); ++ if (host->irq <= 0) { ++ dev_err(dev, "get IRQ failed\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ pr_debug(" - max_clk %lx, irq %d\n", ++ (unsigned long)host->max_clk, ++ (int)host->irq); ++ ++ if (node) ++ mmc_of_parse(mmc); ++ else ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ ++ ret = bcm2835_sdhost_add_host(host); ++ if (ret) ++ goto err; ++ ++ platform_set_drvdata(pdev, host); ++ ++ pr_debug("bcm2835_sdhost_probe -> OK\n"); ++ ++ return 0; ++ ++err: ++ pr_debug("bcm2835_sdhost_probe -> err %d\n", ret); ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++static int bcm2835_sdhost_remove(struct platform_device *pdev) ++{ ++ struct bcm2835_host *host = platform_get_drvdata(pdev); ++ ++ pr_debug("bcm2835_sdhost_remove\n"); ++ ++ mmc_remove_host(host->mmc); ++ ++ bcm2835_sdhost_set_power(host, false); ++ ++ free_irq(host->irq, host); ++ ++ del_timer_sync(&host->timer); ++ ++ tasklet_kill(&host->finish_tasklet); ++ ++ mmc_free_host(host->mmc); ++ platform_set_drvdata(pdev, NULL); ++ ++ pr_debug("bcm2835_sdhost_remove - OK\n"); ++ return 0; ++} ++ ++ ++static const struct of_device_id bcm2835_sdhost_match[] = { ++ { .compatible = "brcm,bcm2835-sdhost" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_sdhost_match); ++ ++ ++ ++static struct platform_driver bcm2835_sdhost_driver = { ++ .probe = bcm2835_sdhost_probe, ++ .remove = bcm2835_sdhost_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2835_sdhost_match, ++ }, ++}; ++module_platform_driver(bcm2835_sdhost_driver); ++ ++MODULE_ALIAS("platform:sdhost-bcm2835"); ++MODULE_DESCRIPTION("BCM2835 SDHost driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Phil Elwell"); + +From 34fb9ba0190b9f9e18e6c136c64af8dcea23376d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 009/216] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 11/77] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix @@ -80985,12 +80479,15 @@ index 0000000..5325832 + +#endif /* VC_CMA_H */ -From 6bafd180b5b7672ebbaea3878e78511d309007a0 Mon Sep 17 00:00:00 2001 +From 0e6896e85bf10d584b555ecae4b55f066a774b54 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 010/216] bcm2708: alsa sound driver +Subject: [PATCH 12/77] bcm2708: alsa sound driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit - Signed-off-by: popcornmix +Signed-off-by: popcornmix alsa: add mmap support and some cleanups to bcm2835 ALSA driver @@ -81014,33 +80511,41 @@ snd-bcm2708: Fix dmesg spam for non-error case alsa: Ensure mutexes are released through error paths alsa: Make interrupted close paths quieter + +BCM270x: Add onboard sound device to Device Tree + +Add Device Tree support to alsa driver. +Add device to Device Tree. +Don't add platform devices when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/bcm2708.c | 54 +++ - sound/arm/Kconfig | 7 + + arch/arm/mach-bcm2708/bcm2708.c | 53 +++ + arch/arm/mach-bcm2709/bcm2709.c | 53 +++ + sound/arm/Kconfig | 8 + sound/arm/Makefile | 5 + sound/arm/bcm2835-ctl.c | 323 +++++++++++++ sound/arm/bcm2835-pcm.c | 557 +++++++++++++++++++++++ sound/arm/bcm2835-vchiq.c | 902 +++++++++++++++++++++++++++++++++++++ - sound/arm/bcm2835.c | 420 +++++++++++++++++ + sound/arm/bcm2835.c | 511 +++++++++++++++++++++ sound/arm/bcm2835.h | 167 +++++++ sound/arm/vc_vchi_audioserv_defs.h | 116 +++++ - 9 files changed, 2551 insertions(+) + 10 files changed, 2695 insertions(+) create mode 100755 sound/arm/bcm2835-ctl.c create mode 100755 sound/arm/bcm2835-pcm.c create mode 100755 sound/arm/bcm2835-vchiq.c - create mode 100755 sound/arm/bcm2835.c + create mode 100644 sound/arm/bcm2835.c create mode 100755 sound/arm/bcm2835.h create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d1308ed..f54e3e9b 100644 +index 5b10802..06271df 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -447,6 +447,58 @@ struct platform_device bcm2708_powerman_device = { - .coherent_dma_mask = 0xffffffffUL}, +@@ -429,6 +429,57 @@ struct platform_device bcm2835_emmc_device = { }; + #endif /* CONFIG_MMC_BCM2835 */ -+ +static struct platform_device bcm2708_alsa_devices[] = { + [0] = { + .name = "bcm2835_AUD0", @@ -81095,26 +80600,98 @@ index d1308ed..f54e3e9b 100644 int __init bcm_register_device(struct platform_device *pdev) { int ret; -@@ -556,6 +608,8 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2835_emmc_device); +@@ -571,6 +622,8 @@ void __init bcm2708_init(void) #endif bcm2708_init_led(); + bcm2708_init_uart1(); + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -+ bcm_register_device(&bcm2708_alsa_devices[i]); ++ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 54c5444..0f875ff 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -449,6 +449,57 @@ struct platform_device bcm2835_emmc_device = { + }; + #endif /* CONFIG_MMC_BCM2835 */ + ++static struct platform_device bcm2708_alsa_devices[] = { ++ [0] = { ++ .name = "bcm2835_AUD0", ++ .id = 0, /* first audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [1] = { ++ .name = "bcm2835_AUD1", ++ .id = 1, /* second audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [2] = { ++ .name = "bcm2835_AUD2", ++ .id = 2, /* third audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [3] = { ++ .name = "bcm2835_AUD3", ++ .id = 3, /* forth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [4] = { ++ .name = "bcm2835_AUD4", ++ .id = 4, /* fifth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [5] = { ++ .name = "bcm2835_AUD5", ++ .id = 5, /* sixth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [6] = { ++ .name = "bcm2835_AUD6", ++ .id = 6, /* seventh audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++ [7] = { ++ .name = "bcm2835_AUD7", ++ .id = 7, /* eighth audio device */ ++ .resource = 0, ++ .num_resources = 0, ++ }, ++}; ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -591,6 +642,8 @@ void __init bcm2709_init(void) + #endif + bcm2709_init_led(); + bcm2709_init_uart1(); ++ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) ++ bcm_register_device_dt(&bcm2708_alsa_devices[i]); + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 885683a..ada7ba2 100644 +index 885683a..fcbe9d7 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig -@@ -39,5 +39,12 @@ config SND_PXA2XX_AC97 +@@ -39,5 +39,13 @@ config SND_PXA2XX_AC97 Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. +config SND_BCM2835 + tristate "BCM2835 ALSA driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709) && BCM2708_VCHIQ && SND ++ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ ++ && BCM2708_VCHIQ && SND + select SND_PCM + help + Say Y or M if you want to support BCM2835 Alsa pcm card driver @@ -82935,11 +82512,11 @@ index 0000000..3de3094 +module_param(force_bulk, bool, 0444); +MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio"); diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c -new file mode 100755 -index 0000000..7ed5079 +new file mode 100644 +index 0000000..6b545e7 --- /dev/null +++ b/sound/arm/bcm2835.c -@@ -0,0 +1,420 @@ +@@ -0,0 +1,511 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -82959,6 +82536,7 @@ index 0000000..7ed5079 +#include +#include +#include ++#include + +#include "bcm2835.h" + @@ -83023,6 +82601,86 @@ index 0000000..7ed5079 + return 0; +} + ++static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ bcm2835_chip_t *chip; ++ struct snd_card *card; ++ u32 numchans; ++ int err, i; ++ ++ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", ++ &numchans); ++ if (err) { ++ dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); ++ return err; ++ } ++ ++ if (numchans == 0 || numchans > MAX_SUBSTREAMS) { ++ numchans = MAX_SUBSTREAMS; ++ dev_warn(dev, "Illegal 'brcm,pwm-channels' value, will use %u\n", ++ numchans); ++ } ++ ++ err = snd_card_new(NULL, -1, NULL, THIS_MODULE, 0, &card); ++ if (err) { ++ dev_err(dev, "Failed to create soundcard structure\n"); ++ return err; ++ } ++ ++ snd_card_set_dev(card, dev); ++ strcpy(card->driver, "bcm2835"); ++ strcpy(card->shortname, "bcm2835 ALSA"); ++ sprintf(card->longname, "%s", card->shortname); ++ ++ err = snd_bcm2835_create(card, pdev, &chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create bcm2835 chip\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_pcm(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 pcm device\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_spdif_pcm(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 spdif pcm device\n"); ++ goto err_free; ++ } ++ ++ err = snd_bcm2835_new_ctl(chip); ++ if (err < 0) { ++ dev_err(dev, "Failed to create new bcm2835 ctl\n"); ++ goto err_free; ++ } ++ ++ for (i = 0; i < numchans; i++) { ++ chip->avail_substreams |= (1 << i); ++ chip->pdev[i] = pdev; ++ } ++ ++ err = snd_card_register(card); ++ if (err) { ++ dev_err(dev, "Failed to register bcm2835 ALSA card \n"); ++ goto err_free; ++ } ++ ++ g_card = card; ++ g_chip = chip; ++ platform_set_drvdata(pdev, card); ++ audio_info("bcm2835 ALSA card created with %u channels\n", numchans); ++ ++ return 0; ++ ++err_free: ++ snd_card_free(card); ++ ++ return err; ++} ++ +static int snd_bcm2835_alsa_probe(struct platform_device *pdev) +{ + static int dev; @@ -83030,6 +82688,9 @@ index 0000000..7ed5079 + struct snd_card *card; + int err; + ++ if (pdev->dev.of_node) ++ return snd_bcm2835_alsa_probe_dt(pdev); ++ + if (dev >= MAX_SUBSTREAMS) + return -ENODEV; + @@ -83166,6 +82827,12 @@ index 0000000..7ed5079 + +#endif + ++static const struct of_device_id snd_bcm2835_of_match_table[] = { ++ { .compatible = "brcm,bcm2835-audio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); ++ +static struct platform_driver bcm2835_alsa0_driver = { + .probe = snd_bcm2835_alsa_probe, + .remove = snd_bcm2835_alsa_remove, @@ -83176,6 +82843,7 @@ index 0000000..7ed5079 + .driver = { + .name = "bcm2835_AUD0", + .owner = THIS_MODULE, ++ .of_match_table = snd_bcm2835_of_match_table, + }, +}; + @@ -83656,10 +83324,13 @@ index 0000000..af3e6eb + +#endif // _VC_AUDIO_DEFS_H_ -From ddf7318165c6faf5bc73597105a2eed9fece4225 Mon Sep 17 00:00:00 2001 +From b2b5ab24c875e79e1fbb55ae76dc5a914fe301d0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 011/216] bcm2708 vchiq driver +Subject: [PATCH 13/77] bcm2708 vchiq driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix @@ -83727,7 +83398,30 @@ vchiq: Fix wrong condition check The log level is checked from within the log call. Remove the check in the call. Signed-off-by: Pranith Kumar + +BCM270x: Add vchiq device to platform file and Device Tree + +Prepare to turn the vchiq module into a driver. + +Signed-off-by: Noralf Trønnes + +bcm2708: vchiq: Add Device Tree support + +Turn vchiq into a driver and stop hardcoding resources. +Use devm_* functions in probe path to simplify cleanup. +A global variable is used to hold the register address. This is done +to keep this patch as small as possible. +Also make available on ARCH_BCM2835. +Based on work by Lubomir Rintel. + +Signed-off-by: Noralf Trønnes + +vchiq: Change logging level for inbound data --- + arch/arm/mach-bcm2708/bcm2708.c | 26 + + arch/arm/mach-bcm2708/include/mach/platform.h | 2 + + arch/arm/mach-bcm2709/bcm2709.c | 26 + + arch/arm/mach-bcm2709/include/mach/platform.h | 2 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/vc04_services/Kconfig | 9 + @@ -83741,9 +83435,9 @@ Signed-off-by: Pranith Kumar .../misc/vc04_services/interface/vchi/vchi_mh.h | 42 + .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + - .../interface/vchiq_arm/vchiq_2835_arm.c | 562 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2884 ++++++++++++++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 223 ++ + .../interface/vchiq_arm/vchiq_2835_arm.c | 547 +++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2886 ++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ .../interface/vchiq_arm/vchiq_build_info.h | 37 + .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + .../interface/vchiq_arm/vchiq_connected.c | 120 + @@ -83763,7 +83457,7 @@ Signed-off-by: Pranith Kumar .../vc04_services/interface/vchiq_arm/vchiq_util.c | 152 + .../vc04_services/interface/vchiq_arm/vchiq_util.h | 81 + .../interface/vchiq_arm/vchiq_version.c | 59 + - 35 files changed, 12770 insertions(+) + 39 files changed, 12810 insertions(+) create mode 100644 drivers/misc/vc04_services/Kconfig create mode 100644 drivers/misc/vc04_services/Makefile create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -83798,6 +83492,120 @@ Signed-off-by: Pranith Kumar create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 06271df..86011af 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -376,6 +376,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++static struct resource bcm2708_vchiq_resources[] = { ++ { ++ .start = ARMCTRL_0_BELL_BASE, ++ .end = ARMCTRL_0_BELL_BASE + 16, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_DOORBELL_0, ++ .end = IRQ_ARM_DOORBELL_0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vchiq_device = { ++ .name = "bcm2835_vchiq", ++ .id = -1, ++ .resource = bcm2708_vchiq_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), ++ .dev = { ++ .dma_mask = &vchiq_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + #ifdef CONFIG_BCM2708_GPIO + #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +@@ -611,6 +636,7 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif +diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h +index 2e7e1bb..69674e9 100644 +--- a/arch/arm/mach-bcm2708/include/mach/platform.h ++++ b/arch/arm/mach-bcm2708/include/mach/platform.h +@@ -81,6 +81,8 @@ + #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ + #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ + #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ ++#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + + /* +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 0f875ff..bc1ee1c 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -396,6 +396,31 @@ static struct platform_device bcm2708_vcio_device = { + }, + }; + ++static struct resource bcm2708_vchiq_resources[] = { ++ { ++ .start = ARMCTRL_0_BELL_BASE, ++ .end = ARMCTRL_0_BELL_BASE + 16, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_ARM_DOORBELL_0, ++ .end = IRQ_ARM_DOORBELL_0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vchiq_device = { ++ .name = "bcm2835_vchiq", ++ .id = -1, ++ .resource = bcm2708_vchiq_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), ++ .dev = { ++ .dma_mask = &vchiq_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + #ifdef CONFIG_BCM2708_GPIO + #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +@@ -631,6 +656,7 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif +diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h +index 7157f38..be99733 100644 +--- a/arch/arm/mach-bcm2709/include/mach/platform.h ++++ b/arch/arm/mach-bcm2709/include/mach/platform.h +@@ -81,6 +81,8 @@ + #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ + #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ + #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ ++#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + + /* diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 006242c..4e6f46c3 100644 --- a/drivers/misc/Kconfig @@ -83824,13 +83632,13 @@ index 7d5c4cd..43d2ac9 100644 obj-$(CONFIG_ECHO) += echo/ diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig new file mode 100644 -index 0000000..b94e6cd +index 0000000..c5ba283 --- /dev/null +++ b/drivers/misc/vc04_services/Kconfig @@ -0,0 +1,9 @@ +config BCM2708_VCHIQ + tristate "Videocore VCHIQ" -+ depends on MACH_BCM2708 || MACH_BCM2709 ++ depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX + default y + help + Kernel to VideoCore communication interface for the @@ -85417,10 +85225,10 @@ index 0000000..7ea5c64 +#endif /* VCHIQ_2835_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c new file mode 100644 -index 0000000..8ec88bb +index 0000000..c739083 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -0,0 +1,562 @@ +@@ -0,0 +1,547 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -85458,23 +85266,18 @@ index 0000000..8ec88bb +#include +#include +#include -+#include +#include +#include +#include +#include ++#include ++#include +#include +#include + -+#include -+ -+#include -+#include -+ +#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) + -+#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0 -+#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) ++#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) + +#include "vchiq_arm.h" +#include "vchiq_2835.h" @@ -85483,17 +85286,19 @@ index 0000000..8ec88bb + +#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) + ++#define BELL0 0x00 ++#define BELL2 0x08 ++ +typedef struct vchiq_2835_state_struct { + int inited; + VCHIQ_ARM_STATE_T arm_state; +} VCHIQ_2835_ARM_STATE_T; + -+static char *g_slot_mem; -+static int g_slot_mem_size; -+dma_addr_t g_slot_phys; ++static void __iomem *g_regs; +static FRAGMENTS_T *g_fragments_base; +static FRAGMENTS_T *g_free_fragments; -+struct semaphore g_free_fragments_sema; ++static struct semaphore g_free_fragments_sema; ++static unsigned long g_virt_to_bus_offset; + +extern int vchiq_arm_log_level; + @@ -85509,43 +85314,42 @@ index 0000000..8ec88bb +static void +free_pagelist(PAGELIST_T *pagelist, int actual); + -+int __init -+vchiq_platform_init(VCHIQ_STATE_T *state) ++int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) +{ ++ struct device *dev = &pdev->dev; + VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -+ int frag_mem_size; -+ int err; -+ int i; ++ struct resource *res; ++ void *slot_mem; ++ dma_addr_t slot_phys; ++ int slot_mem_size, frag_mem_size; ++ int err, irq, i; ++ ++ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); + + /* Allocate space for the channels in coherent memory */ -+ g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); ++ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); + frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); + -+ g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size, -+ &g_slot_phys, GFP_KERNEL); -+ -+ if (!g_slot_mem) { -+ vchiq_log_error(vchiq_arm_log_level, -+ "Unable to allocate channel memory"); -+ err = -ENOMEM; -+ goto failed_alloc; ++ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, ++ &slot_phys, GFP_KERNEL); ++ if (!slot_mem) { ++ dev_err(dev, "could not allocate DMA memory\n"); ++ return -ENOMEM; + } + -+ WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0); ++ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); + -+ vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size); -+ if (!vchiq_slot_zero) { -+ err = -EINVAL; -+ goto failed_init_slots; -+ } ++ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); ++ if (!vchiq_slot_zero) ++ return -EINVAL; + + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -+ (int)g_slot_phys + g_slot_mem_size; ++ (int)slot_phys + slot_mem_size; + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = + MAX_FRAGMENTS; + -+ g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size); -+ g_slot_mem_size += frag_mem_size; ++ g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); ++ slot_mem_size += frag_mem_size; + + g_free_fragments = g_fragments_base; + for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { @@ -85555,54 +85359,46 @@ index 0000000..8ec88bb + *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; + sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); + -+ if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) != -+ VCHIQ_SUCCESS) { -+ err = -EINVAL; -+ goto failed_vchiq_init; ++ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ g_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(g_regs)) ++ return PTR_ERR(g_regs); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev, "failed to get IRQ\n"); ++ return irq; + } + -+ err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq, -+ IRQF_IRQPOLL, "VCHIQ doorbell", -+ state); -+ if (err < 0) { -+ vchiq_log_error(vchiq_arm_log_level, "%s: failed to register " -+ "irq=%d err=%d", __func__, -+ VCHIQ_DOORBELL_IRQ, err); -+ goto failed_request_irq; ++ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, ++ "VCHIQ doorbell", state); ++ if (err) { ++ dev_err(dev, "failed to register irq=%d\n", irq); ++ return err; + } + + /* Send the base address of the slots to VideoCore */ + + dsb(); /* Ensure all writes have completed */ + -+ bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys); ++ err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); ++ if (err) { ++ dev_err(dev, "mailbox write failed\n"); ++ return err; ++ } + + vchiq_log_info(vchiq_arm_log_level, -+ "vchiq_init - done (slots %x, phys %x)", -+ (unsigned int)vchiq_slot_zero, g_slot_phys); ++ "vchiq_init - done (slots %x, phys %pad)", ++ (unsigned int)vchiq_slot_zero, &slot_phys); + -+ vchiq_call_connected_callbacks(); ++ vchiq_call_connected_callbacks(); + + return 0; -+ -+failed_request_irq: -+failed_vchiq_init: -+failed_init_slots: -+ dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys); -+ -+failed_alloc: -+ return err; +} + -+void __exit -+vchiq_platform_exit(VCHIQ_STATE_T *state) -+{ -+ free_irq(VCHIQ_DOORBELL_IRQ, state); -+ dma_free_coherent(NULL, g_slot_mem_size, -+ g_slot_mem, g_slot_phys); -+} -+ -+ +VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state) +{ @@ -85636,11 +85432,8 @@ index 0000000..8ec88bb + + dsb(); /* data barrier operation */ + -+ if (event->armed) { -+ /* trigger vc interrupt */ -+ -+ writel(0, __io_address(ARM_0_BELL2)); -+ } ++ if (event->armed) ++ writel(0, g_regs + BELL2); /* trigger vc interrupt */ +} + +int @@ -85764,7 +85557,7 @@ index 0000000..8ec88bb + unsigned int status; + + /* Read (and clear) the doorbell */ -+ status = readl(__io_address(ARM_0_BELL0)); ++ status = readl(g_regs + BELL0); + + if (status & 0x4) { /* Was the doorbell rung? */ + remote_event_pollall(state); @@ -85985,10 +85778,10 @@ index 0000000..8ec88bb +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000..0ad9656 +index 0000000..31e2cba --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2884 @@ +@@ -0,0 +1,2886 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -86036,6 +85829,7 @@ index 0000000..0ad9656 +#include +#include +#include ++#include + +#include "vchiq_core.h" +#include "vchiq_ioctl.h" @@ -88781,15 +88575,7 @@ index 0000000..0ad9656 + } +} + -+ -+/**************************************************************************** -+* -+* vchiq_init - called when the module is loaded. -+* -+***************************************************************************/ -+ -+static int __init -+vchiq_init(void) ++static int vchiq_probe(struct platform_device *pdev) +{ + int err; + void *ptr_err; @@ -88826,7 +88612,7 @@ index 0000000..0ad9656 + if (IS_ERR(ptr_err)) + goto failed_device_create; + -+ err = vchiq_platform_init(&g_state); ++ err = vchiq_platform_init(pdev, &g_state); + if (err != 0) + goto failed_platform_init; + @@ -88853,32 +88639,41 @@ index 0000000..0ad9656 + return err; +} + -+/**************************************************************************** -+* -+* vchiq_exit - called when the module is unloaded. -+* -+***************************************************************************/ -+ -+static void __exit -+vchiq_exit(void) ++static int vchiq_remove(struct platform_device *pdev) +{ -+ vchiq_platform_exit(&g_state); + device_destroy(vchiq_class, vchiq_devid); + class_destroy(vchiq_class); + cdev_del(&vchiq_cdev); + unregister_chrdev_region(vchiq_devid, 1); ++ ++ return 0; +} + -+module_init(vchiq_init); -+module_exit(vchiq_exit); ++static const struct of_device_id vchiq_of_match[] = { ++ { .compatible = "brcm,bcm2835-vchiq", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, vchiq_of_match); ++ ++static struct platform_driver vchiq_driver = { ++ .driver = { ++ .name = "bcm2835_vchiq", ++ .owner = THIS_MODULE, ++ .of_match_table = vchiq_of_match, ++ }, ++ .probe = vchiq_probe, ++ .remove = vchiq_remove, ++}; ++module_platform_driver(vchiq_driver); ++ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h new file mode 100644 -index 0000000..d1e2741 +index 0000000..9740e1a --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -0,0 +1,223 @@ +@@ -0,0 +1,220 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -88917,6 +88712,7 @@ index 0000000..d1e2741 +#define VCHIQ_ARM_H + +#include ++#include +#include +#include +#include "vchiq_core.h" @@ -89009,11 +88805,7 @@ index 0000000..d1e2741 +extern int vchiq_arm_log_level; +extern int vchiq_susp_log_level; + -+extern int __init -+vchiq_platform_init(VCHIQ_STATE_T *state); -+ -+extern void __exit -+vchiq_platform_exit(VCHIQ_STATE_T *state); ++int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); + +extern VCHIQ_STATE_T * +vchiq_get_state(void); @@ -89404,7 +89196,7 @@ index 0000000..863b3e3 +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 -index 0000000..835688b +index 0000000..2c98da4 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -0,0 +1,3934 @@ @@ -91192,7 +90984,7 @@ index 0000000..835688b + service->remoteport); + break; + case VCHIQ_MSG_DATA: -+ vchiq_log_trace(vchiq_core_log_level, ++ vchiq_log_info(vchiq_core_log_level, + "%d: prs DATA@%x,%x (%d->%d)", + state->id, (unsigned int)header, size, + remoteport, localport); @@ -96789,10 +96581,1019 @@ index 0000000..b6bfa21 + return vchiq_build_time; +} -From 859a7d70416a46048ab89165367891de2104ef6f Mon Sep 17 00:00:00 2001 +From 6290b45c0e5fa71d2131718d1b5770e7849aedeb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 17 Jun 2015 16:07:06 +0100 +Subject: [PATCH 14/77] vc_mem: Add vc_mem driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: popcornmix + +BCM270x: Move vc_mem + +Make the vc_mem module available for ARCH_BCM2835 by moving it. + +Signed-off-by: Noralf Trønnes +--- + arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- + arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- + drivers/char/broadcom/Kconfig | 12 +- + drivers/char/broadcom/Makefile | 1 + + drivers/char/broadcom/vc_mem.c | 423 +++++++++++++++++++++++++++ + include/linux/broadcom/vc_mem.h | 35 +++ + 6 files changed, 470 insertions(+), 467 deletions(-) + delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h + delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c + create mode 100644 drivers/char/broadcom/vc_mem.c + create mode 100644 include/linux/broadcom/vc_mem.h + +diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h +deleted file mode 100644 +index 4a4a338..0000000 +--- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/***************************************************************************** +-* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +-* +-* Unless you and Broadcom execute a separate written software license +-* agreement governing use of this software, this software is licensed to you +-* under the terms of the GNU General Public License version 2, available at +-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +-* +-* Notwithstanding the above, under no circumstances may you combine this +-* software in any way with any other Broadcom software provided under a +-* license other than the GPL, without Broadcom's express prior written +-* consent. +-*****************************************************************************/ +- +-#if !defined( VC_MEM_H ) +-#define VC_MEM_H +- +-#include +- +-#define VC_MEM_IOC_MAGIC 'v' +- +-#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) +-#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) +-#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) +-#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) +- +-#if defined( __KERNEL__ ) +-#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF +- +-extern unsigned long mm_vc_mem_phys_addr; +-extern unsigned int mm_vc_mem_size; +-extern int vc_mem_get_current_size( void ); +-#endif +- +-#endif /* VC_MEM_H */ +diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c +deleted file mode 100644 +index d2adfd1..0000000 +--- a/arch/arm/mach-bcm2709/vc_mem.c ++++ /dev/null +@@ -1,431 +0,0 @@ +-/***************************************************************************** +-* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +-* +-* Unless you and Broadcom execute a separate written software license +-* agreement governing use of this software, this software is licensed to you +-* under the terms of the GNU General Public License version 2, available at +-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +-* +-* Notwithstanding the above, under no circumstances may you combine this +-* software in any way with any other Broadcom software provided under a +-* license other than the GPL, without Broadcom's express prior written +-* consent. +-*****************************************************************************/ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef CONFIG_ARCH_KONA +-#include +-#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) +-#else +-#include +-#endif +- +-#include "mach/vc_mem.h" +- +-#define DRIVER_NAME "vc-mem" +- +-// Device (/dev) related variables +-static dev_t vc_mem_devnum = 0; +-static struct class *vc_mem_class = NULL; +-static struct cdev vc_mem_cdev; +-static int vc_mem_inited = 0; +- +-#ifdef CONFIG_DEBUG_FS +-static struct dentry *vc_mem_debugfs_entry; +-#endif +- +-/* +- * Videocore memory addresses and size +- * +- * Drivers that wish to know the videocore memory addresses and sizes should +- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in +- * headers. This allows the other drivers to not be tied down to a a certain +- * address/size at compile time. +- * +- * In the future, the goal is to have the videocore memory virtual address and +- * size be calculated at boot time rather than at compile time. The decision of +- * where the videocore memory resides and its size would be in the hands of the +- * bootloader (and/or kernel). When that happens, the values of these variables +- * would be calculated and assigned in the init function. +- */ +-// in the 2835 VC in mapped above ARM, but ARM has full access to VC space +-unsigned long mm_vc_mem_phys_addr = 0x00000000; +-unsigned int mm_vc_mem_size = 0; +-unsigned int mm_vc_mem_base = 0; +- +-EXPORT_SYMBOL(mm_vc_mem_phys_addr); +-EXPORT_SYMBOL(mm_vc_mem_size); +-EXPORT_SYMBOL(mm_vc_mem_base); +- +-static uint phys_addr = 0; +-static uint mem_size = 0; +-static uint mem_base = 0; +- +- +-/**************************************************************************** +-* +-* vc_mem_open +-* +-***************************************************************************/ +- +-static int +-vc_mem_open(struct inode *inode, struct file *file) +-{ +- (void) inode; +- (void) file; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- return 0; +-} +- +-/**************************************************************************** +-* +-* vc_mem_release +-* +-***************************************************************************/ +- +-static int +-vc_mem_release(struct inode *inode, struct file *file) +-{ +- (void) inode; +- (void) file; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- return 0; +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_size +-* +-***************************************************************************/ +- +-static void +-vc_mem_get_size(void) +-{ +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_base +-* +-***************************************************************************/ +- +-static void +-vc_mem_get_base(void) +-{ +-} +- +-/**************************************************************************** +-* +-* vc_mem_get_current_size +-* +-***************************************************************************/ +- +-int +-vc_mem_get_current_size(void) +-{ +- return mm_vc_mem_size; +-} +- +-EXPORT_SYMBOL_GPL(vc_mem_get_current_size); +- +-/**************************************************************************** +-* +-* vc_mem_ioctl +-* +-***************************************************************************/ +- +-static long +-vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +-{ +- int rc = 0; +- +- (void) cmd; +- (void) arg; +- +- pr_debug("%s: called file = 0x%p\n", __func__, file); +- +- switch (cmd) { +- case VC_MEM_IOC_MEM_PHYS_ADDR: +- { +- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", +- __func__, (void *) mm_vc_mem_phys_addr); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, +- sizeof (mm_vc_mem_phys_addr)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_SIZE: +- { +- // Get the videocore memory size first +- vc_mem_get_size(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, +- mm_vc_mem_size); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_size, +- sizeof (mm_vc_mem_size)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_BASE: +- { +- // Get the videocore memory base +- vc_mem_get_base(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, +- mm_vc_mem_base); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_base, +- sizeof (mm_vc_mem_base)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- case VC_MEM_IOC_MEM_LOAD: +- { +- // Get the videocore memory base +- vc_mem_get_base(); +- +- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, +- mm_vc_mem_base); +- +- if (copy_to_user((void *) arg, &mm_vc_mem_base, +- sizeof (mm_vc_mem_base)) != 0) { +- rc = -EFAULT; +- } +- break; +- } +- default: +- { +- return -ENOTTY; +- } +- } +- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); +- +- return rc; +-} +- +-/**************************************************************************** +-* +-* vc_mem_mmap +-* +-***************************************************************************/ +- +-static int +-vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) +-{ +- int rc = 0; +- unsigned long length = vma->vm_end - vma->vm_start; +- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; +- +- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", +- __func__, (long) vma->vm_start, (long) vma->vm_end, +- (long) vma->vm_pgoff); +- +- if (offset + length > mm_vc_mem_size) { +- pr_err("%s: length %ld is too big\n", __func__, length); +- return -EINVAL; +- } +- // Do not cache the memory map +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- +- rc = remap_pfn_range(vma, vma->vm_start, +- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + +- vma->vm_pgoff, length, vma->vm_page_prot); +- if (rc != 0) { +- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); +- } +- +- return rc; +-} +- +-/**************************************************************************** +-* +-* File Operations for the driver. +-* +-***************************************************************************/ +- +-static const struct file_operations vc_mem_fops = { +- .owner = THIS_MODULE, +- .open = vc_mem_open, +- .release = vc_mem_release, +- .unlocked_ioctl = vc_mem_ioctl, +- .mmap = vc_mem_mmap, +-}; +- +-#ifdef CONFIG_DEBUG_FS +-static void vc_mem_debugfs_deinit(void) +-{ +- debugfs_remove_recursive(vc_mem_debugfs_entry); +- vc_mem_debugfs_entry = NULL; +-} +- +- +-static int vc_mem_debugfs_init( +- struct device *dev) +-{ +- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); +- if (!vc_mem_debugfs_entry) { +- dev_warn(dev, "could not create debugfs entry\n"); +- return -EFAULT; +- } +- +- if (!debugfs_create_x32("vc_mem_phys_addr", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_phys_addr)) { +- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", +- __func__); +- goto fail; +- } +- +- if (!debugfs_create_x32("vc_mem_size", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_size)) { +- dev_warn(dev, "%s:could not create vc_mem_size entry\n", +- __func__); +- goto fail; +- } +- +- if (!debugfs_create_x32("vc_mem_base", +- 0444, +- vc_mem_debugfs_entry, +- (u32 *)&mm_vc_mem_base)) { +- dev_warn(dev, "%s:could not create vc_mem_base entry\n", +- __func__); +- goto fail; +- } +- +- return 0; +- +-fail: +- vc_mem_debugfs_deinit(); +- return -EFAULT; +-} +- +-#endif /* CONFIG_DEBUG_FS */ +- +- +-/**************************************************************************** +-* +-* vc_mem_init +-* +-***************************************************************************/ +- +-static int __init +-vc_mem_init(void) +-{ +- int rc = -EFAULT; +- struct device *dev; +- +- pr_debug("%s: called\n", __func__); +- +- mm_vc_mem_phys_addr = phys_addr; +- mm_vc_mem_size = mem_size; +- mm_vc_mem_base = mem_base; +- +- vc_mem_get_size(); +- +- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", +- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); +- +- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { +- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", +- __func__, rc); +- goto out_err; +- } +- +- cdev_init(&vc_mem_cdev, &vc_mem_fops); +- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { +- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); +- goto out_unregister; +- } +- +- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); +- if (IS_ERR(vc_mem_class)) { +- rc = PTR_ERR(vc_mem_class); +- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); +- goto out_cdev_del; +- } +- +- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, +- DRIVER_NAME); +- if (IS_ERR(dev)) { +- rc = PTR_ERR(dev); +- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); +- goto out_class_destroy; +- } +- +-#ifdef CONFIG_DEBUG_FS +- /* don't fail if the debug entries cannot be created */ +- vc_mem_debugfs_init(dev); +-#endif +- +- vc_mem_inited = 1; +- return 0; +- +- device_destroy(vc_mem_class, vc_mem_devnum); +- +- out_class_destroy: +- class_destroy(vc_mem_class); +- vc_mem_class = NULL; +- +- out_cdev_del: +- cdev_del(&vc_mem_cdev); +- +- out_unregister: +- unregister_chrdev_region(vc_mem_devnum, 1); +- +- out_err: +- return -1; +-} +- +-/**************************************************************************** +-* +-* vc_mem_exit +-* +-***************************************************************************/ +- +-static void __exit +-vc_mem_exit(void) +-{ +- pr_debug("%s: called\n", __func__); +- +- if (vc_mem_inited) { +-#if CONFIG_DEBUG_FS +- vc_mem_debugfs_deinit(); +-#endif +- device_destroy(vc_mem_class, vc_mem_devnum); +- class_destroy(vc_mem_class); +- cdev_del(&vc_mem_cdev); +- unregister_chrdev_region(vc_mem_devnum, 1); +- } +-} +- +-module_init(vc_mem_init); +-module_exit(vc_mem_exit); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Broadcom Corporation"); +- +-module_param(phys_addr, uint, 0644); +-module_param(mem_size, uint, 0644); +-module_param(mem_base, uint, 0644); +diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig +index 2d8bd6e..7037928 100644 +--- a/drivers/char/broadcom/Kconfig ++++ b/drivers/char/broadcom/Kconfig +@@ -7,9 +7,19 @@ menuconfig BRCM_CHAR_DRIVERS + help + Broadcom's char drivers + ++if BRCM_CHAR_DRIVERS ++ + config BCM_VC_CMA + bool "Videocore CMA" +- depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ ++ depends on CMA && BCM2708_VCHIQ + default n + help + Helper for videocore CMA access. ++ ++config BCM2708_VCMEM ++ bool "Videocore Memory" ++ default y ++ help ++ Helper for videocore memory access and total size allocation. ++ ++endif +diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile +index 13c5bca..fce918c 100644 +--- a/drivers/char/broadcom/Makefile ++++ b/drivers/char/broadcom/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ ++obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +diff --git a/drivers/char/broadcom/vc_mem.c b/drivers/char/broadcom/vc_mem.c +new file mode 100644 +index 0000000..fcde6b1 +--- /dev/null ++++ b/drivers/char/broadcom/vc_mem.c +@@ -0,0 +1,423 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "vc-mem" ++ ++// Device (/dev) related variables ++static dev_t vc_mem_devnum = 0; ++static struct class *vc_mem_class = NULL; ++static struct cdev vc_mem_cdev; ++static int vc_mem_inited = 0; ++ ++#ifdef CONFIG_DEBUG_FS ++static struct dentry *vc_mem_debugfs_entry; ++#endif ++ ++/* ++ * Videocore memory addresses and size ++ * ++ * Drivers that wish to know the videocore memory addresses and sizes should ++ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in ++ * headers. This allows the other drivers to not be tied down to a a certain ++ * address/size at compile time. ++ * ++ * In the future, the goal is to have the videocore memory virtual address and ++ * size be calculated at boot time rather than at compile time. The decision of ++ * where the videocore memory resides and its size would be in the hands of the ++ * bootloader (and/or kernel). When that happens, the values of these variables ++ * would be calculated and assigned in the init function. ++ */ ++// in the 2835 VC in mapped above ARM, but ARM has full access to VC space ++unsigned long mm_vc_mem_phys_addr = 0x00000000; ++unsigned int mm_vc_mem_size = 0; ++unsigned int mm_vc_mem_base = 0; ++ ++EXPORT_SYMBOL(mm_vc_mem_phys_addr); ++EXPORT_SYMBOL(mm_vc_mem_size); ++EXPORT_SYMBOL(mm_vc_mem_base); ++ ++static uint phys_addr = 0; ++static uint mem_size = 0; ++static uint mem_base = 0; ++ ++ ++/**************************************************************************** ++* ++* vc_mem_open ++* ++***************************************************************************/ ++ ++static int ++vc_mem_open(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_release ++* ++***************************************************************************/ ++ ++static int ++vc_mem_release(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_size ++* ++***************************************************************************/ ++ ++static void ++vc_mem_get_size(void) ++{ ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_base ++* ++***************************************************************************/ ++ ++static void ++vc_mem_get_base(void) ++{ ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_current_size ++* ++***************************************************************************/ ++ ++int ++vc_mem_get_current_size(void) ++{ ++ return mm_vc_mem_size; ++} ++ ++EXPORT_SYMBOL_GPL(vc_mem_get_current_size); ++ ++/**************************************************************************** ++* ++* vc_mem_ioctl ++* ++***************************************************************************/ ++ ++static long ++vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int rc = 0; ++ ++ (void) cmd; ++ (void) arg; ++ ++ pr_debug("%s: called file = 0x%p\n", __func__, file); ++ ++ switch (cmd) { ++ case VC_MEM_IOC_MEM_PHYS_ADDR: ++ { ++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", ++ __func__, (void *) mm_vc_mem_phys_addr); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, ++ sizeof (mm_vc_mem_phys_addr)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_SIZE: ++ { ++ // Get the videocore memory size first ++ vc_mem_get_size(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, ++ mm_vc_mem_size); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_size, ++ sizeof (mm_vc_mem_size)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_BASE: ++ { ++ // Get the videocore memory base ++ vc_mem_get_base(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, ++ mm_vc_mem_base); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_base, ++ sizeof (mm_vc_mem_base)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_LOAD: ++ { ++ // Get the videocore memory base ++ vc_mem_get_base(); ++ ++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, ++ mm_vc_mem_base); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_base, ++ sizeof (mm_vc_mem_base)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ default: ++ { ++ return -ENOTTY; ++ } ++ } ++ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_mmap ++* ++***************************************************************************/ ++ ++static int ++vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ int rc = 0; ++ unsigned long length = vma->vm_end - vma->vm_start; ++ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; ++ ++ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", ++ __func__, (long) vma->vm_start, (long) vma->vm_end, ++ (long) vma->vm_pgoff); ++ ++ if (offset + length > mm_vc_mem_size) { ++ pr_err("%s: length %ld is too big\n", __func__, length); ++ return -EINVAL; ++ } ++ // Do not cache the memory map ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ ++ rc = remap_pfn_range(vma, vma->vm_start, ++ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + ++ vma->vm_pgoff, length, vma->vm_page_prot); ++ if (rc != 0) { ++ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); ++ } ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* File Operations for the driver. ++* ++***************************************************************************/ ++ ++static const struct file_operations vc_mem_fops = { ++ .owner = THIS_MODULE, ++ .open = vc_mem_open, ++ .release = vc_mem_release, ++ .unlocked_ioctl = vc_mem_ioctl, ++ .mmap = vc_mem_mmap, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++static void vc_mem_debugfs_deinit(void) ++{ ++ debugfs_remove_recursive(vc_mem_debugfs_entry); ++ vc_mem_debugfs_entry = NULL; ++} ++ ++ ++static int vc_mem_debugfs_init( ++ struct device *dev) ++{ ++ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); ++ if (!vc_mem_debugfs_entry) { ++ dev_warn(dev, "could not create debugfs entry\n"); ++ return -EFAULT; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_phys_addr", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_phys_addr)) { ++ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_size", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_size)) { ++ dev_warn(dev, "%s:could not create vc_mem_size entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ if (!debugfs_create_x32("vc_mem_base", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_base)) { ++ dev_warn(dev, "%s:could not create vc_mem_base entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ vc_mem_debugfs_deinit(); ++ return -EFAULT; ++} ++ ++#endif /* CONFIG_DEBUG_FS */ ++ ++ ++/**************************************************************************** ++* ++* vc_mem_init ++* ++***************************************************************************/ ++ ++static int __init ++vc_mem_init(void) ++{ ++ int rc = -EFAULT; ++ struct device *dev; ++ ++ pr_debug("%s: called\n", __func__); ++ ++ mm_vc_mem_phys_addr = phys_addr; ++ mm_vc_mem_size = mem_size; ++ mm_vc_mem_base = mem_base; ++ ++ vc_mem_get_size(); ++ ++ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", ++ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); ++ ++ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { ++ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", ++ __func__, rc); ++ goto out_err; ++ } ++ ++ cdev_init(&vc_mem_cdev, &vc_mem_fops); ++ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { ++ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); ++ goto out_unregister; ++ } ++ ++ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); ++ if (IS_ERR(vc_mem_class)) { ++ rc = PTR_ERR(vc_mem_class); ++ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); ++ goto out_cdev_del; ++ } ++ ++ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, ++ DRIVER_NAME); ++ if (IS_ERR(dev)) { ++ rc = PTR_ERR(dev); ++ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); ++ goto out_class_destroy; ++ } ++ ++#ifdef CONFIG_DEBUG_FS ++ /* don't fail if the debug entries cannot be created */ ++ vc_mem_debugfs_init(dev); ++#endif ++ ++ vc_mem_inited = 1; ++ return 0; ++ ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ ++ out_class_destroy: ++ class_destroy(vc_mem_class); ++ vc_mem_class = NULL; ++ ++ out_cdev_del: ++ cdev_del(&vc_mem_cdev); ++ ++ out_unregister: ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ ++ out_err: ++ return -1; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_exit ++* ++***************************************************************************/ ++ ++static void __exit ++vc_mem_exit(void) ++{ ++ pr_debug("%s: called\n", __func__); ++ ++ if (vc_mem_inited) { ++#if CONFIG_DEBUG_FS ++ vc_mem_debugfs_deinit(); ++#endif ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ class_destroy(vc_mem_class); ++ cdev_del(&vc_mem_cdev); ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ } ++} ++ ++module_init(vc_mem_init); ++module_exit(vc_mem_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); ++ ++module_param(phys_addr, uint, 0644); ++module_param(mem_size, uint, 0644); ++module_param(mem_base, uint, 0644); +diff --git a/include/linux/broadcom/vc_mem.h b/include/linux/broadcom/vc_mem.h +new file mode 100644 +index 0000000..20a4753 +--- /dev/null ++++ b/include/linux/broadcom/vc_mem.h +@@ -0,0 +1,35 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#ifndef _VC_MEM_H ++#define _VC_MEM_H ++ ++#include ++ ++#define VC_MEM_IOC_MAGIC 'v' ++ ++#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) ++#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) ++#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) ++#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) ++ ++#if defined( __KERNEL__ ) ++#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF ++ ++extern unsigned long mm_vc_mem_phys_addr; ++extern unsigned int mm_vc_mem_size; ++extern int vc_mem_get_current_size( void ); ++#endif ++ ++#endif /* _VC_MEM_H */ + +From e9ebded52208b6164753a82d268cd80e833e2737 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 012/216] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 15/77] vcsm: VideoCore shared memory service for BCM2835 Add experimental support for the VideoCore shared memory service. This allows user processes to allocate memory from VideoCore's @@ -96823,17 +97624,19 @@ On building the bcm_vc_sm as a module we get the following error: v7_dma_flush_range and do_munmap are undefined in vc-sm.ko. Fix by making it not an option to build as module + +vcsm: Add ioctl for custom cache flushing --- arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h | 181 ++ arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h | 55 + arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h | 82 + - arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 233 ++ - drivers/char/broadcom/Kconfig | 7 + + arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 248 ++ + drivers/char/broadcom/Kconfig | 9 + drivers/char/broadcom/Makefile | 1 + drivers/char/broadcom/vc_sm/Makefile | 21 + drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 492 +++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 3163 ++++++++++++++++++++ - 9 files changed, 4235 insertions(+) + drivers/char/broadcom/vc_sm/vmcs_sm.c | 3211 ++++++++++++++++++++ + 9 files changed, 4300 insertions(+) create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h @@ -97180,10 +97983,10 @@ index 0000000..5e279f5 +#endif /* __VC_VCHI_SM_H__INCLUDED__ */ diff --git a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h new file mode 100644 -index 0000000..42d0eb0 +index 0000000..334f36d --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -@@ -0,0 +1,233 @@ +@@ -0,0 +1,248 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97247,6 +98050,8 @@ index 0000000..42d0eb0 + VMCS_SM_CMD_HOST_WALK_PID_ALLOC, + VMCS_SM_CMD_HOST_WALK_PID_MAP, + ++ VMCS_SM_CMD_CLEAN_INVALID, ++ + VMCS_SM_CMD_LAST /* Do no delete */ +}; + @@ -97349,6 +98154,16 @@ index 0000000..42d0eb0 + unsigned int size; +}; + ++struct vmcs_sm_ioctl_clean_invalid { ++ /* user -> kernel */ ++ struct { ++ unsigned int cmd; ++ unsigned int handle; ++ unsigned int addr; ++ unsigned int size; ++ } s[8]; ++}; ++ +/* IOCTL numbers */ +#define VMCS_SM_IOCTL_MEM_ALLOC\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\ @@ -97377,6 +98192,9 @@ index 0000000..42d0eb0 +#define VMCS_SM_IOCTL_MEM_INVALID\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\ + struct vmcs_sm_ioctl_cache) ++#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\ ++ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\ ++ struct vmcs_sm_ioctl_clean_invalid) + +#define VMCS_SM_IOCTL_SIZE_USR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\ @@ -97418,26 +98236,29 @@ index 0000000..42d0eb0 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 2d8bd6e..fd23e00 100644 +index 7037928..75fa1cb 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -13,3 +13,10 @@ config BCM_VC_CMA - default n - help - Helper for videocore CMA access. +@@ -23,3 +23,12 @@ config BCM2708_VCMEM + Helper for videocore memory access and total size allocation. + + endif + +config BCM_VC_SM + bool "VMCS Shared Memory" ++ depends on BCM2708_VCHIQ ++ select BCM2708_VCMEM + default n + help + Support for the VC shared memory on the Broadcom reference + design. Uses the VCHIQ stack. diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 13c5bca..0bf7fdf 100644 +index fce918c..de8feb9 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -1 +1,2 @@ +@@ -1,2 +1,3 @@ obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ + obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ diff --git a/drivers/char/broadcom/vc_sm/Makefile b/drivers/char/broadcom/vc_sm/Makefile new file mode 100644 @@ -97966,10 +98787,10 @@ index 0000000..7c6ba1a +} diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c new file mode 100644 -index 0000000..da1c523 +index 0000000..0bfb42e --- /dev/null +++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -0,0 +1,3163 @@ +@@ -0,0 +1,3211 @@ +/***************************************************************************** +* Copyright 2011-2012 Broadcom Corporation. All rights reserved. +* @@ -97987,6 +98808,7 @@ index 0000000..da1c523 +/* ---- Include Files ----------------------------------------------------- */ + +#include ++#include +#include +#include +#include @@ -98007,8 +98829,6 @@ index 0000000..da1c523 +#include +#include + -+#include -+ +#include "vchiq_connected.h" +#include "vc_vchi_sm.h" + @@ -100704,6 +101524,55 @@ index 0000000..da1c523 + } + break; + ++ /* Flush/Invalidate the cache for a given mapping. */ ++ case VMCS_SM_CMD_CLEAN_INVALID: ++ { ++ int i; ++ struct vmcs_sm_ioctl_clean_invalid ioparam; ++ ++ /* Get parameter data. */ ++ if (copy_from_user(&ioparam, ++ (void *)arg, sizeof(ioparam)) != 0) { ++ pr_err("[%s]: failed to copy-from-user for cmd %x\n", ++ __func__, cmdnr); ++ ret = -EFAULT; ++ goto out; ++ } ++ for (i=0; ires_cached) { ++ unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1); ++ unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1); ++ resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++; ++ ++ /* L1/L2 cache flush */ ++ down_read(¤t->mm->mmap_sem); ++ vcsm_vma_cache_clean_page_range(base, end); ++ up_read(¤t->mm->mmap_sem); ++ } else if (resource == NULL) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (resource) ++ vmcs_sm_release_resource(resource, 0); ++ } ++ break; ++ } ++ } ++ } ++ break; ++ + default: + { + ret = -EINVAL; @@ -101134,23 +102003,32 @@ index 0000000..da1c523 +MODULE_DESCRIPTION("VideoCore SharedMemory Driver"); +MODULE_LICENSE("GPL v2"); -From 103cb0411fad640ec86640f3fda90a3da782aa68 Mon Sep 17 00:00:00 2001 +From 7f769de038003dcf3f6eff180e2e295888789dc2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 013/216] Add hwrng (hardware random number generator) driver +Subject: [PATCH 16/77] Add hwrng (hardware random number generator) driver --- - drivers/char/hw_random/Kconfig | 11 ++++ + drivers/char/hw_random/Kconfig | 13 +++- drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/bcm2708-rng.c | 118 +++++++++++++++++++++++++++++++++++ - 3 files changed, 130 insertions(+) + 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100755 drivers/char/hw_random/bcm2708-rng.c diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index de57b38..1c97093 100644 +index f48cf11..70f9613 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig -@@ -320,6 +320,17 @@ config HW_RANDOM_TPM +@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX + + config HW_RANDOM_BCM2835 + tristate "Broadcom BCM2835 Random Number Generator support" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number +@@ -333,6 +333,17 @@ config HW_RANDOM_TPM If unsure, say Y. @@ -101169,16 +102047,17 @@ index de57b38..1c97093 100644 tristate "Qualcomm SoCs Random Number Generator support" depends on HW_RANDOM && ARCH_QCOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile -index 0b4cd57..78b019c 100644 +index 055bb01..36be864 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile -@@ -28,5 +28,6 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o - obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o - obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o - obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o +@@ -4,6 +4,7 @@ + + obj-$(CONFIG_HW_RANDOM) += rng-core.o + rng-core-y := core.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o - obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o - obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o + obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o + obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o diff --git a/drivers/char/hw_random/bcm2708-rng.c b/drivers/char/hw_random/bcm2708-rng.c new file mode 100755 index 0000000..340f004 @@ -101304,10 +102183,10 @@ index 0000000..340f004 +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); -From 4e3072cbb7ce07057d091188fc1a3897e3169007 Mon Sep 17 00:00:00 2001 +From 68990b28334ea63cdc56bfe9663025dade9d7822 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 014/216] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 17/77] 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 @@ -101344,11 +102223,19 @@ read_current_timer isn't guaranteed to return values in microseconds, and indeed it doesn't on a Pi2. Issue: linux#827 + +lirc-rpi: Add device tree support, and a suitable overlay + +The overlay supports DT parameters that match the old module +parameters, except that gpio_in_pull should be set using the +strings "up", "down" or "off". + +lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode --- drivers/staging/media/lirc/Kconfig | 6 + drivers/staging/media/lirc/Makefile | 1 + - drivers/staging/media/lirc/lirc_rpi.c | 667 ++++++++++++++++++++++++++++++++++ - 3 files changed, 674 insertions(+) + drivers/staging/media/lirc/lirc_rpi.c | 765 ++++++++++++++++++++++++++++++++++ + 3 files changed, 772 insertions(+) create mode 100644 drivers/staging/media/lirc/lirc_rpi.c diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig @@ -101382,10 +102269,10 @@ index 5430adf..9e53cd0 100644 obj-$(CONFIG_LIRC_SIR) += lirc_sir.o diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c new file mode 100644 -index 0000000..8aa452d +index 0000000..24563ec --- /dev/null +++ b/drivers/staging/media/lirc/lirc_rpi.c -@@ -0,0 +1,667 @@ +@@ -0,0 +1,765 @@ +/* + * lirc_rpi.c + * @@ -101429,6 +102316,7 @@ index 0000000..8aa452d +#include +#include +#include ++#include + +#include + @@ -101691,32 +102579,117 @@ index 0000000..8aa452d + return 0; +} + ++static inline int read_bool_property(const struct device_node *np, ++ const char *propname, ++ bool *out_value) ++{ ++ u32 value = 0; ++ int err = of_property_read_u32(np, propname, &value); ++ if (err == 0) ++ *out_value = (value != 0); ++ return err; ++} ++ ++static void read_pin_settings(struct device_node *node) ++{ ++ u32 pin; ++ int index; ++ ++ for (index = 0; ++ of_property_read_u32_index( ++ node, ++ "brcm,pins", ++ index, ++ &pin) == 0; ++ index++) { ++ u32 function; ++ int err; ++ err = of_property_read_u32_index( ++ node, ++ "brcm,function", ++ index, ++ &function); ++ if (err == 0) { ++ if (function == 1) /* Output */ ++ gpio_out_pin = pin; ++ else if (function == 0) /* Input */ ++ gpio_in_pin = pin; ++ } ++ } ++} ++ +static int init_port(void) +{ + int i, nlow, nhigh, ret; ++ struct device_node *node; ++ ++ node = lirc_rpi_dev->dev.of_node; + + gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip); + -+ if (!gpiochip) ++ /* ++ * Because of the lack of a setpull function, only support ++ * pinctrl-bcm2835 if using device tree. ++ */ ++ if (!gpiochip && node) ++ gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip); ++ ++ if (!gpiochip) { ++ pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n"); + return -ENODEV; -+ -+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_out_pin); -+ ret = -ENODEV; -+ goto exit_init_port; + } + -+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_in_pin); -+ ret = -ENODEV; -+ goto exit_gpio_free_out_pin; ++ if (node) { ++ struct device_node *pins_node; ++ ++ pins_node = of_parse_phandle(node, "pinctrl-0", 0); ++ if (!pins_node) { ++ printk(KERN_ERR LIRC_DRIVER_NAME ++ ": pinctrl settings not found!\n"); ++ ret = -EINVAL; ++ goto exit_init_port; ++ } ++ ++ read_pin_settings(pins_node); ++ ++ of_property_read_u32(node, "rpi,sense", &sense); ++ ++ read_bool_property(node, "rpi,softcarrier", &softcarrier); ++ ++ read_bool_property(node, "rpi,invert", &invert); ++ ++ read_bool_property(node, "rpi,debug", &debug); ++ ++ } ++ else ++ { ++ if (gpio_in_pin >= BCM2708_NR_GPIOS || ++ gpio_out_pin >= BCM2708_NR_GPIOS) { ++ ret = -EINVAL; ++ printk(KERN_ERR LIRC_DRIVER_NAME ++ ": invalid GPIO pin(s) specified!\n"); ++ goto exit_init_port; ++ } ++ ++ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { ++ printk(KERN_ALERT LIRC_DRIVER_NAME ++ ": cant claim gpio pin %d\n", gpio_out_pin); ++ ret = -ENODEV; ++ goto exit_init_port; ++ } ++ ++ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { ++ printk(KERN_ALERT LIRC_DRIVER_NAME ++ ": cant claim gpio pin %d\n", gpio_in_pin); ++ ret = -ENODEV; ++ goto exit_gpio_free_out_pin; ++ } ++ ++ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); ++ gpiochip->direction_input(gpiochip, gpio_in_pin); ++ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); + } + -+ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -+ gpiochip->direction_input(gpiochip, gpio_in_pin); -+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); + gpiochip->set(gpiochip, gpio_out_pin, invert); + + irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin); @@ -101910,15 +102883,23 @@ index 0000000..8aa452d + .owner = THIS_MODULE, +}; + ++static const struct of_device_id lirc_rpi_of_match[] = { ++ { .compatible = "rpi,lirc-rpi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, lirc_rpi_of_match); ++ +static struct platform_driver lirc_rpi_driver = { + .driver = { + .name = LIRC_DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(lirc_rpi_of_match), + }, +}; + +static int __init lirc_rpi_init(void) +{ ++ struct device_node *node; + int result; + + /* Init read buffer. */ @@ -101933,15 +102914,26 @@ index 0000000..8aa452d + goto exit_buffer_free; + } + -+ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -+ if (!lirc_rpi_dev) { -+ result = -ENOMEM; -+ goto exit_driver_unregister; -+ } ++ node = of_find_compatible_node(NULL, NULL, ++ lirc_rpi_of_match[0].compatible); + -+ result = platform_device_add(lirc_rpi_dev); -+ if (result) -+ goto exit_device_put; ++ if (node) { ++ /* DT-enabled */ ++ lirc_rpi_dev = of_find_device_by_node(node); ++ WARN_ON(lirc_rpi_dev->dev.of_node != node); ++ of_node_put(node); ++ } ++ else { ++ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); ++ if (!lirc_rpi_dev) { ++ result = -ENOMEM; ++ goto exit_driver_unregister; ++ } ++ ++ result = platform_device_add(lirc_rpi_dev); ++ if (result) ++ goto exit_device_put; ++ } + + return 0; + @@ -101973,13 +102965,6 @@ index 0000000..8aa452d + if (result) + return result; + -+ if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) { -+ result = -EINVAL; -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": invalid GPIO pin(s) specified!\n"); -+ goto exit_rpi; -+ } -+ + result = init_port(); + if (result < 0) + goto exit_rpi; @@ -102054,40 +103039,29 @@ index 0000000..8aa452d +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -From 123948742379f19e1c2764020d8c523d445550bf Mon Sep 17 00:00:00 2001 +From b359d4ff9144f1ee3f333eee7b49bab1c6d92c1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 015/216] Add cpufreq driver +Subject: [PATCH 18/77] Add cpufreq driver +Signed-off-by: popcornmix --- - arch/arm/Kconfig | 1 + - drivers/cpufreq/Kconfig.arm | 8 ++ + drivers/cpufreq/Kconfig.arm | 9 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/bcm2835-cpufreq.c | 224 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 234 insertions(+) - create mode 100755 drivers/cpufreq/bcm2835-cpufreq.c + 3 files changed, 234 insertions(+) + create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index ee1bb5e..9fcd395 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -378,6 +378,7 @@ config ARCH_BCM2708 - select NEED_MACH_GPIO_H - select NEED_MACH_MEMORY_H - select CLKDEV_LOOKUP -+ select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS - select ARM_ERRATA_411920 - select MACH_BCM2708 diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 1b06fc4..0b90de8 100644 +index 4f3dbc8..a1039f0 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -249,6 +249,14 @@ config ARM_SPEAR_CPUFREQ +@@ -258,6 +258,15 @@ config ARM_SPEAR_CPUFREQ help This adds the CPUFreq driver support for SPEAr SOCs. +config ARM_BCM2835_CPUFREQ ++ depends on BCM2708_MBOX + bool "BCM2835 Driver" + default y + help @@ -102099,10 +103073,10 @@ index 1b06fc4..0b90de8 100644 bool "TEGRA CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 82a1821..50b1954 100644 +index cdce92a..c420f3f 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o +@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o @@ -102111,8 +103085,8 @@ index 82a1821..50b1954 100644 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -new file mode 100755 -index 0000000..447ca09 +new file mode 100644 +index 0000000..6735da9 --- /dev/null +++ b/drivers/cpufreq/bcm2835-cpufreq.c @@ -0,0 +1,224 @@ @@ -102144,7 +103118,7 @@ index 0000000..447ca09 +#include +#include +#include -+#include ++#include + +/* ---------- DEFINES ---------- */ +/*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */ @@ -102341,36 +103315,39 @@ index 0000000..447ca09 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From f563316302e117df98e91a8e1366dae653094f04 Mon Sep 17 00:00:00 2001 +From 37e551cc949ea14042539b089e08df475bab0f59 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 016/216] Added hwmon/thermal driver for reporting core +Subject: [PATCH 19/77] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +BCM270x: Move thermal sensor to Device Tree + +Add Device Tree support to bcm2835-thermal driver. +Add thermal sensor device to Device Tree. +Don't add platform device when booting in DT mode. + +Signed-off-by: Noralf Trønnes --- - arch/arm/mach-bcm2708/bcm2708.c | 11 ++ - drivers/hwmon/Kconfig | 10 ++ - drivers/hwmon/Makefile | 1 + - drivers/hwmon/bcm2835-hwmon.c | 219 ++++++++++++++++++++++++++++++++++++++ - drivers/thermal/Kconfig | 6 ++ + arch/arm/mach-bcm2708/bcm2708.c | 6 ++ + arch/arm/mach-bcm2709/bcm2709.c | 6 ++ + drivers/thermal/Kconfig | 7 ++ drivers/thermal/Makefile | 1 + - drivers/thermal/bcm2835-thermal.c | 184 ++++++++++++++++++++++++++++++++ - 7 files changed, 432 insertions(+) - create mode 100644 drivers/hwmon/bcm2835-hwmon.c + drivers/thermal/bcm2835-thermal.c | 190 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 210 insertions(+) create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f54e3e9b..bae8ba5 100644 +index 86011af..f2d9b03 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -499,6 +499,14 @@ static struct platform_device bcm2708_alsa_devices[] = { +@@ -505,6 +505,10 @@ static struct platform_device bcm2708_alsa_devices[] = { }, }; -+static struct platform_device bcm2835_hwmon_device = { -+ .name = "bcm2835_hwmon", -+}; -+ +static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", +}; @@ -102378,283 +103355,49 @@ index f54e3e9b..bae8ba5 100644 int __init bcm_register_device(struct platform_device *pdev) { int ret; -@@ -611,6 +619,9 @@ void __init bcm2708_init(void) +@@ -651,6 +655,8 @@ void __init bcm2708_init(void) for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); + bcm_register_device_dt(&bcm2708_alsa_devices[i]); -+ bcm_register_device(&bcm2835_hwmon_device); -+ bcm_register_device(&bcm2835_thermal_device); ++ bcm_register_device_dt(&bcm2835_thermal_device); + - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 110fade..8c4474d 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -1703,6 +1703,16 @@ config SENSORS_ULTRA45 - This driver provides support for the Ultra45 workstation environmental - sensors. + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index bc1ee1c..9631bdb 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -525,6 +525,10 @@ static struct platform_device bcm2708_alsa_devices[] = { + }, + }; -+config SENSORS_BCM2835 -+ depends on THERMAL_BCM2835=n -+ tristate "Broadcom BCM2835 HWMON Driver" -+ help -+ If you say yes here you get support for the hardware -+ monitoring features of the BCM2835 Chip ++static struct platform_device bcm2835_thermal_device = { ++ .name = "bcm2835_thermal", ++}; + -+ This driver can also be built as a module. If so, the module -+ will be called bcm2835-hwmon. -+ - if ACPI + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -671,6 +675,8 @@ void __init bcm2709_init(void) + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device_dt(&bcm2708_alsa_devices[i]); - comment "ACPI drivers" -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 6c94147..e7c60cb 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -155,6 +155,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o - obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o - obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o - obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -+obj-$(CONFIG_SENSORS_BCM2835) += bcm2835-hwmon.o - - obj-$(CONFIG_PMBUS) += pmbus/ - -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -new file mode 100644 -index 0000000..5bbed45 ---- /dev/null -+++ b/drivers/hwmon/bcm2835-hwmon.c -@@ -0,0 +1,219 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ ++ bcm_register_device_dt(&bcm2835_thermal_device); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "bcm2835_hwmon" -+ -+/*#define HWMON_DEBUG_ENABLE*/ -+ -+#ifdef HWMON_DEBUG_ENABLE -+#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__) -+#else -+#define print_debug(fmt,...) -+#endif -+#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__) -+#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__) -+ -+#define VC_TAG_GET_TEMP 0x00030006 -+#define VC_TAG_GET_MAX_TEMP 0x0003000A -+ -+/* --- STRUCTS --- */ -+struct bcm2835_hwmon_data { -+ struct device *hwmon_dev; -+}; -+ -+/* tag part of the message */ -+struct vc_msg_tag { -+ uint32_t tag_id; /* the tag ID for the temperature */ -+ uint32_t buffer_size; /* size of the buffer (should be 8) */ -+ uint32_t request_code; /* identifies message as a request (should be 0) */ -+ uint32_t id; /* extra ID field (should be 0) */ -+ uint32_t val; /* returned value of the temperature */ -+}; -+ -+/* message structure to be sent to videocore */ -+struct vc_msg { -+ uint32_t msg_size; /* simply, sizeof(struct vc_msg) */ -+ uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */ -+ struct vc_msg_tag tag; /* the tag structure above to make */ -+ uint32_t end_tag; /* an end identifier, should be set to NULL */ -+}; -+ -+typedef enum { -+ TEMP, -+ MAX_TEMP, -+} temp_type; -+ -+/* --- PROTOTYPES --- */ -+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf); -+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf); -+ -+/* --- GLOBALS --- */ -+ -+static struct bcm2835_hwmon_data *bcm2835_data; -+static struct platform_driver bcm2835_hwmon_driver; -+ -+static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0); -+static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP); -+static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP); -+ -+static struct attribute* bcm2835_attributes[] = { -+ &sensor_dev_attr_name.dev_attr.attr, -+ &sensor_dev_attr_temp1_input.dev_attr.attr, -+ &sensor_dev_attr_temp1_max.dev_attr.attr, -+ NULL, -+}; -+ -+static struct attribute_group bcm2835_attr_group = { -+ .attrs = bcm2835_attributes, -+}; -+ -+/* --- FUNCTIONS --- */ -+ -+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf,"bcm2835_hwmon\n"); -+} -+ -+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct vc_msg msg; -+ int result; -+ uint temp = 0; -+ int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index; -+ -+ print_debug("IN"); -+ -+ /* wipe all previous message data */ -+ memset(&msg, 0, sizeof msg); -+ -+ /* determine the message type */ -+ if(index == TEMP) -+ msg.tag.tag_id = VC_TAG_GET_TEMP; -+ else if (index == MAX_TEMP) -+ msg.tag.tag_id = VC_TAG_GET_MAX_TEMP; -+ else -+ { -+ print_debug("Unknown temperature message!"); -+ return -EINVAL; -+ } -+ -+ msg.msg_size = sizeof msg; -+ msg.tag.buffer_size = 8; -+ -+ /* send the message */ -+ result = bcm_mailbox_property(&msg, sizeof msg); -+ -+ /* check if it was all ok and return the rate in milli degrees C */ -+ if (result == 0 && (msg.request_code & 0x80000000)) -+ temp = (uint)msg.tag.val; -+ #ifdef HWMON_DEBUG_ENABLE -+ else -+ print_debug("Failed to get temperature!"); -+ #endif -+ print_debug("Got temperature as %u",temp); -+ print_debug("OUT"); -+ return sprintf(buf, "%u\n", temp); -+} -+ -+ -+static int bcm2835_hwmon_probe(struct platform_device *pdev) -+{ -+ int err; -+ -+ print_debug("IN"); -+ print_debug("HWMON Driver has been probed!"); -+ -+ /* check that the device isn't null!*/ -+ if(pdev == NULL) -+ { -+ print_debug("Platform device is empty!"); -+ return -ENODEV; -+ } -+ -+ /* allocate memory for neccessary data */ -+ bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL); -+ if(!bcm2835_data) -+ { -+ print_debug("Unable to allocate memory for hwmon data!"); -+ err = -ENOMEM; -+ goto kzalloc_error; -+ } -+ -+ /* create the sysfs files */ -+ if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group)) -+ { -+ print_debug("Unable to create sysfs files!"); -+ err = -EFAULT; -+ goto sysfs_error; -+ } -+ -+ /* register the hwmon device */ -+ bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev); -+ if (IS_ERR(bcm2835_data->hwmon_dev)) -+ { -+ err = PTR_ERR(bcm2835_data->hwmon_dev); -+ goto hwmon_error; -+ } -+ print_debug("OUT"); -+ return 0; -+ -+ /* error goto's */ -+ hwmon_error: -+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -+ -+ sysfs_error: -+ kfree(bcm2835_data); -+ -+ kzalloc_error: -+ -+ return err; -+ -+} -+ -+static int bcm2835_hwmon_remove(struct platform_device *pdev) -+{ -+ print_debug("IN"); -+ hwmon_device_unregister(bcm2835_data->hwmon_dev); -+ -+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -+ print_debug("OUT"); -+ return 0; -+} -+ -+/* Hwmon Driver */ -+static struct platform_driver bcm2835_hwmon_driver = { -+ .probe = bcm2835_hwmon_probe, -+ .remove = bcm2835_hwmon_remove, -+ .driver = { -+ .name = "bcm2835_hwmon", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dorian Peake"); -+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip"); -+ -+module_platform_driver(bcm2835_hwmon_driver); + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index af40db0..4584b1e 100644 +index af40db0..ddc77ad 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -238,6 +238,12 @@ config INTEL_POWERCLAMP +@@ -238,6 +238,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. +config THERMAL_BCM2835 ++ depends on BCM2708_MBOX + tristate "BCM2835 Thermal Driver" + help + This will enable temperature monitoring for the Broadcom BCM2835 @@ -102677,10 +103420,10 @@ index fa0dc48..453d4d9 100644 obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c new file mode 100644 -index 0000000..85fceb5 +index 0000000..3bc80f1 --- /dev/null +++ b/drivers/thermal/bcm2835-thermal.c -@@ -0,0 +1,184 @@ +@@ -0,0 +1,190 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -102698,10 +103441,10 @@ index 0000000..85fceb5 +#include +#include +#include ++#include +#include +#include +#include -+#include +#include + + @@ -102850,13 +103593,19 @@ index 0000000..85fceb5 + .get_mode = bcm2835_get_mode, +}; + -+/* Thermal Driver */ ++static const struct of_device_id bcm2835_thermal_of_match_table[] = { ++ { .compatible = "brcm,bcm2835-thermal", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); ++ +static struct platform_driver bcm2835_thermal_driver = { + .probe = bcm2835_thermal_probe, + .remove = bcm2835_thermal_remove, + .driver = { + .name = "bcm2835_thermal", + .owner = THIS_MODULE, ++ .of_match_table = bcm2835_thermal_of_match_table, + }, +}; + @@ -102866,49 +103615,58 @@ index 0000000..85fceb5 + +module_platform_driver(bcm2835_thermal_driver); -From bb1c2fec8850e0e017e3b80f51df5dc850627555 Mon Sep 17 00:00:00 2001 +From 4d5da3fa21e1d94e38644bf9a5493bb677854e42 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Mon, 4 Nov 2013 18:56:10 +0000 -Subject: [PATCH 017/216] Add Chris Boot's i2c and spi drivers. +Date: Wed, 17 Jun 2015 15:41:33 +0100 +Subject: [PATCH 20/77] Add Chris Boot's spi driver. -i2c-bcm2708: fixed baudrate +spi: bcm2708: add device tree support -Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock). -In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits. -This resulted in incorrect setting of CDIV and higher baudrate than intended. -Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz -After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz -The correct baudrate is shown in the log after the cdiv > 0xffff correction. +Add DT support to driver and add to .dtsi file. +Setup pins and spidev in .dts file. +SPI is disabled by default. -Perform I2C combined transactions when possible +Signed-off-by: Noralf Tronnes -Perform I2C combined transactions whenever possible, within the -restrictions of the Broadcomm Serial Controller. +BCM2708: don't register SPI controller when using DT -Disable DONE interrupt during TA poll +The device for the SPI controller is in the Device Tree. +Only register the device when not using DT. -Prevent interrupt from being triggered if poll is missed and transfer -starts and finishes. +Signed-off-by: Noralf Tronnes -i2c: Make combined transactions optional and disabled by default +spi: bcm2835: make driver available on ARCH_BCM2708 + +Make this driver available on ARCH_BCM2708 + +Signed-off-by: Noralf Tronnes + +bcm2708: Remove the prohibition on mixing SPIDEV and DT + +spi-bcm2708: Prepare for Common Clock Framework migration + +As part of migrating to use the Common Clock Framework, replace clk_enable() +with clk_prepare_enable() and clk_disable() with clk_disable_unprepare(). +This does not affect behaviour under the current clock implementation. + +Also add a missing clk_disable_unprepare() in the probe error path. + +Signed-off-by: Noralf Tronnes --- - arch/arm/mach-bcm2708/Kconfig | 7 + - arch/arm/mach-bcm2708/bcm2708.c | 104 ++++++- - drivers/i2c/busses/Kconfig | 19 ++ - drivers/i2c/busses/Makefile | 2 + - drivers/i2c/busses/i2c-bcm2708.c | 449 ++++++++++++++++++++++++++++ - drivers/spi/Kconfig | 8 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-bcm2708.c | 626 +++++++++++++++++++++++++++++++++++++++ - 8 files changed, 1214 insertions(+), 2 deletions(-) - create mode 100644 drivers/i2c/busses/i2c-bcm2708.c + arch/arm/mach-bcm2708/Kconfig | 7 + + arch/arm/mach-bcm2708/bcm2708.c | 53 ++++ + arch/arm/mach-bcm2709/bcm2709.c | 53 ++++ + drivers/spi/Kconfig | 10 +- + drivers/spi/Makefile | 1 + + drivers/spi/spi-bcm2708.c | 635 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 758 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/spi-bcm2708.c diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 9355841..e151ed4 100644 +index 4cbda0c..68e3706 100644 --- a/arch/arm/mach-bcm2708/Kconfig +++ b/arch/arm/mach-bcm2708/Kconfig -@@ -31,4 +31,11 @@ config BCM2708_NOL2CACHE +@@ -35,4 +35,11 @@ config BCM2708_NOL2CACHE help Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. @@ -102921,50 +103679,18 @@ index 9355841..e151ed4 100644 + Binds spidev driver to the SPI0 master endmenu diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index bae8ba5..752dd46 100644 +index f2d9b03..e3aa6fc 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -31,6 +31,7 @@ - #include +@@ -34,6 +34,7 @@ #include #include + #include +#include + #include #include - #include -@@ -205,7 +206,6 @@ static struct clk osc_clk = { - - /* warning - the USB needs a clock > 34MHz */ - --#ifdef CONFIG_MMC_BCM2708 - static struct clk sdhost_clk = { - #ifdef CONFIG_ARCH_BCM2708_CHIPIT - .rate = 4000000, /* 4MHz */ -@@ -213,7 +213,6 @@ static struct clk sdhost_clk = { - .rate = 250000000, /* 250MHz */ - #endif - }; --#endif - - static struct clk_lookup lookups[] = { - { /* UART0 */ -@@ -223,6 +222,15 @@ static struct clk_lookup lookups[] = { - { /* USB */ - .dev_id = "bcm2708_usb", - .clk = &osc_clk, -+ }, { /* SPI */ -+ .dev_id = "bcm2708_spi.0", -+ .clk = &sdhost_clk, -+ }, { /* BSC0 */ -+ .dev_id = "bcm2708_i2c.0", -+ .clk = &sdhost_clk, -+ }, { /* BSC1 */ -+ .dev_id = "bcm2708_i2c.1", -+ .clk = &sdhost_clk, - } - }; - -@@ -499,6 +507,89 @@ static struct platform_device bcm2708_alsa_devices[] = { +@@ -505,6 +506,50 @@ static struct platform_device bcm2708_alsa_devices[] = { }, }; @@ -103012,580 +103738,136 @@ index bae8ba5..752dd46 100644 +}; +#endif + -+static struct resource bcm2708_bsc0_resources[] = { -+ { -+ .start = BSC0_BASE, -+ .end = BSC0_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc0_device = { -+ .name = "bcm2708_i2c", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), -+ .resource = bcm2708_bsc0_resources, -+}; -+ -+ -+static struct resource bcm2708_bsc1_resources[] = { -+ { -+ .start = BSC1_BASE, -+ .end = BSC1_BASE + SZ_256 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = INTERRUPT_I2C, -+ .end = INTERRUPT_I2C, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device bcm2708_bsc1_device = { -+ .name = "bcm2708_i2c", -+ .id = 1, -+ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), -+ .resource = bcm2708_bsc1_resources, -+}; -+ - static struct platform_device bcm2835_hwmon_device = { - .name = "bcm2835_hwmon", + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", }; -@@ -619,6 +710,10 @@ void __init bcm2708_init(void) +@@ -655,6 +700,8 @@ void __init bcm2708_init(void) for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); + bcm_register_device_dt(&bcm2708_alsa_devices[i]); -+ bcm_register_device(&bcm2708_spi_device); -+ bcm_register_device(&bcm2708_bsc0_device); -+ bcm_register_device(&bcm2708_bsc1_device); ++ bcm_register_device_dt(&bcm2708_spi_device); + - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); + bcm_register_device_dt(&bcm2835_thermal_device); -@@ -628,6 +723,11 @@ void __init bcm2708_init(void) + if (!use_dt) { +@@ -665,6 +712,12 @@ void __init bcm2708_init(void) } system_rev = boardrev; system_serial_low = serial; + +#ifdef CONFIG_BCM2708_SPIDEV -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); ++ if (!use_dt) ++ spi_register_board_info(bcm2708_spi_devices, ++ ARRAY_SIZE(bcm2708_spi_devices)); +#endif } static void timer_set_mode(enum clock_event_mode mode, -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 22da9c2..00c7baa 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" - comment "PC SMBus host controller drivers" - depends on PCI +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 9631bdb..5fb99b6 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include -+config I2C_BCM2708 -+ tristate "BCM2708 BSC" -+ depends on MACH_BCM2708 -+ help -+ Enabling this option will add BSC (Broadcom Serial Controller) -+ support for the BCM2708. BSC is a Broadcom proprietary bus compatible -+ with I2C/TWI/SMBus. -+ -+config I2C_BCM2708_BAUDRATE -+ prompt "BCM2708 I2C baudrate" -+ depends on I2C_BCM2708 -+ int -+ default 100000 -+ help -+ Set the I2C baudrate. This will alter the default value. A -+ different baudrate can be set by using a module parameter as well. If -+ no parameter is provided when loading, this is the value that will be -+ used. -+ - config I2C_ALI1535 - tristate "ALI 1535" - depends on PCI -diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 3638feb..4905fae 100644 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -2,6 +2,8 @@ - # Makefile for the i2c bus drivers. - # + #include +@@ -525,6 +526,50 @@ static struct platform_device bcm2708_alsa_devices[] = { + }, + }; -+obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o -+ - # ACPI drivers - obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -new file mode 100644 -index 0000000..7d385a3 ---- /dev/null -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -0,0 +1,449 @@ -+/* -+ * Driver for Broadcom BCM2708 BSC Controllers -+ * -+ * Copyright (C) 2012 Chris Boot & Frank Buss -+ * -+ * This driver is inspired by: -+ * i2c-ocores.c, by Peter Korsgaard -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* BSC register offsets */ -+#define BSC_C 0x00 -+#define BSC_S 0x04 -+#define BSC_DLEN 0x08 -+#define BSC_A 0x0c -+#define BSC_FIFO 0x10 -+#define BSC_DIV 0x14 -+#define BSC_DEL 0x18 -+#define BSC_CLKT 0x1c -+ -+/* Bitfields in BSC_C */ -+#define BSC_C_I2CEN 0x00008000 -+#define BSC_C_INTR 0x00000400 -+#define BSC_C_INTT 0x00000200 -+#define BSC_C_INTD 0x00000100 -+#define BSC_C_ST 0x00000080 -+#define BSC_C_CLEAR_1 0x00000020 -+#define BSC_C_CLEAR_2 0x00000010 -+#define BSC_C_READ 0x00000001 -+ -+/* Bitfields in BSC_S */ -+#define BSC_S_CLKT 0x00000200 -+#define BSC_S_ERR 0x00000100 -+#define BSC_S_RXF 0x00000080 -+#define BSC_S_TXE 0x00000040 -+#define BSC_S_RXD 0x00000020 -+#define BSC_S_TXD 0x00000010 -+#define BSC_S_RXR 0x00000008 -+#define BSC_S_TXW 0x00000004 -+#define BSC_S_DONE 0x00000002 -+#define BSC_S_TA 0x00000001 -+ -+#define I2C_TIMEOUT_MS 150 -+ -+#define DRV_NAME "bcm2708_i2c" -+ -+static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; -+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(baudrate, "The I2C baudrate"); -+ -+static bool combined = false; -+module_param(combined, bool, 0644); -+MODULE_PARM_DESC(combined, "Use combined transactions"); -+ -+struct bcm2708_i2c { -+ struct i2c_adapter adapter; -+ -+ spinlock_t lock; -+ void __iomem *base; -+ int irq; -+ struct clk *clk; -+ -+ struct completion done; -+ -+ struct i2c_msg *msg; -+ int pos; -+ int nmsgs; -+ bool error; -+}; -+ -+/* -+ * This function sets the ALT mode on the I2C pins so that we can use them with -+ * the BSC hardware. -+ * -+ * FIXME: This is a hack. Use pinmux / pinctrl. -+ */ -+static void bcm2708_i2c_init_pinmode(int id) -+{ -+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) -+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) -+ -+ int pin; -+ u32 *gpio = ioremap(GPIO_BASE, SZ_16K); -+ -+ BUG_ON(id != 0 && id != 1); -+ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ -+ for (pin = id*2+0; pin <= id*2+1; pin++) { -+printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); -+ INP_GPIO(pin); /* set mode to GPIO input first */ -+ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ -+ } -+ -+ iounmap(gpio); -+ -+#undef INP_GPIO -+#undef SET_GPIO_ALT -+} -+ -+static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg) -+{ -+ return readl(bi->base + reg); -+} -+ -+static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) -+{ -+ writel(val, bi->base + reg); -+} -+ -+static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) -+{ -+ bcm2708_wr(bi, BSC_C, 0); -+ bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); -+} -+ -+static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi) -+{ -+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len)) -+ bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO); -+} -+ -+static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) -+{ -+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len)) -+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+} -+ -+static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) -+{ -+ unsigned long bus_hz; -+ u32 cdiv, s; -+ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; -+ -+ bus_hz = clk_get_rate(bi->clk); -+ cdiv = bus_hz / baudrate; -+ if (cdiv > 0xffff) -+ cdiv = 0xffff; -+ -+ if (bi->msg->flags & I2C_M_RD) -+ c |= BSC_C_INTR | BSC_C_READ; -+ else -+ c |= BSC_C_INTT; -+ -+ bcm2708_wr(bi, BSC_DIV, cdiv); -+ bcm2708_wr(bi, BSC_A, bi->msg->addr); -+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); -+ if (combined) ++static struct resource bcm2708_spi_resources[] = { + { -+ /* Do the next two messages meet combined transaction criteria? -+ - Current message is a write, next message is a read -+ - Both messages to same slave address -+ - Write message can fit inside FIFO (16 bytes or less) */ -+ if ( (bi->nmsgs > 1) && -+ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -+ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { -+ /* Fill FIFO with entire write message (16 byte FIFO) */ -+ while (bi->pos < bi->msg->len) -+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+ /* Start write transfer (no interrupts, don't clear FIFO) */ -+ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); -+ /* poll for transfer start bit (should only take 1-20 polls) */ -+ do { -+ s = bcm2708_rd(bi, BSC_S); -+ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE))); -+ /* Send next read message before the write transfer finishes. */ -+ bi->nmsgs--; -+ bi->msg++; -+ bi->pos = 0; -+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); -+ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ; -+ } ++ .start = SPI0_BASE, ++ .end = SPI0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_SPI, ++ .end = IRQ_SPI, ++ .flags = IORESOURCE_IRQ, + } -+ bcm2708_wr(bi, BSC_C, c); -+} -+ -+static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) -+{ -+ struct bcm2708_i2c *bi = dev_id; -+ bool handled = true; -+ u32 s; -+ -+ spin_lock(&bi->lock); -+ -+ /* we may see camera interrupts on the "other" I2C channel -+ Just return if we've not sent anything */ -+ if (!bi->nmsgs || !bi->msg ) -+ goto early_exit; -+ -+ s = bcm2708_rd(bi, BSC_S); -+ -+ if (s & (BSC_S_CLKT | BSC_S_ERR)) { -+ bcm2708_bsc_reset(bi); -+ bi->error = true; -+ -+ /* wake up our bh */ -+ complete(&bi->done); -+ } else if (s & BSC_S_DONE) { -+ bi->nmsgs--; -+ -+ if (bi->msg->flags & I2C_M_RD) -+ bcm2708_bsc_fifo_drain(bi); -+ -+ bcm2708_bsc_reset(bi); -+ -+ if (bi->nmsgs) { -+ /* advance to next message */ -+ bi->msg++; -+ bi->pos = 0; -+ bcm2708_bsc_setup(bi); -+ } else { -+ /* wake up our bh */ -+ complete(&bi->done); -+ } -+ } else if (s & BSC_S_TXW) { -+ bcm2708_bsc_fifo_fill(bi); -+ } else if (s & BSC_S_RXR) { -+ bcm2708_bsc_fifo_drain(bi); -+ } else { -+ handled = false; -+ } -+ -+early_exit: -+ spin_unlock(&bi->lock); -+ -+ return handled ? IRQ_HANDLED : IRQ_NONE; -+} -+ -+static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, -+ struct i2c_msg *msgs, int num) -+{ -+ struct bcm2708_i2c *bi = adap->algo_data; -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&bi->lock, flags); -+ -+ reinit_completion(&bi->done); -+ bi->msg = msgs; -+ bi->pos = 0; -+ bi->nmsgs = num; -+ bi->error = false; -+ -+ bcm2708_bsc_setup(bi); -+ -+ /* unlockig _after_ the setup to avoid races with the interrupt routine */ -+ spin_unlock_irqrestore(&bi->lock, flags); -+ -+ ret = wait_for_completion_timeout(&bi->done, -+ msecs_to_jiffies(I2C_TIMEOUT_MS)); -+ if (ret == 0) { -+ dev_err(&adap->dev, "transfer timed out\n"); -+ spin_lock_irqsave(&bi->lock, flags); -+ bcm2708_bsc_reset(bi); -+ spin_unlock_irqrestore(&bi->lock, flags); -+ return -ETIMEDOUT; -+ } -+ -+ return bi->error ? -EIO : num; -+} -+ -+static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL; -+} -+ -+static struct i2c_algorithm bcm2708_i2c_algorithm = { -+ .master_xfer = bcm2708_i2c_master_xfer, -+ .functionality = bcm2708_i2c_functionality, +}; + -+static int bcm2708_i2c_probe(struct platform_device *pdev) -+{ -+ struct resource *regs; -+ int irq, err = -ENOMEM; -+ struct clk *clk; -+ struct bcm2708_i2c *bi; -+ struct i2c_adapter *adap; -+ unsigned long bus_hz; -+ u32 cdiv; + -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) { -+ dev_err(&pdev->dev, "could not get IO memory\n"); -+ return -ENXIO; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "could not get IRQ\n"); -+ return irq; -+ } -+ -+ clk = clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk)); -+ return PTR_ERR(clk); -+ } -+ -+ bcm2708_i2c_init_pinmode(pdev->id); -+ -+ bi = kzalloc(sizeof(*bi), GFP_KERNEL); -+ if (!bi) -+ goto out_clk_put; -+ -+ platform_set_drvdata(pdev, bi); -+ -+ adap = &bi->adapter; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC; -+ adap->algo = &bcm2708_i2c_algorithm; -+ adap->algo_data = bi; -+ adap->dev.parent = &pdev->dev; -+ adap->nr = pdev->id; -+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ -+ switch (pdev->id) { -+ case 0: -+ adap->class = I2C_CLASS_HWMON; -+ break; -+ case 1: -+ adap->class = I2C_CLASS_DDC; -+ break; -+ default: -+ dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n"); -+ err = -ENXIO; -+ goto out_free_bi; -+ } -+ -+ spin_lock_init(&bi->lock); -+ init_completion(&bi->done); -+ -+ bi->base = ioremap(regs->start, resource_size(regs)); -+ if (!bi->base) { -+ dev_err(&pdev->dev, "could not remap memory\n"); -+ goto out_free_bi; -+ } -+ -+ bi->irq = irq; -+ bi->clk = clk; -+ -+ err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED, -+ dev_name(&pdev->dev), bi); -+ if (err) { -+ dev_err(&pdev->dev, "could not request IRQ: %d\n", err); -+ goto out_iounmap; -+ } -+ -+ bcm2708_bsc_reset(bi); -+ -+ err = i2c_add_numbered_adapter(adap); -+ if (err < 0) { -+ dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); -+ goto out_free_irq; -+ } -+ -+ bus_hz = clk_get_rate(bi->clk); -+ cdiv = bus_hz / baudrate; -+ if (cdiv > 0xffff) { -+ cdiv = 0xffff; -+ baudrate = bus_hz / cdiv; -+ } -+ -+ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", -+ pdev->id, (unsigned long)regs->start, irq, baudrate); -+ -+ return 0; -+ -+out_free_irq: -+ free_irq(bi->irq, bi); -+out_iounmap: -+ iounmap(bi->base); -+out_free_bi: -+ kfree(bi); -+out_clk_put: -+ clk_put(clk); -+ return err; -+} -+ -+static int bcm2708_i2c_remove(struct platform_device *pdev) -+{ -+ struct bcm2708_i2c *bi = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ i2c_del_adapter(&bi->adapter); -+ free_irq(bi->irq, bi); -+ iounmap(bi->base); -+ clk_disable(bi->clk); -+ clk_put(bi->clk); -+ kfree(bi); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm2708_i2c_driver = { -+ .driver = { -+ .name = DRV_NAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = bcm2708_i2c_probe, -+ .remove = bcm2708_i2c_remove, ++static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++static struct platform_device bcm2708_spi_device = { ++ .name = "bcm2708_spi", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_spi_resources), ++ .resource = bcm2708_spi_resources, ++ .dev = { ++ .dma_mask = &bcm2708_spi_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, +}; + -+// module_platform_driver(bcm2708_i2c_driver); ++#ifdef CONFIG_BCM2708_SPIDEV ++static struct spi_board_info bcm2708_spi_devices[] = { ++#ifdef CONFIG_SPI_SPIDEV ++ { ++ .modalias = "spidev", ++ .max_speed_hz = 500000, ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_0, ++ }, { ++ .modalias = "spidev", ++ .max_speed_hz = 500000, ++ .bus_num = 0, ++ .chip_select = 1, ++ .mode = SPI_MODE_0, ++ } ++#endif ++}; ++#endif + + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -675,6 +720,8 @@ void __init bcm2709_init(void) + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device_dt(&bcm2708_alsa_devices[i]); + ++ bcm_register_device_dt(&bcm2708_spi_device); + -+static int __init bcm2708_i2c_init(void) -+{ -+ return platform_driver_register(&bcm2708_i2c_driver); -+} + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -685,6 +732,12 @@ void __init bcm2709_init(void) + } + system_rev = boardrev; + system_serial_low = serial; + -+static void __exit bcm2708_i2c_exit(void) -+{ -+ platform_driver_unregister(&bcm2708_i2c_driver); -+} -+ -+module_init(bcm2708_i2c_init); -+module_exit(bcm2708_i2c_exit); -+ -+ -+ -+MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); -+MODULE_AUTHOR("Chris Boot "); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:" DRV_NAME); ++#ifdef CONFIG_BCM2708_SPIDEV ++ if (!use_dt) ++ spi_register_board_info(bcm2708_spi_devices, ++ ARRAY_SIZE(bcm2708_spi_devices)); ++#endif + } + + #ifdef SYSTEM_TIMER diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index ab8dfbe..9628e75 100644 +index 72b0590..ea5e5de 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -86,6 +86,14 @@ config SPI_BCM2835 +@@ -77,7 +77,7 @@ config SPI_ATMEL + + config SPI_BCM2835 + tristate "BCM2835 SPI controller" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on GPIOLIB + help + This selects a driver for the Broadcom BCM2835 SPI master. +@@ -87,6 +87,14 @@ config SPI_BCM2835 is for the regular SPI controller. Slave mode operation is not also not supported. +config SPI_BCM2708 + tristate "BCM2708 SPI controller driver (SPI0)" -+ depends on MACH_BCM2708 ++ depends on MACH_BCM2708 || MACH_BCM2709 + help + This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This + driver is not compatible with the "Universal SPI Master" or the SPI slave @@ -103608,10 +103890,10 @@ index d8cbf65..0dcd03d 100644 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c new file mode 100644 -index 0000000..b04a57d +index 0000000..041b5e2 --- /dev/null +++ b/drivers/spi/spi-bcm2708.c -@@ -0,0 +1,626 @@ +@@ -0,0 +1,635 @@ +/* + * Driver for Broadcom BCM2708 SPI Controllers + * @@ -104126,6 +104408,7 @@ index 0000000..b04a57d + master->setup = bcm2708_spi_setup; + master->transfer = bcm2708_spi_transfer; + master->cleanup = bcm2708_spi_cleanup; ++ master->dev.of_node = pdev->dev.of_node; + platform_set_drvdata(pdev, master); + + bs = spi_master_get_devdata(master); @@ -104159,7 +104442,7 @@ index 0000000..b04a57d + } + + /* initialise the hardware */ -+ clk_enable(clk); ++ clk_prepare_enable(clk); + bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX); + + err = spi_register_master(master); @@ -104175,6 +104458,7 @@ index 0000000..b04a57d + +out_free_irq: + free_irq(bs->irq, master); ++ clk_disable_unprepare(bs->clk); +out_workqueue: + destroy_workqueue(bs->workq); +out_iounmap: @@ -104199,7 +104483,7 @@ index 0000000..b04a57d + + flush_work(&bs->work); + -+ clk_disable(bs->clk); ++ clk_disable_unprepare(bs->clk); + clk_put(bs->clk); + free_irq(bs->irq, master); + iounmap(bs->base); @@ -104209,10 +104493,17 @@ index 0000000..b04a57d + return 0; +} + ++static const struct of_device_id bcm2708_spi_match[] = { ++ { .compatible = "brcm,bcm2708-spi", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_spi_match); ++ +static struct platform_driver bcm2708_spi_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, ++ .of_match_table = bcm2708_spi_match, + }, + .probe = bcm2708_spi_probe, + .remove = bcm2708_spi_remove, @@ -104239,10 +104530,814 @@ index 0000000..b04a57d +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 530db15891390005623b20a03dda6ef6871607bc Mon Sep 17 00:00:00 2001 +From 75d6625177ee7e4746baf70b60380069d58231ba Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 17 Jun 2015 15:44:08 +0100 +Subject: [PATCH 21/77] Add Chris Boot's i2c driver + +i2c-bcm2708: fixed baudrate + +Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock). +In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits. +This resulted in incorrect setting of CDIV and higher baudrate than intended. +Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz +After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz +The correct baudrate is shown in the log after the cdiv > 0xffff correction. + +Perform I2C combined transactions when possible + +Perform I2C combined transactions whenever possible, within the +restrictions of the Broadcomm Serial Controller. + +Disable DONE interrupt during TA poll + +Prevent interrupt from being triggered if poll is missed and transfer +starts and finishes. + +i2c: Make combined transactions optional and disabled by default + +i2c: bcm2708: add device tree support + +Add DT support to driver and add to .dtsi file. +Setup pins in .dts file. +i2c is disabled by default. + +Signed-off-by: Noralf Tronnes + +bcm2708: don't register i2c controllers when using DT + +The devices for the i2c controllers are in the Device Tree. +Only register devices when not using DT. + +Signed-off-by: Noralf Tronnes + +I2C: Only register the I2C device for the current board revision + +i2c_bcm2708: Fix clock reference counting + +Fix grabbing lock from atomic context in i2c driver + +2 main changes: +- check for timeouts in the bcm2708_bsc_setup function as indicated by this comment: + /* poll for transfer start bit (should only take 1-20 polls) */ + This implies that the setup function can now fail so account for this everywhere it's called +- Removed the clk_get_rate call from inside the setup function as it locks a mutex and that's not ok since we call it from under a spin lock. + +i2c-bcm2708: When using DT, leave the GPIO setup to pinctrl +--- + arch/arm/mach-bcm2708/bcm2708.c | 51 ++++ + arch/arm/mach-bcm2709/bcm2709.c | 51 ++++ + drivers/i2c/busses/Kconfig | 21 +- + drivers/i2c/busses/Makefile | 2 + + drivers/i2c/busses/i2c-bcm2708.c | 522 +++++++++++++++++++++++++++++++++++++++ + 5 files changed, 646 insertions(+), 1 deletion(-) + create mode 100644 drivers/i2c/busses/i2c-bcm2708.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index e3aa6fc..efb3544 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -83,6 +83,7 @@ static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static bool vc_i2c_override = false; + + static unsigned use_dt = 0; + +@@ -550,6 +551,45 @@ static struct spi_board_info bcm2708_spi_devices[] = { + }; + #endif + ++static struct resource bcm2708_bsc0_resources[] = { ++ { ++ .start = BSC0_BASE, ++ .end = BSC0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc0_device = { ++ .name = "bcm2708_i2c", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), ++ .resource = bcm2708_bsc0_resources, ++}; ++ ++ ++static struct resource bcm2708_bsc1_resources[] = { ++ { ++ .start = BSC1_BASE, ++ .end = BSC1_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc1_device = { ++ .name = "bcm2708_i2c", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), ++ .resource = bcm2708_bsc1_resources, ++}; ++ + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -702,6 +742,15 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2708_spi_device); + ++ if (vc_i2c_override) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ } else { ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } ++ + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -893,3 +942,5 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(vc_i2c_override, bool, 0644); ++MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 5fb99b6..8017c50 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -85,6 +85,7 @@ static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static bool vc_i2c_override = false; + + static unsigned use_dt = 0; + +@@ -570,6 +571,45 @@ static struct spi_board_info bcm2708_spi_devices[] = { + }; + #endif + ++static struct resource bcm2708_bsc0_resources[] = { ++ { ++ .start = BSC0_BASE, ++ .end = BSC0_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc0_device = { ++ .name = "bcm2708_i2c", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), ++ .resource = bcm2708_bsc0_resources, ++}; ++ ++ ++static struct resource bcm2708_bsc1_resources[] = { ++ { ++ .start = BSC1_BASE, ++ .end = BSC1_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = INTERRUPT_I2C, ++ .end = INTERRUPT_I2C, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device bcm2708_bsc1_device = { ++ .name = "bcm2708_i2c", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), ++ .resource = bcm2708_bsc1_resources, ++}; ++ + static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; +@@ -722,6 +762,15 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2708_spi_device); + ++ if (vc_i2c_override) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { ++ bcm_register_device_dt(&bcm2708_bsc0_device); ++ } else { ++ bcm_register_device_dt(&bcm2708_bsc1_device); ++ } ++ + bcm_register_device_dt(&bcm2835_thermal_device); + + if (!use_dt) { +@@ -1061,3 +1110,5 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(vc_i2c_override, bool, 0644); ++MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 2255af2..5b0c772 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" + comment "PC SMBus host controller drivers" + depends on PCI + ++config I2C_BCM2708 ++ tristate "BCM2708 BSC" ++ depends on MACH_BCM2708 || MACH_BCM2709 ++ help ++ Enabling this option will add BSC (Broadcom Serial Controller) ++ support for the BCM2708. BSC is a Broadcom proprietary bus compatible ++ with I2C/TWI/SMBus. ++ ++config I2C_BCM2708_BAUDRATE ++ prompt "BCM2708 I2C baudrate" ++ depends on I2C_BCM2708 ++ int ++ default 100000 ++ help ++ Set the I2C baudrate. This will alter the default value. A ++ different baudrate can be set by using a module parameter as well. If ++ no parameter is provided when loading, this is the value that will be ++ used. ++ + config I2C_ALI1535 + tristate "ALI 1535" + depends on PCI +@@ -362,7 +381,7 @@ config I2C_AXXIA + + config I2C_BCM2835 + tristate "Broadcom BCM2835 I2C controller" +- depends on ARCH_BCM2835 ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + help + If you say yes to this option, support will be included for the + BCM2835 I2C controller. +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index cdf941d..e0176d7 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -2,6 +2,8 @@ + # Makefile for the i2c bus drivers. + # + ++obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o ++ + # ACPI drivers + obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o + +diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c +new file mode 100644 +index 0000000..8773203 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-bcm2708.c +@@ -0,0 +1,522 @@ ++/* ++ * Driver for Broadcom BCM2708 BSC Controllers ++ * ++ * Copyright (C) 2012 Chris Boot & Frank Buss ++ * ++ * This driver is inspired by: ++ * i2c-ocores.c, by Peter Korsgaard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* BSC register offsets */ ++#define BSC_C 0x00 ++#define BSC_S 0x04 ++#define BSC_DLEN 0x08 ++#define BSC_A 0x0c ++#define BSC_FIFO 0x10 ++#define BSC_DIV 0x14 ++#define BSC_DEL 0x18 ++#define BSC_CLKT 0x1c ++ ++/* Bitfields in BSC_C */ ++#define BSC_C_I2CEN 0x00008000 ++#define BSC_C_INTR 0x00000400 ++#define BSC_C_INTT 0x00000200 ++#define BSC_C_INTD 0x00000100 ++#define BSC_C_ST 0x00000080 ++#define BSC_C_CLEAR_1 0x00000020 ++#define BSC_C_CLEAR_2 0x00000010 ++#define BSC_C_READ 0x00000001 ++ ++/* Bitfields in BSC_S */ ++#define BSC_S_CLKT 0x00000200 ++#define BSC_S_ERR 0x00000100 ++#define BSC_S_RXF 0x00000080 ++#define BSC_S_TXE 0x00000040 ++#define BSC_S_RXD 0x00000020 ++#define BSC_S_TXD 0x00000010 ++#define BSC_S_RXR 0x00000008 ++#define BSC_S_TXW 0x00000004 ++#define BSC_S_DONE 0x00000002 ++#define BSC_S_TA 0x00000001 ++ ++#define I2C_TIMEOUT_MS 150 ++#define I2C_WAIT_LOOP_COUNT 40 ++ ++#define DRV_NAME "bcm2708_i2c" ++ ++static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; ++module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(baudrate, "The I2C baudrate"); ++ ++static bool combined = false; ++module_param(combined, bool, 0644); ++MODULE_PARM_DESC(combined, "Use combined transactions"); ++ ++struct bcm2708_i2c { ++ struct i2c_adapter adapter; ++ ++ spinlock_t lock; ++ void __iomem *base; ++ int irq; ++ struct clk *clk; ++ u32 cdiv; ++ ++ struct completion done; ++ ++ struct i2c_msg *msg; ++ int pos; ++ int nmsgs; ++ bool error; ++}; ++ ++/* ++ * This function sets the ALT mode on the I2C pins so that we can use them with ++ * the BSC hardware. ++ * ++ * FIXME: This is a hack. Use pinmux / pinctrl. ++ */ ++static void bcm2708_i2c_init_pinmode(int id) ++{ ++#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) ++#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) ++ ++ int pin; ++ u32 *gpio = ioremap(GPIO_BASE, SZ_16K); ++ ++ BUG_ON(id != 0 && id != 1); ++ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ ++ for (pin = id*2+0; pin <= id*2+1; pin++) { ++ printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); ++ INP_GPIO(pin); /* set mode to GPIO input first */ ++ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ ++ } ++ ++ iounmap(gpio); ++ ++#undef INP_GPIO ++#undef SET_GPIO_ALT ++} ++ ++static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg) ++{ ++ return readl(bi->base + reg); ++} ++ ++static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) ++{ ++ writel(val, bi->base + reg); ++} ++ ++static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) ++{ ++ bcm2708_wr(bi, BSC_C, 0); ++ bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); ++} ++ ++static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi) ++{ ++ while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len)) ++ bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO); ++} ++ ++static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) ++{ ++ while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len)) ++ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); ++} ++ ++static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi) ++{ ++ u32 cdiv, s; ++ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; ++ int wait_loops = I2C_WAIT_LOOP_COUNT; ++ ++ /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked. ++ * Use the value that we cached in the probe. ++ */ ++ cdiv = bi->cdiv; ++ ++ if (bi->msg->flags & I2C_M_RD) ++ c |= BSC_C_INTR | BSC_C_READ; ++ else ++ c |= BSC_C_INTT; ++ ++ bcm2708_wr(bi, BSC_DIV, cdiv); ++ bcm2708_wr(bi, BSC_A, bi->msg->addr); ++ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); ++ if (combined) ++ { ++ /* Do the next two messages meet combined transaction criteria? ++ - Current message is a write, next message is a read ++ - Both messages to same slave address ++ - Write message can fit inside FIFO (16 bytes or less) */ ++ if ( (bi->nmsgs > 1) && ++ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && ++ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { ++ /* Fill FIFO with entire write message (16 byte FIFO) */ ++ while (bi->pos < bi->msg->len) { ++ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); ++ } ++ /* Start write transfer (no interrupts, don't clear FIFO) */ ++ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); ++ ++ /* poll for transfer start bit (should only take 1-20 polls) */ ++ do { ++ s = bcm2708_rd(bi, BSC_S); ++ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0); ++ ++ /* did we time out or some error occured? */ ++ if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) { ++ return -1; ++ } ++ ++ /* Send next read message before the write transfer finishes. */ ++ bi->nmsgs--; ++ bi->msg++; ++ bi->pos = 0; ++ bcm2708_wr(bi, BSC_DLEN, bi->msg->len); ++ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ; ++ } ++ } ++ bcm2708_wr(bi, BSC_C, c); ++ ++ return 0; ++} ++ ++static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) ++{ ++ struct bcm2708_i2c *bi = dev_id; ++ bool handled = true; ++ u32 s; ++ int ret; ++ ++ spin_lock(&bi->lock); ++ ++ /* we may see camera interrupts on the "other" I2C channel ++ Just return if we've not sent anything */ ++ if (!bi->nmsgs || !bi->msg) { ++ goto early_exit; ++ } ++ ++ s = bcm2708_rd(bi, BSC_S); ++ ++ if (s & (BSC_S_CLKT | BSC_S_ERR)) { ++ bcm2708_bsc_reset(bi); ++ bi->error = true; ++ ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ } else if (s & BSC_S_DONE) { ++ bi->nmsgs--; ++ ++ if (bi->msg->flags & I2C_M_RD) { ++ bcm2708_bsc_fifo_drain(bi); ++ } ++ ++ bcm2708_bsc_reset(bi); ++ ++ if (bi->nmsgs) { ++ /* advance to next message */ ++ bi->msg++; ++ bi->pos = 0; ++ ret = bcm2708_bsc_setup(bi); ++ if (ret < 0) { ++ bcm2708_bsc_reset(bi); ++ bi->error = true; ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ goto early_exit; ++ } ++ } else { ++ bi->msg = 0; /* to inform the that all work is done */ ++ bi->nmsgs = 0; ++ /* wake up our bh */ ++ complete(&bi->done); ++ } ++ } else if (s & BSC_S_TXW) { ++ bcm2708_bsc_fifo_fill(bi); ++ } else if (s & BSC_S_RXR) { ++ bcm2708_bsc_fifo_drain(bi); ++ } else { ++ handled = false; ++ } ++ ++early_exit: ++ spin_unlock(&bi->lock); ++ ++ return handled ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct bcm2708_i2c *bi = adap->algo_data; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&bi->lock, flags); ++ ++ reinit_completion(&bi->done); ++ bi->msg = msgs; ++ bi->pos = 0; ++ bi->nmsgs = num; ++ bi->error = false; ++ ++ ret = bcm2708_bsc_setup(bi); ++ ++ spin_unlock_irqrestore(&bi->lock, flags); ++ ++ /* check the result of the setup */ ++ if (ret < 0) ++ { ++ dev_err(&adap->dev, "transfer setup timed out\n"); ++ goto error_timeout; ++ } ++ ++ ret = wait_for_completion_timeout(&bi->done, msecs_to_jiffies(I2C_TIMEOUT_MS)); ++ if (ret == 0) { ++ dev_err(&adap->dev, "transfer timed out\n"); ++ goto error_timeout; ++ } ++ ++ ret = bi->error ? -EIO : num; ++ return ret; ++ ++error_timeout: ++ spin_lock_irqsave(&bi->lock, flags); ++ bcm2708_bsc_reset(bi); ++ bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */ ++ bi->nmsgs = 0; ++ spin_unlock_irqrestore(&bi->lock, flags); ++ return -ETIMEDOUT; ++} ++ ++static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL; ++} ++ ++static struct i2c_algorithm bcm2708_i2c_algorithm = { ++ .master_xfer = bcm2708_i2c_master_xfer, ++ .functionality = bcm2708_i2c_functionality, ++}; ++ ++static int bcm2708_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int irq, err = -ENOMEM; ++ struct clk *clk; ++ struct bcm2708_i2c *bi; ++ struct i2c_adapter *adap; ++ unsigned long bus_hz; ++ u32 cdiv; ++ ++ if (pdev->dev.of_node) { ++ u32 bus_clk_rate; ++ pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c"); ++ if (pdev->id < 0) { ++ dev_err(&pdev->dev, "alias is missing\n"); ++ return -EINVAL; ++ } ++ if (!of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &bus_clk_rate)) ++ baudrate = bus_clk_rate; ++ else ++ dev_warn(&pdev->dev, ++ "Could not read clock-frequency property\n"); ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_err(&pdev->dev, "could not get IO memory\n"); ++ return -ENXIO; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "could not get IRQ\n"); ++ return irq; ++ } ++ ++ clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk)); ++ return PTR_ERR(clk); ++ } ++ ++ err = clk_prepare_enable(clk); ++ if (err) { ++ dev_err(&pdev->dev, "could not enable clk: %d\n", err); ++ goto out_clk_put; ++ } ++ ++ if (!pdev->dev.of_node) ++ bcm2708_i2c_init_pinmode(pdev->id); ++ ++ bi = kzalloc(sizeof(*bi), GFP_KERNEL); ++ if (!bi) ++ goto out_clk_disable; ++ ++ platform_set_drvdata(pdev, bi); ++ ++ adap = &bi->adapter; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC; ++ adap->algo = &bcm2708_i2c_algorithm; ++ adap->algo_data = bi; ++ adap->dev.parent = &pdev->dev; ++ adap->nr = pdev->id; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ switch (pdev->id) { ++ case 0: ++ adap->class = I2C_CLASS_HWMON; ++ break; ++ case 1: ++ adap->class = I2C_CLASS_DDC; ++ break; ++ default: ++ dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n"); ++ err = -ENXIO; ++ goto out_free_bi; ++ } ++ ++ spin_lock_init(&bi->lock); ++ init_completion(&bi->done); ++ ++ bi->base = ioremap(regs->start, resource_size(regs)); ++ if (!bi->base) { ++ dev_err(&pdev->dev, "could not remap memory\n"); ++ goto out_free_bi; ++ } ++ ++ bi->irq = irq; ++ bi->clk = clk; ++ ++ err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED, ++ dev_name(&pdev->dev), bi); ++ if (err) { ++ dev_err(&pdev->dev, "could not request IRQ: %d\n", err); ++ goto out_iounmap; ++ } ++ ++ bcm2708_bsc_reset(bi); ++ ++ err = i2c_add_numbered_adapter(adap); ++ if (err < 0) { ++ dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); ++ goto out_free_irq; ++ } ++ ++ bus_hz = clk_get_rate(bi->clk); ++ cdiv = bus_hz / baudrate; ++ if (cdiv > 0xffff) { ++ cdiv = 0xffff; ++ baudrate = bus_hz / cdiv; ++ } ++ bi->cdiv = cdiv; ++ ++ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", ++ pdev->id, (unsigned long)regs->start, irq, baudrate); ++ ++ return 0; ++ ++out_free_irq: ++ free_irq(bi->irq, bi); ++out_iounmap: ++ iounmap(bi->base); ++out_free_bi: ++ kfree(bi); ++out_clk_disable: ++ clk_disable_unprepare(clk); ++out_clk_put: ++ clk_put(clk); ++ return err; ++} ++ ++static int bcm2708_i2c_remove(struct platform_device *pdev) ++{ ++ struct bcm2708_i2c *bi = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ i2c_del_adapter(&bi->adapter); ++ free_irq(bi->irq, bi); ++ iounmap(bi->base); ++ clk_disable_unprepare(bi->clk); ++ clk_put(bi->clk); ++ kfree(bi); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm2708_i2c_of_match[] = { ++ { .compatible = "brcm,bcm2708-i2c" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match); ++ ++static struct platform_driver bcm2708_i2c_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2708_i2c_of_match, ++ }, ++ .probe = bcm2708_i2c_probe, ++ .remove = bcm2708_i2c_remove, ++}; ++ ++// module_platform_driver(bcm2708_i2c_driver); ++ ++ ++static int __init bcm2708_i2c_init(void) ++{ ++ return platform_driver_register(&bcm2708_i2c_driver); ++} ++ ++static void __exit bcm2708_i2c_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_i2c_driver); ++} ++ ++module_init(bcm2708_i2c_init); ++module_exit(bcm2708_i2c_exit); ++ ++ ++ ++MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); ++MODULE_AUTHOR("Chris Boot "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); + +From 87711afd62feac0850e063b279057c91fe0aabbf Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 018/216] bcm2835: add v4l2 camera device +Subject: [PATCH 22/77] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -104582,7 +105677,7 @@ index 0000000..c585a8f + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index d9b872b..2da9264 100644 +index 421f531..34ad311 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -104595,7 +105690,7 @@ index d9b872b..2da9264 100644 config VIDEO_VIA_CAMERA diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 3ec1547..d8d5927 100644 +index 8f85561..7b15c24 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -2,6 +2,8 @@ @@ -104609,7 +105704,7 @@ index 3ec1547..d8d5927 100644 diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig new file mode 100644 -index 0000000..2cb1a68 +index 0000000..99a5cbc --- /dev/null +++ b/drivers/media/platform/bcm2835/Kconfig @@ -0,0 +1,25 @@ @@ -104617,7 +105712,7 @@ index 0000000..2cb1a68 + +config VIDEO_BCM2835 + bool "Broadcom BCM2835 camera interface driver" -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709) ++ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) + ---help--- + Say Y here to enable camera host interface devices for + Broadcom BCM2835 SoC. This operates over the VCHIQ interface @@ -111569,6942 +112664,10 @@ index 0000000..9d1d11e + +#endif /* MMAL_VCHIQ_H */ -From 47303896a0462c49e8bf3e5ef31e744d891a30a4 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 6 Jul 2014 12:07:25 +0200 -Subject: [PATCH 019/216] spi-bcm2708: Prepare for Common Clock Framework - migration - -As part of migrating to use the Common Clock Framework, replace clk_enable() -with clk_prepare_enable() and clk_disable() with clk_disable_unprepare(). -This does not affect behaviour under the current clock implementation. - -Also add a missing clk_disable_unprepare() in the probe error path. - -Signed-off-by: Noralf Tronnes ---- - drivers/spi/spi-bcm2708.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c -index b04a57d..349d21f 100644 ---- a/drivers/spi/spi-bcm2708.c -+++ b/drivers/spi/spi-bcm2708.c -@@ -545,7 +545,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - } - - /* initialise the hardware */ -- clk_enable(clk); -+ clk_prepare_enable(clk); - bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX); - - err = spi_register_master(master); -@@ -561,6 +561,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - - out_free_irq: - free_irq(bs->irq, master); -+ clk_disable_unprepare(bs->clk); - out_workqueue: - destroy_workqueue(bs->workq); - out_iounmap: -@@ -585,7 +586,7 @@ static int bcm2708_spi_remove(struct platform_device *pdev) - - flush_work(&bs->work); - -- clk_disable(bs->clk); -+ clk_disable_unprepare(bs->clk); - clk_put(bs->clk); - free_irq(bs->irq, master); - iounmap(bs->base); - -From d8d78e0bb5731d6fb3f1f813dc795e98be064870 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 6 Jul 2014 12:09:30 +0200 -Subject: [PATCH 020/216] BCM2708: Migrate to the Common Clock Framework - -As part of moving towards using Device Tree, the Common Clock Framework -has to be used instead of the BCM2708 clock implementation. - -Selecting COMMON_CLK removes the need to set CLKDEV_LOOKUP and HAVE_CLK explicitly. - -CONFIG_ARCH_BCM2708_CHIPIT #ifdef's are removed. They are no longer in use. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/Kconfig | 3 +- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 79 +++++++++++++++++------------------------ - arch/arm/mach-bcm2708/clock.c | 61 ------------------------------- - arch/arm/mach-bcm2708/clock.h | 24 ------------- - 5 files changed, 34 insertions(+), 135 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/clock.c - delete mode 100644 arch/arm/mach-bcm2708/clock.h - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 9fcd395..c495965 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -373,11 +373,10 @@ config ARCH_BCM2708 - bool "Broadcom BCM2708 family" - select CPU_V6 - select ARM_AMBA -- select HAVE_CLK - select HAVE_SCHED_CLOCK - select NEED_MACH_GPIO_H - select NEED_MACH_MEMORY_H -- select CLKDEV_LOOKUP -+ select COMMON_CLK - select ARCH_HAS_CPUFREQ - select GENERIC_CLOCKEVENTS - select ARM_ERRATA_411920 -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index a722f3f..21e3521 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o dma.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 752dd46..080e260 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -27,6 +27,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -57,7 +59,6 @@ - - #include "bcm2708.h" - #include "armctrl.h" --#include "clock.h" - - #ifdef CONFIG_BCM_VC_CMA - #include -@@ -78,7 +79,7 @@ - - /* command line parameters */ - static unsigned boardrev, serial; --static unsigned uart_clock; -+static unsigned uart_clock = UART0_CLOCK; - static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; -@@ -188,51 +189,39 @@ static void __init bcm2708_clocksource_init(void) - } - } - -+struct clk __init *bcm2708_clk_register(const char *name, unsigned long fixed_rate) -+{ -+ struct clk *clk; - --/* -- * These are fixed clocks. -- */ --static struct clk ref24_clk = { -- .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */ --}; -+ clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, -+ fixed_rate); -+ if (IS_ERR(clk)) -+ pr_err("%s not registered\n", name); - --static struct clk osc_clk = { --#ifdef CONFIG_ARCH_BCM2708_CHIPIT -- .rate = 27000000, --#else -- .rate = 500000000, /* ARM clock is set from the VideoCore booter */ --#endif --}; -+ return clk; -+} - --/* warning - the USB needs a clock > 34MHz */ -+void __init bcm2708_register_clkdev(struct clk *clk, const char *name) -+{ -+ int ret; - --static struct clk sdhost_clk = { --#ifdef CONFIG_ARCH_BCM2708_CHIPIT -- .rate = 4000000, /* 4MHz */ --#else -- .rate = 250000000, /* 250MHz */ --#endif --}; -+ ret = clk_register_clkdev(clk, NULL, name); -+ if (ret) -+ pr_err("%s alias not registered\n", name); -+} - --static struct clk_lookup lookups[] = { -- { /* UART0 */ -- .dev_id = "dev:f1", -- .clk = &ref24_clk, -- }, -- { /* USB */ -- .dev_id = "bcm2708_usb", -- .clk = &osc_clk, -- }, { /* SPI */ -- .dev_id = "bcm2708_spi.0", -- .clk = &sdhost_clk, -- }, { /* BSC0 */ -- .dev_id = "bcm2708_i2c.0", -- .clk = &sdhost_clk, -- }, { /* BSC1 */ -- .dev_id = "bcm2708_i2c.1", -- .clk = &sdhost_clk, -- } --}; -+void __init bcm2708_init_clocks(void) -+{ -+ struct clk *clk; -+ -+ clk = bcm2708_clk_register("uart0_clk", uart_clock); -+ bcm2708_register_clkdev(clk, "dev:f1"); -+ -+ clk = bcm2708_clk_register("sdhost_clk", 250000000); -+ bcm2708_register_clkdev(clk, "bcm2708_spi.0"); -+ bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); -+ bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); -+} - - #define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } - #define UART0_DMA { 15, 14 } -@@ -685,11 +674,7 @@ void __init bcm2708_init(void) - printk("bcm2708.uart_clock = %d\n", uart_clock); - pm_power_off = bcm2708_power_off; - -- if (uart_clock) -- lookups[0].clk->rate = uart_clock; -- -- for (i = 0; i < ARRAY_SIZE(lookups); i++) -- clkdev_add(&lookups[i]); -+ bcm2708_init_clocks(); - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_dmaengine_device); -diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c -deleted file mode 100644 -index 4fc556e..0000000 ---- a/arch/arm/mach-bcm2708/clock.c -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "clock.h" -- --int clk_enable(struct clk *clk) --{ -- return 0; --} --EXPORT_SYMBOL(clk_enable); -- --void clk_disable(struct clk *clk) --{ --} --EXPORT_SYMBOL(clk_disable); -- --unsigned long clk_get_rate(struct clk *clk) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_get_rate); -- --long clk_round_rate(struct clk *clk, unsigned long rate) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_round_rate); -- --int clk_set_rate(struct clk *clk, unsigned long rate) --{ -- return -EIO; --} --EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h -deleted file mode 100644 -index 5f9d725..0000000 ---- a/arch/arm/mach-bcm2708/clock.h -+++ /dev/null -@@ -1,24 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --struct module; -- --struct clk { -- unsigned long rate; --}; - -From 5f8aad35cdb010ca9fc0c58cca2a5a11fce879ec Mon Sep 17 00:00:00 2001 -From: notro -Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 021/216] BCM2708: Add core Device Tree support - -Add the bare minimum needed to boot BCM2708 from a Device Tree. - -Signed-off-by: Noralf Tronnes - -BCM2708: DT: change 'axi' nodename to 'soc' - -Change DT node named 'axi' to 'soc' so it matches ARCH_BCM2835. -The VC4 bootloader fills in certain properties in the 'axi' subtree, -but since this is part of an upstreaming effort, the name is changed. - -Signed-off-by: Noralf Tronnes notro@tronnes.org - -BCM2708_DT: Correct length of the peripheral space ---- - arch/arm/boot/dts/Makefile | 21 ++++ - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 81 +++++++++++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 81 +++++++++++++++ - arch/arm/boot/dts/bcm2708.dtsi | 86 ++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 165 +++++++++++++++++++++++++++++++ - arch/arm/mach-bcm2708/Kconfig | 8 ++ - arch/arm/mach-bcm2708/bcm2708.c | 45 ++++++++- - 7 files changed, 484 insertions(+), 3 deletions(-) - create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts - create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts - create mode 100644 arch/arm/boot/dts/bcm2708.dtsi - create mode 100644 arch/arm/boot/dts/bcm2709.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 992ea0b..25fbf52 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,5 +1,17 @@ - ifeq ($(CONFIG_OF),y) - -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb -+dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb -+ -+# Raspberry Pi -+ifeq ($(CONFIG_BCM2708_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_BCM2709_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC -@@ -645,7 +657,16 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt6592-evb.dtb \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb -+ -+targets += dtbs dtbs_install -+targets += $(dtb-y) -+ - endif - - always := $(dtb-y) - clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) -+ DTC_FLAGS ?= -@ -+endif -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -new file mode 100644 -index 0000000..983c23f ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,81 @@ -+/dts-v1/; -+ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "Raspberry Pi Model B+"; -+ -+ aliases { -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -new file mode 100644 -index 0000000..d8c6d15 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,81 @@ -+/dts-v1/; -+ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "Raspberry Pi Model B"; -+ -+ aliases { -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&gpio { -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <28 29 30 31>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -new file mode 100644 -index 0000000..96b7311 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -0,0 +1,86 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ model = "BCM2708"; -+ -+ interrupt-parent = <&intc>; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ -+ soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x7e000000 0x20000000 0x01000000>; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -new file mode 100644 -index 0000000..15c7e65 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -0,0 +1,165 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ compatible = "brcm,bcm2709"; -+ model = "BCM2709"; -+ -+ interrupt-parent = <&intc>; -+ -+ chosen { -+ /* No padding required - the boot loader can do that. */ -+ bootargs = ""; -+ }; -+ -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x7e000000 0x3f000000 0x01000000>; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; -+ -+ arm-pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupts = <3 9>; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ clock-frequency = <19200000>; -+ interrupts = <3 0>, // PHYS_SECURE_PPI -+ <3 1>, // PHYS_NONSECURE_PPI -+ <3 3>, // VIRT_PPI -+ <3 2>; // HYP_PPI -+ always-on; -+ }; -+ -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ v7_cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf00>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf01>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf02>; -+ clock-frequency = <800000000>; -+ }; -+ -+ v7_cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0xf03>; -+ clock-frequency = <800000000>; -+ }; -+ }; -+ -+ __overrides__ { -+ arm_freq = <&v7_cpu0>, "clock-frequency:0", -+ <&v7_cpu1>, "clock-frequency:0", -+ <&v7_cpu2>, "clock-frequency:0", -+ <&v7_cpu3>, "clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index e151ed4..182e7ba 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -9,6 +9,14 @@ config MACH_BCM2708 - help - Include support for the Broadcom(R) BCM2708 platform. - -+config BCM2708_DT -+ bool "BCM2708 Device Tree support" -+ depends on MACH_BCM2708 -+ default n -+ select USE_OF -+ help -+ Enable Device Tree support for BCM2708 -+ - config BCM2708_GPIO - bool "BCM2708 gpio support" - depends on MACH_BCM2708 -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 080e260..496cbcd 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -33,7 +33,9 @@ - #include - #include - #include -+#include - #include -+#include - - #include - #include -@@ -84,6 +86,8 @@ static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - -+static unsigned use_dt = 0; -+ - static void __init bcm2708_init_led(void); - - void __init bcm2708_init_irq(void) -@@ -599,6 +603,16 @@ int __init bcm_register_device(struct platform_device *pdev) - return ret; - } - -+/* -+ * Use these macros for platform and i2c devices that are present in the -+ * Device Tree. This way the devices are only added on non-DT systems. -+ */ -+#define bcm_register_device_dt(pdev) \ -+ if (!use_dt) bcm_register_device(pdev) -+ -+#define i2c_register_board_info_dt(busnum, info, n) \ -+ if (!use_dt) i2c_register_board_info(busnum, info, n) -+ - int calc_rsts(int partition) - { - return PM_PASSWORD | -@@ -664,6 +678,24 @@ static void bcm2708_power_off(void) - } - } - -+#ifdef CONFIG_OF -+static void __init bcm2708_dt_init(void) -+{ -+ int ret; -+ -+ of_clk_init(NULL); -+ ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -+ if (ret) { -+ pr_err("of_platform_populate failed: %d\n", ret); -+ /* Proceed as if CONFIG_OF was not defined */ -+ } else { -+ use_dt = 1; -+ } -+} -+#else -+static void __init bcm2708_dt_init(void) { } -+#endif /* CONFIG_OF */ -+ - void __init bcm2708_init(void) - { - int i; -@@ -675,6 +707,7 @@ void __init bcm2708_init(void) - pm_power_off = bcm2708_power_off; - - bcm2708_init_clocks(); -+ bcm2708_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device(&bcm2708_dmaengine_device); -@@ -842,9 +875,9 @@ static struct platform_device bcm2708_led_device = { - - static void __init bcm2708_init_led(void) - { -- bcm2708_leds[0].gpio = disk_led_gpio; -- bcm2708_leds[0].active_low = disk_led_active_low; -- platform_device_register(&bcm2708_led_device); -+ bcm2708_leds[0].gpio = disk_led_gpio; -+ bcm2708_leds[0].active_low = disk_led_active_low; -+ bcm_register_device_dt(&bcm2708_led_device); - } - #else - static inline void bcm2708_init_led(void) -@@ -869,6 +902,11 @@ static void __init board_reserve(void) - #endif - } - -+static const char * const bcm2708_compat[] = { -+ "brcm,bcm2708", -+ NULL -+}; -+ - MACHINE_START(BCM2708, "BCM2708") - /* Maintainer: Broadcom Europe Ltd. */ - .map_io = bcm2708_map_io, -@@ -878,6 +916,7 @@ MACHINE_START(BCM2708, "BCM2708") - .init_early = bcm2708_init_early, - .reserve = board_reserve, - .restart = bcm2708_restart, -+ .dt_compat = bcm2708_compat, - MACHINE_END - - module_param(boardrev, uint, 0644); - -From 55bd100cb5e042a279b944a4ff3c0f00c51ed64c Mon Sep 17 00:00:00 2001 -From: Siarhei Siamashka -Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 022/216] fbdev: add FBIOCOPYAREA ioctl - -Based on the patch authored by Ali Gholami Rudi at - https://lkml.org/lkml/2009/7/13/153 - -Provide an ioctl for userspace applications, but only if this operation -is hardware accelerated (otherwide it does not make any sense). - -Signed-off-by: Siarhei Siamashka ---- - drivers/video/fbdev/core/fbmem.c | 30 ++++++++++++++++++++++++++++++ - include/uapi/linux/fb.h | 5 +++++ - 2 files changed, 35 insertions(+) - -diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index 0705d88..771992a 100644 ---- a/drivers/video/fbdev/core/fbmem.c -+++ b/drivers/video/fbdev/core/fbmem.c -@@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) - } - EXPORT_SYMBOL(fb_blank); - -+static int fb_copyarea_user(struct fb_info *info, -+ struct fb_copyarea *copy) -+{ -+ int ret = 0; -+ if (!lock_fb_info(info)) -+ return -ENODEV; -+ if (copy->dx + copy->width > info->var.xres || -+ copy->sx + copy->width > info->var.xres || -+ copy->dy + copy->height > info->var.yres || -+ copy->sy + copy->height > info->var.yres) { -+ ret = -EINVAL; -+ goto out; -+ } -+ info->fbops->fb_copyarea(info, copy); -+out: -+ unlock_fb_info(info); -+ return ret; -+} -+ - static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) - { -@@ -1094,6 +1113,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - struct fb_cmap cmap_from; - struct fb_cmap_user cmap; - struct fb_event event; -+ struct fb_copyarea copy; - void __user *argp = (void __user *)arg; - long ret = 0; - -@@ -1211,6 +1231,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - unlock_fb_info(info); - console_unlock(); - break; -+ case FBIOCOPYAREA: -+ if (info->flags & FBINFO_HWACCEL_COPYAREA) { -+ /* only provide this ioctl if it is accelerated */ -+ if (copy_from_user(©, argp, sizeof(copy))) -+ return -EFAULT; -+ ret = fb_copyarea_user(info, ©); -+ break; -+ } -+ /* fall through */ - default: - if (!lock_fb_info(info)) - return -ENODEV; -@@ -1365,6 +1394,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, - case FBIOPAN_DISPLAY: - case FBIOGET_CON2FBMAP: - case FBIOPUT_CON2FBMAP: -+ case FBIOCOPYAREA: - arg = (unsigned long) compat_ptr(arg); - case FBIOBLANK: - ret = do_fb_ioctl(info, cmd, arg); -diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h -index fb795c3..fa72af0 100644 ---- a/include/uapi/linux/fb.h -+++ b/include/uapi/linux/fb.h -@@ -34,6 +34,11 @@ - #define FBIOPUT_MODEINFO 0x4617 - #define FBIOGET_DISPINFO 0x4618 - #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) -+/* -+ * HACK: use 'z' in order not to clash with any other ioctl numbers which might -+ * be concurrently added to the mainline kernel -+ */ -+#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) - - #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ - #define FB_TYPE_PLANES 1 /* Non interleaved planes */ - -From ee44a85f3a6b76509c3de7ee16164e8d32eecc24 Mon Sep 17 00:00:00 2001 -From: Harm Hanemaaijer -Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 025/216] 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 -console monochrome imageblit function used to draw console text is -suboptimal for common pixel depths such as 16bpp and 32bpp. The existing -code is quite general and can deal with several pixel depths. By creating -special case functions for 16bpp and 32bpp, by far the most common pixel -formats used on modern systems, a significant speed-up is attained -which can be readily felt on ARM-based devices like the Raspberry Pi -and the Allwinner platform, but should help any platform using the -fb layer. - -The special case functions allow constant folding, eliminating a number -of instructions including divide operations, and allow the use of an -unrolled loop, eliminating instructions with a variable shift size, -reducing source memory access instructions, and eliminating excessive -branching. These unrolled loops also allow much better code optimization -by the C compiler. The code that selects which optimized variant is used -is also simplified, eliminating integer divide instructions. - -The speed-up, measured by timing 'cat file.txt' in the console, varies -between 40% and 70%, when testing on the Raspberry Pi and Allwinner -ARM-based platforms, depending on font size and the pixel depth, with -the greater benefit for 32bpp. - -Signed-off-by: Harm Hanemaaijer ---- - drivers/video/fbdev/core/cfbimgblt.c | 152 +++++++++++++++++++++++++++++++++-- - 1 file changed, 147 insertions(+), 5 deletions(-) - -diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c -index a2bb276..436494f 100644 ---- a/drivers/video/fbdev/core/cfbimgblt.c -+++ b/drivers/video/fbdev/core/cfbimgblt.c -@@ -28,6 +28,11 @@ - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. -+ * Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013: -+ * - Provide optimized versions of fast_imageblit for 16 and 32bpp that are -+ * significantly faster than the previous implementation. -+ * - Simplify the fast/slow_imageblit selection code, avoiding integer -+ * divides. - */ - #include - #include -@@ -262,6 +267,133 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * - } - } - -+/* -+ * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded -+ * into the code, main loop unrolled. -+ */ -+ -+static inline void fast_imageblit16(const struct fb_image *image, -+ struct fb_info *p, u8 __iomem * dst1, -+ u32 fgcolor, u32 bgcolor) -+{ -+ u32 fgx = fgcolor, bgx = bgcolor; -+ u32 spitch = (image->width + 7) / 8; -+ u32 end_mask, eorx; -+ const char *s = image->data, *src; -+ u32 __iomem *dst; -+ const u32 *tab = NULL; -+ int i, j, k; -+ -+ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; -+ -+ fgx <<= 16; -+ bgx <<= 16; -+ fgx |= fgcolor; -+ bgx |= bgcolor; -+ -+ eorx = fgx ^ bgx; -+ k = image->width / 2; -+ -+ for (i = image->height; i--;) { -+ dst = (u32 __iomem *) dst1; -+ src = s; -+ -+ j = k; -+ while (j >= 4) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 6) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 4) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 2) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[bits & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ src++; -+ j -= 4; -+ } -+ if (j != 0) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 6) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ if (j >= 2) { -+ end_mask = tab[(bits >> 4) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ if (j == 3) { -+ end_mask = tab[(bits >> 2) & 3]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst); -+ } -+ } -+ } -+ dst1 += p->fix.line_length; -+ s += spitch; -+ } -+} -+ -+/* -+ * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded -+ * into the code, main loop unrolled. -+ */ -+ -+static inline void fast_imageblit32(const struct fb_image *image, -+ struct fb_info *p, u8 __iomem * dst1, -+ u32 fgcolor, u32 bgcolor) -+{ -+ u32 fgx = fgcolor, bgx = bgcolor; -+ u32 spitch = (image->width + 7) / 8; -+ u32 end_mask, eorx; -+ const char *s = image->data, *src; -+ u32 __iomem *dst; -+ const u32 *tab = NULL; -+ int i, j, k; -+ -+ tab = cfb_tab32; -+ -+ eorx = fgx ^ bgx; -+ k = image->width; -+ -+ for (i = image->height; i--;) { -+ dst = (u32 __iomem *) dst1; -+ src = s; -+ -+ j = k; -+ while (j >= 8) { -+ u8 bits = *src; -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 6) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 5) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 4) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 3) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 2) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[(bits >> 1) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ end_mask = tab[bits & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ src++; -+ j -= 8; -+ } -+ if (j != 0) { -+ u32 bits = (u32) * src; -+ while (j > 1) { -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); -+ bits <<= 1; -+ j--; -+ } -+ end_mask = tab[(bits >> 7) & 1]; -+ FB_WRITEL((end_mask & eorx) ^ bgx, dst); -+ } -+ dst1 += p->fix.line_length; -+ s += spitch; -+ } -+} -+ - void cfb_imageblit(struct fb_info *p, const struct fb_image *image) - { - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; -@@ -294,11 +426,21 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) - bgcolor = image->bg_color; - } - -- if (32 % bpp == 0 && !start_index && !pitch_index && -- ((width & (32/bpp-1)) == 0) && -- bpp >= 8 && bpp <= 32) -- fast_imageblit(image, p, dst1, fgcolor, bgcolor); -- else -+ if (!start_index && !pitch_index) { -+ if (bpp == 32) -+ fast_imageblit32(image, p, dst1, fgcolor, -+ bgcolor); -+ else if (bpp == 16 && (width & 1) == 0) -+ fast_imageblit16(image, p, dst1, fgcolor, -+ bgcolor); -+ else if (bpp == 8 && (width & 3) == 0) -+ fast_imageblit(image, p, dst1, fgcolor, -+ bgcolor); -+ else -+ slow_imageblit(image, p, dst1, fgcolor, -+ bgcolor, -+ start_index, pitch_index); -+ } else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - -From 12b6956e3ba31498771d282025fc4a44b6648559 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 026/216] Allow mac address to be set in smsc95xx - -Signed-off-by: popcornmix ---- - drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 56 insertions(+) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 26423ad..e29a323 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -59,6 +59,7 @@ - #define SUSPEND_SUSPEND3 (0x08) - #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ - SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) -+#define MAC_ADDR_LEN (6) - - struct smsc95xx_priv { - u32 mac_cr; -@@ -74,6 +75,10 @@ static bool turbo_mode = true; - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - -+static char *macaddr = ":"; -+module_param(macaddr, charp, 0); -+MODULE_PARM_DESC(macaddr, "MAC address"); -+ - static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, - u32 *data, int in_pm) - { -@@ -763,8 +768,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); - } - -+/* Check the macaddr module parameter for a MAC address */ -+static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) -+{ -+ int i, j, got_num, num; -+ u8 mtbl[MAC_ADDR_LEN]; -+ -+ if (macaddr[0] == ':') -+ return 0; -+ -+ i = 0; -+ j = 0; -+ num = 0; -+ got_num = 0; -+ while (j < MAC_ADDR_LEN) { -+ if (macaddr[i] && macaddr[i] != ':') { -+ got_num++; -+ if ('0' <= macaddr[i] && macaddr[i] <= '9') -+ num = num * 16 + macaddr[i] - '0'; -+ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') -+ num = num * 16 + 10 + macaddr[i] - 'A'; -+ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') -+ num = num * 16 + 10 + macaddr[i] - 'a'; -+ else -+ break; -+ i++; -+ } else if (got_num == 2) { -+ mtbl[j++] = (u8) num; -+ num = 0; -+ got_num = 0; -+ i++; -+ } else { -+ break; -+ } -+ } -+ -+ if (j == MAC_ADDR_LEN) { -+ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " -+ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], -+ mtbl[3], mtbl[4], mtbl[5]); -+ for (i = 0; i < MAC_ADDR_LEN; i++) -+ dev_mac[i] = mtbl[i]; -+ return 1; -+ } else { -+ return 0; -+ } -+} -+ - static void smsc95xx_init_mac_address(struct usbnet *dev) - { -+ /* Check module parameters */ -+ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) -+ return; -+ - /* try reading mac address from EEPROM */ - if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { - -From 03ecfd1c727358b884730a06b05d072ef28ebffd Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 027/216] 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 -See: https://github.com/raspberrypi/linux/pull/457 - -Add bitbanging pullups, use them for w1-gpio - -Allows parasite power to work, uses module option pullup=1 - -bcm2708: Ensure 1-wire pullup is disabled by default, and expose as module parameter - -Signed-off-by: Alex J Lennon - -w1-gpio: Add gpiopin module parameter and correctly free up gpio pull-up pin, if set - -Signed-off-by: Alex J Lennon ---- - arch/arm/mach-bcm2708/bcm2708.c | 29 ++++++++++++++++++++++ - drivers/w1/masters/w1-gpio.c | 55 +++++++++++++++++++++++++++++++++++++---- - drivers/w1/w1.h | 6 +++++ - drivers/w1/w1_int.c | 14 +++++++++++ - drivers/w1/w1_io.c | 18 +++++++++++--- - 5 files changed, 114 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 496cbcd..5873f8b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -79,12 +80,19 @@ - */ - #define DMA_MASK_BITS_COMMON 32 - -+// use GPIO 4 for the one-wire GPIO pin, if enabled -+#define W1_GPIO 4 -+// ensure one-wire GPIO pullup is disabled by default -+#define W1_PULLUP -1 -+ - /* command line parameters */ - static unsigned boardrev, serial; - static unsigned uart_clock = UART0_CLOCK; - static unsigned disk_led_gpio = 16; - static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; -+static unsigned w1_gpio_pin = W1_GPIO; -+static unsigned w1_gpio_pullup = W1_PULLUP; - - static unsigned use_dt = 0; - -@@ -256,6 +264,20 @@ static struct platform_device bcm2708_dmaengine_device = { - .id = -1, - }; - -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+static struct w1_gpio_platform_data w1_gpio_pdata = { -+ .pin = W1_GPIO, -+ .ext_pullup_enable_pin = W1_PULLUP, -+ .is_open_drain = 0, -+}; -+ -+static struct platform_device w1_device = { -+ .name = "w1-gpio", -+ .id = -1, -+ .dev.platform_data = &w1_gpio_pdata, -+}; -+#endif -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -715,6 +737,11 @@ void __init bcm2708_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device(&bcm2708_gpio_device); - #endif -+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -+ w1_gpio_pdata.pin = w1_gpio_pin; -+ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -+ bcm_register_device_dt(&w1_device); -+#endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); -@@ -925,3 +952,5 @@ module_param(uart_clock, uint, 0644); - module_param(disk_led_gpio, uint, 0644); - module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); -+module_param(w1_gpio_pin, uint, 0644); -+module_param(w1_gpio_pullup, uint, 0644); -diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c -index b99a932..3ad15cc 100644 ---- a/drivers/w1/masters/w1-gpio.c -+++ b/drivers/w1/masters/w1-gpio.c -@@ -23,6 +23,15 @@ - #include "../w1.h" - #include "../w1_int.h" - -+static int w1_gpio_pullup = -1; -+static int w1_gpio_pullup_orig = -1; -+module_param_named(pullup, w1_gpio_pullup, int, 0); -+MODULE_PARM_DESC(pullup, "GPIO pin pullup number"); -+static int w1_gpio_pin = -1; -+static int w1_gpio_pin_orig = -1; -+module_param_named(gpiopin, w1_gpio_pin, int, 0); -+MODULE_PARM_DESC(gpiopin, "GPIO pin number"); -+ - static u8 w1_gpio_set_pullup(void *data, int delay) - { - struct w1_gpio_platform_data *pdata = data; -@@ -67,6 +76,16 @@ static u8 w1_gpio_read_bit(void *data) - return gpio_get_value(pdata->pin) ? 1 : 0; - } - -+static void w1_gpio_bitbang_pullup(void *data, u8 on) -+{ -+ struct w1_gpio_platform_data *pdata = data; -+ -+ if (on) -+ gpio_direction_output(pdata->pin, 1); -+ else -+ gpio_direction_input(pdata->pin); -+} -+ - #if defined(CONFIG_OF) - static struct of_device_id w1_gpio_dt_ids[] = { - { .compatible = "w1-gpio" }, -@@ -113,13 +132,15 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - static int w1_gpio_probe(struct platform_device *pdev) - { - struct w1_bus_master *master; -- struct w1_gpio_platform_data *pdata; -+ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; - int err; - -- if (of_have_populated_dt()) { -- err = w1_gpio_probe_dt(pdev); -- if (err < 0) -- return err; -+ if(pdata == NULL) { -+ if (of_have_populated_dt()) { -+ err = w1_gpio_probe_dt(pdev); -+ if (err < 0) -+ return err; -+ } - } - - pdata = dev_get_platdata(&pdev->dev); -@@ -136,6 +157,19 @@ static int w1_gpio_probe(struct platform_device *pdev) - return -ENOMEM; - } - -+ w1_gpio_pin_orig = pdata->pin; -+ w1_gpio_pullup_orig = pdata->ext_pullup_enable_pin; -+ -+ if(gpio_is_valid(w1_gpio_pin)) { -+ pdata->pin = w1_gpio_pin; -+ pdata->ext_pullup_enable_pin = -1; -+ } -+ if(gpio_is_valid(w1_gpio_pullup)) { -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup; -+ } -+ -+ dev_info(&pdev->dev, "gpio pin %d, gpio pullup pin %d\n", pdata->pin, pdata->ext_pullup_enable_pin); -+ - err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); - if (err) { - dev_err(&pdev->dev, "gpio_request (pin) failed\n"); -@@ -165,6 +199,14 @@ static int w1_gpio_probe(struct platform_device *pdev) - master->set_pullup = w1_gpio_set_pullup; - } - -+ if (gpio_is_valid(w1_gpio_pullup)) { -+ if (pdata->is_open_drain) -+ printk(KERN_ERR "w1-gpio 'pullup' option " -+ "doesn't work with open drain GPIO\n"); -+ else -+ master->bitbang_pullup = w1_gpio_bitbang_pullup; -+ } -+ - err = w1_add_master_device(master); - if (err) { - dev_err(&pdev->dev, "w1_add_master device failed\n"); -@@ -195,6 +237,9 @@ static int w1_gpio_remove(struct platform_device *pdev) - - w1_remove_master_device(master); - -+ pdata->pin = w1_gpio_pin_orig; -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_orig; -+ - return 0; - } - -diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 56a49ba..881d728 100644 ---- a/drivers/w1/w1.h -+++ b/drivers/w1/w1.h -@@ -171,6 +171,12 @@ struct w1_bus_master - - u8 (*set_pullup)(void *, int); - -+ /** -+ * Turns the pullup on/off in bitbanging mode, takes an on/off argument. -+ * @return -1=Error, 0=completed -+ */ -+ void (*bitbang_pullup) (void *, u8); -+ - void (*search)(void *, struct w1_master *, - u8, w1_slave_found_callback); - }; -diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c -index 47249a3..a4b4a8d 100644 ---- a/drivers/w1/w1_int.c -+++ b/drivers/w1/w1_int.c -@@ -123,6 +123,20 @@ int w1_add_master_device(struct w1_bus_master *master) - return(-EINVAL); - } - -+ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup -+ * and takes care of timing itself */ -+ if (!master->write_byte && !master->touch_bit && master->set_pullup) { -+ printk(KERN_ERR "w1_add_master_device: set_pullup requires " -+ "write_byte or touch_bit, disabling\n"); -+ master->set_pullup = NULL; -+ } -+ -+ if (master->set_pullup && master->bitbang_pullup) { -+ printk(KERN_ERR "w1_add_master_device: set_pullup should not " -+ "be set when bitbang_pullup is used, disabling\n"); -+ master->set_pullup = NULL; -+ } -+ - /* Lock until the device is added (or not) to w1_masters. */ - mutex_lock(&w1_mlock); - /* Search for the first available id (starting at 1). */ -diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c -index 2820924..fd0550f 100644 ---- a/drivers/w1/w1_io.c -+++ b/drivers/w1/w1_io.c -@@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) - static void w1_post_write(struct w1_master *dev) - { - if (dev->pullup_duration) { -- if (dev->enable_pullup && dev->bus_master->set_pullup) -- dev->bus_master->set_pullup(dev->bus_master->data, 0); -- else -+ if (dev->enable_pullup) { -+ if (dev->bus_master->set_pullup) { -+ dev->bus_master->set_pullup(dev-> -+ bus_master->data, -+ 0); -+ } else if (dev->bus_master->bitbang_pullup) { -+ dev->bus_master-> -+ bitbang_pullup(dev->bus_master->data, 1); -+ msleep(dev->pullup_duration); -+ dev->bus_master-> -+ bitbang_pullup(dev->bus_master->data, 0); -+ } -+ } else { - msleep(dev->pullup_duration); -+ } -+ - dev->pullup_duration = 0; - } - } - -From 4624b823abd044524b26cb4d7111564f141e540f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 029/216] config: Enable CONFIG_MEMCG, but leave it disabled - (due to memory cost). Enable with cgroup_enable=memory. - ---- - kernel/cgroup.c | 23 +++++++++++++++++++++++ - mm/memcontrol.c | 1 + - 2 files changed, 24 insertions(+) - -diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index 29a7b2c..54fd2f0 100644 ---- a/kernel/cgroup.c -+++ b/kernel/cgroup.c -@@ -5393,6 +5393,29 @@ static int __init cgroup_disable(char *str) - } - __setup("cgroup_disable=", cgroup_disable); - -+static int __init cgroup_enable(char *str) -+{ -+ struct cgroup_subsys *ss; -+ char *token; -+ int i; -+ -+ while ((token = strsep(&str, ",")) != NULL) { -+ if (!*token) -+ continue; -+ -+ for_each_subsys(ss, i) { -+ if (!strcmp(token, ss->name)) { -+ ss->disabled = 0; -+ printk(KERN_INFO "Enabling %s control group" -+ " subsystem\n", ss->name); -+ break; -+ } -+ } -+ } -+ return 1; -+} -+__setup("cgroup_enable=", cgroup_enable); -+ - static int __init cgroup_set_legacy_files_on_dfl(char *str) - { - printk("cgroup: using legacy files on the default hierarchy\n"); -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index b34ef4a..c2aa348 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -5391,6 +5391,7 @@ struct cgroup_subsys memory_cgrp_subsys = { - .dfl_cftypes = memory_files, - .legacy_cftypes = mem_cgroup_legacy_files, - .early_init = 0, -+ .disabled = 1, - }; - - /** - -From 14913d5804e6cc14027404667dbacd69267fd032 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:33:38 +0100 -Subject: [PATCH 030/216] ASoC: Add support for BCM2708 - -This driver adds support for digital audio (I2S) -for the BCM2708 SoC that is used by the -Raspberry Pi. External audio codecs can be -connected to the Raspberry Pi via P5 header. - -It relies on cyclic DMA engine support for BCM2708. - -Signed-off-by: Florian Meier - -ASoC: BCM2708: Add 24 bit support - -This adds 24 bit support to the I2S driver of the BCM2708. -Besides enabling the 24 bit flags, it includes two bug fixes: - -MMAP is not supported. Claiming this leads to strange issues -when the format of driver and file do not match. - -The datasheet states that the width extension bit should be set -for widths greater than 24, but greater or equal would be correct. -This follows from the definition of the width field. - -Signed-off-by: Florian Meier - -bcm2708-i2s: Update bclk_ratio to more correct values - -Move GPIO setup to hw_params. - -This is used to stop the I2S driver from breaking -the GPIO setup for other uses of the PCM interface - -Configure GPIOs for I2S based on revision/card settings - -With RPi model B+, assignment of the I2S GPIO pins has changed. -This patch uses the board revision to auto-detect the GPIOs used -for I2S. It also allows sound card drivers to set the GPIOs that -should be used. This is especially important with the Compute -Module. - -bcm2708-i2s: Avoid leak from iomap when accessing gpio - -bcm2708: Eliminate i2s debugfs directory error - -Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') -to avoid the name clash when registering debugfs entries. ---- - sound/soc/bcm/Kconfig | 11 + - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/bcm2708-i2s.c | 1009 +++++++++++++++++++++++++++++++++++++++++++ - sound/soc/bcm/bcm2708-i2s.h | 35 ++ - 4 files changed, 1059 insertions(+) - create mode 100644 sound/soc/bcm/bcm2708-i2s.c - create mode 100644 sound/soc/bcm/bcm2708-i2s.h - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 6a834e1..8642296 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -7,3 +7,14 @@ config SND_BCM2835_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2835 I2S interface. You will also need - to select the audio interfaces to support below. -+ -+config SND_BCM2708_SOC_I2S -+ tristate "SoC Audio support for the Broadcom BCM2708 I2S module" -+ depends on MACH_BCM2708 || MACH_BCM2709 -+ select REGMAP_MMIO -+ select SND_SOC_DMAENGINE_PCM -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ help -+ Say Y or M if you want to add support for codecs attached to -+ the BCM2708 I2S interface. You will also need -+ to select the audio interfaces to support below. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index bc816b7..f8bbe1f 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o - - obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - -+# BCM2708 Platform Support -+snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c -new file mode 100644 -index 0000000..a3b65dc ---- /dev/null -+++ b/sound/soc/bcm/bcm2708-i2s.c -@@ -0,0 +1,1009 @@ -+/* -+ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * Based on -+ * Raspberry Pi PCM I2S ALSA Driver -+ * Copyright (c) by Phil Poole 2013 -+ * -+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor -+ * Vladimir Barinov, -+ * Copyright (C) 2007 MontaVista Software, Inc., -+ * -+ * OMAP ALSA SoC DAI driver using McBSP port -+ * Copyright (C) 2008 Nokia Corporation -+ * Contact: Jarkko Nikula -+ * Peter Ujfalusi -+ * -+ * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver -+ * Author: Timur Tabi -+ * Copyright 2007-2010 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include "bcm2708-i2s.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* Clock registers */ -+#define BCM2708_CLK_PCMCTL_REG 0x00 -+#define BCM2708_CLK_PCMDIV_REG 0x04 -+ -+/* Clock register settings */ -+#define BCM2708_CLK_PASSWD (0x5a000000) -+#define BCM2708_CLK_PASSWD_MASK (0xff000000) -+#define BCM2708_CLK_MASH(v) ((v) << 9) -+#define BCM2708_CLK_FLIP BIT(8) -+#define BCM2708_CLK_BUSY BIT(7) -+#define BCM2708_CLK_KILL BIT(5) -+#define BCM2708_CLK_ENAB BIT(4) -+#define BCM2708_CLK_SRC(v) (v) -+ -+#define BCM2708_CLK_SHIFT (12) -+#define BCM2708_CLK_DIVI(v) ((v) << BCM2708_CLK_SHIFT) -+#define BCM2708_CLK_DIVF(v) (v) -+#define BCM2708_CLK_DIVF_MASK (0xFFF) -+ -+enum { -+ BCM2708_CLK_MASH_0 = 0, -+ BCM2708_CLK_MASH_1, -+ BCM2708_CLK_MASH_2, -+ BCM2708_CLK_MASH_3, -+}; -+ -+enum { -+ BCM2708_CLK_SRC_GND = 0, -+ BCM2708_CLK_SRC_OSC, -+ BCM2708_CLK_SRC_DBG0, -+ BCM2708_CLK_SRC_DBG1, -+ BCM2708_CLK_SRC_PLLA, -+ BCM2708_CLK_SRC_PLLC, -+ BCM2708_CLK_SRC_PLLD, -+ BCM2708_CLK_SRC_HDMI, -+}; -+ -+/* Most clocks are not useable (freq = 0) */ -+static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = { -+ [BCM2708_CLK_SRC_GND] = 0, -+ [BCM2708_CLK_SRC_OSC] = 19200000, -+ [BCM2708_CLK_SRC_DBG0] = 0, -+ [BCM2708_CLK_SRC_DBG1] = 0, -+ [BCM2708_CLK_SRC_PLLA] = 0, -+ [BCM2708_CLK_SRC_PLLC] = 0, -+ [BCM2708_CLK_SRC_PLLD] = 500000000, -+ [BCM2708_CLK_SRC_HDMI] = 0, -+}; -+ -+/* I2S registers */ -+#define BCM2708_I2S_CS_A_REG 0x00 -+#define BCM2708_I2S_FIFO_A_REG 0x04 -+#define BCM2708_I2S_MODE_A_REG 0x08 -+#define BCM2708_I2S_RXC_A_REG 0x0c -+#define BCM2708_I2S_TXC_A_REG 0x10 -+#define BCM2708_I2S_DREQ_A_REG 0x14 -+#define BCM2708_I2S_INTEN_A_REG 0x18 -+#define BCM2708_I2S_INTSTC_A_REG 0x1c -+#define BCM2708_I2S_GRAY_REG 0x20 -+ -+/* I2S register settings */ -+#define BCM2708_I2S_STBY BIT(25) -+#define BCM2708_I2S_SYNC BIT(24) -+#define BCM2708_I2S_RXSEX BIT(23) -+#define BCM2708_I2S_RXF BIT(22) -+#define BCM2708_I2S_TXE BIT(21) -+#define BCM2708_I2S_RXD BIT(20) -+#define BCM2708_I2S_TXD BIT(19) -+#define BCM2708_I2S_RXR BIT(18) -+#define BCM2708_I2S_TXW BIT(17) -+#define BCM2708_I2S_CS_RXERR BIT(16) -+#define BCM2708_I2S_CS_TXERR BIT(15) -+#define BCM2708_I2S_RXSYNC BIT(14) -+#define BCM2708_I2S_TXSYNC BIT(13) -+#define BCM2708_I2S_DMAEN BIT(9) -+#define BCM2708_I2S_RXTHR(v) ((v) << 7) -+#define BCM2708_I2S_TXTHR(v) ((v) << 5) -+#define BCM2708_I2S_RXCLR BIT(4) -+#define BCM2708_I2S_TXCLR BIT(3) -+#define BCM2708_I2S_TXON BIT(2) -+#define BCM2708_I2S_RXON BIT(1) -+#define BCM2708_I2S_EN (1) -+ -+#define BCM2708_I2S_CLKDIS BIT(28) -+#define BCM2708_I2S_PDMN BIT(27) -+#define BCM2708_I2S_PDME BIT(26) -+#define BCM2708_I2S_FRXP BIT(25) -+#define BCM2708_I2S_FTXP BIT(24) -+#define BCM2708_I2S_CLKM BIT(23) -+#define BCM2708_I2S_CLKI BIT(22) -+#define BCM2708_I2S_FSM BIT(21) -+#define BCM2708_I2S_FSI BIT(20) -+#define BCM2708_I2S_FLEN(v) ((v) << 10) -+#define BCM2708_I2S_FSLEN(v) (v) -+ -+#define BCM2708_I2S_CHWEX BIT(15) -+#define BCM2708_I2S_CHEN BIT(14) -+#define BCM2708_I2S_CHPOS(v) ((v) << 4) -+#define BCM2708_I2S_CHWID(v) (v) -+#define BCM2708_I2S_CH1(v) ((v) << 16) -+#define BCM2708_I2S_CH2(v) (v) -+ -+#define BCM2708_I2S_TX_PANIC(v) ((v) << 24) -+#define BCM2708_I2S_RX_PANIC(v) ((v) << 16) -+#define BCM2708_I2S_TX(v) ((v) << 8) -+#define BCM2708_I2S_RX(v) (v) -+ -+#define BCM2708_I2S_INT_RXERR BIT(3) -+#define BCM2708_I2S_INT_TXERR BIT(2) -+#define BCM2708_I2S_INT_RXR BIT(1) -+#define BCM2708_I2S_INT_TXW BIT(0) -+ -+/* I2S DMA interface */ -+#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004 -+#define BCM2708_DMA_DREQ_PCM_TX 2 -+#define BCM2708_DMA_DREQ_PCM_RX 3 -+ -+/* I2S pin configuration */ -+static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO; -+ -+/* General device struct */ -+struct bcm2708_i2s_dev { -+ struct device *dev; -+ struct snd_dmaengine_dai_dma_data dma_data[2]; -+ unsigned int fmt; -+ unsigned int bclk_ratio; -+ -+ struct regmap *i2s_regmap; -+ struct regmap *clk_regmap; -+}; -+ -+void bcm2708_i2s_set_gpio(int gpio) { -+ bcm2708_i2s_gpio=gpio; -+} -+EXPORT_SYMBOL(bcm2708_i2s_set_gpio); -+ -+ -+static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev) -+{ -+ /* Start the clock if in master mode */ -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ -+ switch (master) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ case SND_SOC_DAIFMT_CBS_CFM: -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void bcm2708_i2s_stop_clock(struct bcm2708_i2s_dev *dev) -+{ -+ uint32_t clkreg; -+ int timeout = 1000; -+ -+ /* Stop clock */ -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD); -+ -+ /* Wait for the BUSY flag going down */ -+ while (--timeout) { -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ if (!(clkreg & BCM2708_CLK_BUSY)) -+ break; -+ } -+ -+ if (!timeout) { -+ /* KILL the clock */ -+ dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD_MASK, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD); -+ } -+} -+ -+static void bcm2708_i2s_clear_fifos(struct bcm2708_i2s_dev *dev, -+ bool tx, bool rx) -+{ -+ int timeout = 1000; -+ uint32_t syncval; -+ uint32_t csreg; -+ uint32_t i2s_active_state; -+ uint32_t clkreg; -+ uint32_t clk_active_state; -+ uint32_t off; -+ uint32_t clr; -+ -+ off = tx ? BCM2708_I2S_TXON : 0; -+ off |= rx ? BCM2708_I2S_RXON : 0; -+ -+ clr = tx ? BCM2708_I2S_TXCLR : 0; -+ clr |= rx ? BCM2708_I2S_RXCLR : 0; -+ -+ /* Backup the current state */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ i2s_active_state = csreg & (BCM2708_I2S_RXON | BCM2708_I2S_TXON); -+ -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ clk_active_state = clkreg & BCM2708_CLK_ENAB; -+ -+ /* Start clock if not running */ -+ if (!clk_active_state) { -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ } -+ -+ /* Stop I2S module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, off, 0); -+ -+ /* -+ * Clear the FIFOs -+ * Requires at least 2 PCM clock cycles to take effect -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, clr, clr); -+ -+ /* Wait for 2 PCM clock cycles */ -+ -+ /* -+ * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back -+ * FIXME: This does not seem to work for slave mode! -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &syncval); -+ syncval &= BCM2708_I2S_SYNC; -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_SYNC, ~syncval); -+ -+ /* Wait for the SYNC flag changing it's state */ -+ while (--timeout) { -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ if ((csreg & BCM2708_I2S_SYNC) != syncval) -+ break; -+ } -+ -+ if (!timeout) -+ dev_err(dev->dev, "I2S SYNC error!\n"); -+ -+ /* Stop clock if it was not running before */ -+ if (!clk_active_state) -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Restore I2S state */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXON | BCM2708_I2S_TXON, i2s_active_state); -+} -+ -+static int bcm2708_i2s_set_dai_fmt(struct snd_soc_dai *dai, -+ unsigned int fmt) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->fmt = fmt; -+ return 0; -+} -+ -+static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, -+ unsigned int ratio) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->bclk_ratio = ratio; -+ return 0; -+} -+ -+ -+static int bcm2708_i2s_set_function(unsigned offset, int function) -+{ -+ #define GPIOFSEL(x) (0x00+(x)*4) -+ void __iomem *gpio = __io_address(GPIO_BASE); -+ unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2; -+ unsigned gpiodir; -+ unsigned gpio_bank = offset / 10; -+ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; -+ -+ if (offset >= BCM2708_NR_GPIOS) -+ return -EINVAL; -+ -+ gpiodir = readl(gpio + GPIOFSEL(gpio_bank)); -+ gpiodir &= ~(7 << gpio_field_offset); -+ gpiodir |= alt << gpio_field_offset; -+ writel(gpiodir, gpio + GPIOFSEL(gpio_bank)); -+ return 0; -+} -+ -+static void bcm2708_i2s_setup_gpio(void) -+{ -+ /* -+ * This is the common way to handle the GPIO pins for -+ * the Raspberry Pi. -+ * TODO Better way would be to handle -+ * this in the device tree! -+ */ -+ int pin,pinconfig,startpin,alt; -+ -+ /* SPI is on different GPIOs on different boards */ -+ /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */ -+ if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) { -+ if ((system_rev & 0xffffff) >= 0x10) { -+ /* Model B+ */ -+ pinconfig=BCM2708_I2S_GPIO_PIN18; -+ } else { -+ /* original */ -+ pinconfig=BCM2708_I2S_GPIO_PIN28; -+ } -+ } else { -+ pinconfig=bcm2708_i2s_gpio; -+ } -+ -+ if (pinconfig==BCM2708_I2S_GPIO_PIN18) { -+ startpin=18; -+ alt=BCM2708_I2S_GPIO_PIN18_ALT; -+ } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) { -+ startpin=28; -+ alt=BCM2708_I2S_GPIO_PIN28_ALT; -+ } else { -+ printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig); -+ return; -+ } -+ -+ /* configure I2S pins to correct ALT mode */ -+ for (pin = startpin; pin <= startpin+3; pin++) { -+ bcm2708_i2s_set_function(pin, alt); -+ } -+} -+ -+static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ unsigned int sampling_rate = params_rate(params); -+ unsigned int data_length, data_delay, bclk_ratio; -+ unsigned int ch1pos, ch2pos, mode, format; -+ unsigned int mash = BCM2708_CLK_MASH_1; -+ unsigned int divi, divf, target_frequency; -+ int clk_src = -1; -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBS_CFM); -+ -+ bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBM_CFS); -+ uint32_t csreg; -+ -+ /* -+ * If a stream is already enabled, -+ * the registers are already set properly. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ -+ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON)) -+ return 0; -+ -+ -+ bcm2708_i2s_setup_gpio(); -+ -+ /* -+ * Adjust the data length according to the format. -+ * We prefill the half frame length with an integer -+ * divider of 2400 as explained at the clock settings. -+ * Maybe it is overwritten there, if the Integer mode -+ * does not apply. -+ */ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ data_length = 16; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ data_length = 24; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ data_length = 32; -+ bclk_ratio = 100; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* If bclk_ratio already set, use that one. */ -+ if (dev->bclk_ratio) -+ bclk_ratio = dev->bclk_ratio; -+ -+ /* -+ * Clock Settings -+ * -+ * The target frequency of the bit clock is -+ * sampling rate * frame length -+ * -+ * Integer mode: -+ * Sampling rates that are multiples of 8000 kHz -+ * can be driven by the oscillator of 19.2 MHz -+ * with an integer divider as long as the frame length -+ * is an integer divider of 19200000/8000=2400 as set up above. -+ * This is no longer possible if the sampling rate -+ * is too high (e.g. 192 kHz), because the oscillator is too slow. -+ * -+ * MASH mode: -+ * For all other sampling rates, it is not possible to -+ * have an integer divider. Approximate the clock -+ * with the MASH module that induces a slight frequency -+ * variance. To minimize that it is best to have the fastest -+ * clock here. That is PLLD with 500 MHz. -+ */ -+ target_frequency = sampling_rate * bclk_ratio; -+ clk_src = BCM2708_CLK_SRC_OSC; -+ mash = BCM2708_CLK_MASH_0; -+ -+ if (bcm2708_clk_freq[clk_src] % target_frequency == 0 -+ && bit_master && frame_master) { -+ divi = bcm2708_clk_freq[clk_src] / target_frequency; -+ divf = 0; -+ } else { -+ uint64_t dividend; -+ -+ if (!dev->bclk_ratio) { -+ /* -+ * Overwrite bclk_ratio, because the -+ * above trick is not needed or can -+ * not be used. -+ */ -+ bclk_ratio = 2 * data_length; -+ } -+ -+ target_frequency = sampling_rate * bclk_ratio; -+ -+ clk_src = BCM2708_CLK_SRC_PLLD; -+ mash = BCM2708_CLK_MASH_1; -+ -+ dividend = bcm2708_clk_freq[clk_src]; -+ dividend <<= BCM2708_CLK_SHIFT; -+ do_div(dividend, target_frequency); -+ divi = dividend >> BCM2708_CLK_SHIFT; -+ divf = dividend & BCM2708_CLK_DIVF_MASK; -+ } -+ -+ /* Clock should only be set up here if CPU is clock master */ -+ if (((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS) || -+ ((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFM)) { -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMDIV_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_DIVI(divi) -+ | BCM2708_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_MASH(mash) -+ | BCM2708_CLK_SRC(clk_src)); -+ } -+ -+ /* Setup the frame format */ -+ format = BCM2708_I2S_CHEN; -+ -+ if (data_length >= 24) -+ format |= BCM2708_I2S_CHWEX; -+ -+ format |= BCM2708_I2S_CHWID((data_length-8)&0xf); -+ -+ switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ data_delay = 1; -+ break; -+ default: -+ /* -+ * TODO -+ * Others are possible but are not implemented at the moment. -+ */ -+ dev_err(dev->dev, "%s:bad format\n", __func__); -+ return -EINVAL; -+ } -+ -+ ch1pos = data_delay; -+ ch2pos = bclk_ratio / 2 + data_delay; -+ -+ switch (params_channels(params)) { -+ case 2: -+ format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format); -+ format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos)); -+ format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * Set format for both streams. -+ * We cannot set another frame length -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_RXC_A_REG, format); -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_TXC_A_REG, format); -+ -+ /* Setup the I2S mode */ -+ mode = 0; -+ -+ if (data_length <= 16) { -+ /* -+ * Use frame packed mode (2 channels per 32 bit word) -+ * We cannot set another frame length in the second stream -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ mode |= BCM2708_I2S_FTXP | BCM2708_I2S_FRXP; -+ } -+ -+ mode |= BCM2708_I2S_FLEN(bclk_ratio - 1); -+ mode |= BCM2708_I2S_FSLEN(bclk_ratio / 2); -+ -+ /* Master or slave? */ -+ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* CPU is master */ -+ break; -+ case SND_SOC_DAIFMT_CBM_CFS: -+ /* -+ * CODEC is bit clock master -+ * CPU is frame master -+ */ -+ mode |= BCM2708_I2S_CLKM; -+ break; -+ case SND_SOC_DAIFMT_CBS_CFM: -+ /* -+ * CODEC is frame master -+ * CPU is bit clock master -+ */ -+ mode |= BCM2708_I2S_FSM; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ /* CODEC is master */ -+ mode |= BCM2708_I2S_CLKM; -+ mode |= BCM2708_I2S_FSM; -+ break; -+ default: -+ dev_err(dev->dev, "%s:bad master\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* -+ * Invert clocks? -+ * -+ * The BCM approach seems to be inverted to the classical I2S approach. -+ */ -+ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ /* None. Therefore, both for BCM */ -+ mode |= BCM2708_I2S_CLKI; -+ mode |= BCM2708_I2S_FSI; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ /* Both. Therefore, none for BCM */ -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ /* -+ * Invert only frame sync. Therefore, -+ * invert only bit clock for BCM -+ */ -+ mode |= BCM2708_I2S_CLKI; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ /* -+ * Invert only bit clock. Therefore, -+ * invert only frame sync for BCM -+ */ -+ mode |= BCM2708_I2S_FSI; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_MODE_A_REG, mode); -+ -+ /* Setup the DMA parameters */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXTHR(1) -+ | BCM2708_I2S_TXTHR(1) -+ | BCM2708_I2S_DMAEN, 0xffffffff); -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_DREQ_A_REG, -+ BCM2708_I2S_TX_PANIC(0x10) -+ | BCM2708_I2S_RX_PANIC(0x30) -+ | BCM2708_I2S_TX(0x30) -+ | BCM2708_I2S_RX(0x20), 0xffffffff); -+ -+ /* Clear FIFOs */ -+ bcm2708_i2s_clear_fifos(dev, true, true); -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_prepare(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t cs_reg; -+ -+ bcm2708_i2s_start_clock(dev); -+ -+ /* -+ * Clear both FIFOs if the one that should be started -+ * is not empty at the moment. This should only happen -+ * after overrun. Otherwise, hw_params would have cleared -+ * the FIFO. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &cs_reg); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK -+ && !(cs_reg & BCM2708_I2S_TXE)) -+ bcm2708_i2s_clear_fifos(dev, true, false); -+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE -+ && (cs_reg & BCM2708_I2S_RXD)) -+ bcm2708_i2s_clear_fifos(dev, false, true); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_stop(struct bcm2708_i2s_dev *dev, -+ struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ uint32_t mask; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, 0); -+ -+ /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ -+ if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static int bcm2708_i2s_trigger(struct snd_pcm_substream *substream, int cmd, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t mask; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ bcm2708_i2s_start_clock(dev); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, mask); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ bcm2708_i2s_stop(dev, substream, dai); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ if (dai->active) -+ return 0; -+ -+ /* Should this still be running stop it */ -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Enable PCM block */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, BCM2708_I2S_EN); -+ -+ /* -+ * Disable STBY. -+ * Requires at least 4 PCM clock cycles to take effect. -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_STBY, BCM2708_I2S_STBY); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ bcm2708_i2s_stop(dev, substream, dai); -+ -+ /* If both streams are stopped, disable module and clock */ -+ if (dai->active) -+ return; -+ -+ /* Disable the module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, 0); -+ -+ /* -+ * Stopping clock is necessary, because stop does -+ * not stop the clock when SND_SOC_DAIFMT_CONT -+ */ -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static const struct snd_soc_dai_ops bcm2708_i2s_dai_ops = { -+ .startup = bcm2708_i2s_startup, -+ .shutdown = bcm2708_i2s_shutdown, -+ .prepare = bcm2708_i2s_prepare, -+ .trigger = bcm2708_i2s_trigger, -+ .hw_params = bcm2708_i2s_hw_params, -+ .set_fmt = bcm2708_i2s_set_dai_fmt, -+ .set_bclk_ratio = bcm2708_i2s_set_dai_bclk_ratio -+}; -+ -+static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; -+ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ return 0; -+} -+ -+static struct snd_soc_dai_driver bcm2708_i2s_dai = { -+ .name = "bcm2708-i2s", -+ .probe = bcm2708_i2s_dai_probe, -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .capture = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .ops = &bcm2708_i2s_dai_ops, -+ .symmetric_rates = 1 -+}; -+ -+static bool bcm2708_i2s_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_CS_A_REG: -+ case BCM2708_I2S_FIFO_A_REG: -+ case BCM2708_I2S_INTSTC_A_REG: -+ case BCM2708_I2S_GRAY_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_i2s_precious_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_FIFO_A_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_clk_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_CLK_PCMCTL_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config bcm2708_regmap_config[] = { -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_I2S_GRAY_REG, -+ .precious_reg = bcm2708_i2s_precious_reg, -+ .volatile_reg = bcm2708_i2s_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ .name = "i2s", -+ }, -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_CLK_PCMDIV_REG, -+ .volatile_reg = bcm2708_clk_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ .name = "clk", -+ }, -+}; -+ -+static const struct snd_soc_component_driver bcm2708_i2s_component = { -+ .name = "bcm2708-i2s-comp", -+}; -+ -+static const struct snd_pcm_hardware bcm2708_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_JOINT_DUPLEX, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE, -+ .period_bytes_min = 32, -+ .period_bytes_max = 64 * PAGE_SIZE, -+ .periods_min = 2, -+ .periods_max = 255, -+ .buffer_bytes_max = 128 * PAGE_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &bcm2708_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ -+ -+static int bcm2708_i2s_probe(struct platform_device *pdev) -+{ -+ struct bcm2708_i2s_dev *dev; -+ int i; -+ int ret; -+ struct regmap *regmap[2]; -+ struct resource *mem[2]; -+ -+ /* Request both ioareas */ -+ for (i = 0; i <= 1; i++) { -+ void __iomem *base; -+ -+ mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); -+ base = devm_ioremap_resource(&pdev->dev, mem[i]); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, -+ &bcm2708_regmap_config[i]); -+ if (IS_ERR(regmap[i])) { -+ dev_err(&pdev->dev, "I2S probe: regmap init failed\n"); -+ return PTR_ERR(regmap[i]); -+ } -+ } -+ -+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), -+ GFP_KERNEL); -+ if (IS_ERR(dev)) -+ return PTR_ERR(dev); -+ -+ dev->i2s_regmap = regmap[0]; -+ dev->clk_regmap = regmap[1]; -+ -+ /* Set the DMA address */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ /* Set the DREQ */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id = -+ BCM2708_DMA_DREQ_PCM_TX; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id = -+ BCM2708_DMA_DREQ_PCM_RX; -+ -+ /* Set the bus width */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ -+ /* Set burst */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; -+ -+ /* BCLK ratio - use default */ -+ dev->bclk_ratio = 0; -+ -+ /* Store the pdev */ -+ dev->dev = &pdev->dev; -+ dev_set_drvdata(&pdev->dev, dev); -+ -+ ret = snd_soc_register_component(&pdev->dev, -+ &bcm2708_i2s_component, &bcm2708_i2s_dai, 1); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); -+ ret = -ENOMEM; -+ return ret; -+ } -+ -+ ret = snd_dmaengine_pcm_register(&pdev->dev, -+ &bcm2708_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); -+ snd_soc_unregister_component(&pdev->dev); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_remove(struct platform_device *pdev) -+{ -+ snd_dmaengine_pcm_unregister(&pdev->dev); -+ snd_soc_unregister_component(&pdev->dev); -+ return 0; -+} -+ -+static const struct of_device_id bcm2708_i2s_of_match[] = { -+ { .compatible = "brcm,bcm2708-i2s", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_i2s_of_match); -+ -+static struct platform_driver bcm2708_i2s_driver = { -+ .probe = bcm2708_i2s_probe, -+ .remove = bcm2708_i2s_remove, -+ .driver = { -+ .name = "bcm2708-i2s", -+ .owner = THIS_MODULE, -+ .of_match_table = bcm2708_i2s_of_match, -+ }, -+}; -+ -+module_platform_driver(bcm2708_i2s_driver); -+ -+MODULE_ALIAS("platform:bcm2708-i2s"); -+MODULE_DESCRIPTION("BCM2708 I2S interface"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/bcm/bcm2708-i2s.h b/sound/soc/bcm/bcm2708-i2s.h -new file mode 100644 -index 0000000..6fdcbc1 ---- /dev/null -+++ b/sound/soc/bcm/bcm2708-i2s.h -@@ -0,0 +1,35 @@ -+/* -+ * I2S configuration for sound cards. -+ * -+ * Copyright (c) 2014 Daniel Matuschek -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef BCM2708_I2S_H -+#define BCM2708_I2S_H -+ -+/* I2S pin assignment */ -+#define BCM2708_I2S_GPIO_AUTO 0 -+#define BCM2708_I2S_GPIO_PIN18 1 -+#define BCM2708_I2S_GPIO_PIN28 2 -+ -+/* Alt mode to enable I2S */ -+#define BCM2708_I2S_GPIO_PIN18_ALT 0 -+#define BCM2708_I2S_GPIO_PIN28_ALT 2 -+ -+extern void bcm2708_i2s_set_gpio(int gpio); -+ -+#endif - -From 95f9b87c32e716eb0276c9d6d1228db5a9e38a0e Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 031/216] ASoC: Add support for PCM5102A codec - -Some definitions to support the PCM5102A codec -by Texas Instruments. - -Signed-off-by: Florian Meier ---- - sound/soc/codecs/Kconfig | 4 +++ - sound/soc/codecs/Makefile | 2 ++ - sound/soc/codecs/pcm5102a.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 69 insertions(+) - create mode 100644 sound/soc/codecs/pcm5102a.c - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index ea9f0e3..bc39bbc 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -82,6 +82,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM512x_I2C if I2C - select SND_SOC_PCM512x_SPI if SPI_MASTER - select SND_SOC_RT286 if I2C -+ select SND_SOC_PCM5102A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -506,6 +507,9 @@ config SND_SOC_RT286 - tristate - depends on I2C - -+config SND_SOC_PCM5102A -+ tristate -+ - config SND_SOC_RT5631 - tristate "Realtek ALC5631/RT5631 CODEC" - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 69b8666..905ef6f 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -77,6 +77,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rt286-objs := rt286.o -+snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-rt5645-objs := rt5645.o -@@ -259,6 +260,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o -+obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o - obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -new file mode 100644 -index 0000000..126f1e9 ---- /dev/null -+++ b/sound/soc/codecs/pcm5102a.c -@@ -0,0 +1,63 @@ -+/* -+ * Driver for the PCM5102A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm5102a_dai = { -+ .name = "pcm5102a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; -+ -+static int pcm5102a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, -+ &pcm5102a_dai, 1); -+} -+ -+static int pcm5102a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm5102a_codec_driver = { -+ .probe = pcm5102a_probe, -+ .remove = pcm5102a_remove, -+ .driver = { -+ .name = "pcm5102a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm5102a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From b8442f0526d6de697deec639e36023a92a2d178a Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:04:54 +0100 -Subject: [PATCH 032/216] BCM2708: Add I2S support to board file - -Adds the required initializations for I2S -to the board file of mach-bcm2708. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5873f8b..7f4ebf4 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -613,6 +613,28 @@ static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; - -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+static struct resource bcm2708_i2s_resources[] = { -+ { -+ .start = I2S_BASE, -+ .end = I2S_BASE + 0x20, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = PCM_CLOCK_BASE, -+ .end = PCM_CLOCK_BASE + 0x02, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_i2s_device = { -+ .name = "bcm2708-i2s", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), -+ .resource = bcm2708_i2s_resources, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -762,6 +784,10 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); - -+#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -+ bcm_register_device_dt(&bcm2708_i2s_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - -From 40cf34f896f3ac88ad775464619175b5167ddacb Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 033/216] ASoC: Add support for HifiBerry DAC - -This adds a machine driver for the HifiBerry DAC. -It is a sound card that can -be stacked onto the Raspberry Pi. - -Signed-off-by: Florian Meier ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 5 +++ - sound/soc/bcm/hifiberry_dac.c | 100 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 112 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8642296..a92adb2 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -18,3 +18,10 @@ config SND_BCM2708_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2708 I2S interface. You will also need - to select the audio interfaces to support below. -+ -+config SND_BCM2708_SOC_HIFIBERRY_DAC -+ tristate "Support for HifiBerry DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM5102A -+ help -+ Say Y or M if you want to add support for HifiBerry DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index f8bbe1f..be90a49cb 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,3 +7,8 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o - - obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -+ -+# BCM2708 Machine Support -+snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -new file mode 100644 -index 0000000..4b70b45 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,100 @@ -+/* -+ * ASoC Driver for HifiBerry DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dac_ops = { -+ .hw_params = snd_rpi_hifiberry_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { -+{ -+ .name = "HifiBerry DAC", -+ .stream_name = "HifiBerry DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm5102a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm5102a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dac_ops, -+ .init = snd_rpi_hifiberry_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dac = { -+ .name = "snd_rpi_hifiberry_dac", -+ .dai_link = snd_rpi_hifiberry_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), -+}; -+ -+static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_dac_driver = { -+ .driver = { -+ .name = "snd-hifiberry-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_dac_probe, -+ .remove = snd_rpi_hifiberry_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); -+MODULE_LICENSE("GPL v2"); - -From c2ef063e2adb0e41654dc580ae959a86cde6f6f5 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:21:34 +0100 -Subject: [PATCH 034/216] BCM2708: Add HifiBerry DAC to board file - -This adds the initalization of the HifiBerry DAC -to the mach-bcm2708 board file. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7f4ebf4..94ce8fc 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -635,6 +635,20 @@ static struct platform_device bcm2708_i2s_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+static struct platform_device snd_hifiberry_dac_device = { -+ .name = "snd-hifiberry-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm5102a_codec_device = { -+ .name = "pcm5102a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -788,6 +802,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2708_i2s_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_dac_device); -+ bcm_register_device_dt(&snd_pcm5102a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - -From 1de129c2113a6fb145e654260b683e6c7e30bb51 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 6 Dec 2013 20:50:28 +0100 -Subject: [PATCH 035/216] ASoC: BCM2708: Add support for RPi-DAC - -This adds a machine driver for the RPi-DAC. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-dac.c | 97 +++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/Kconfig | 4 ++ - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm1794a.c | 62 ++++++++++++++++++++++++++ - 7 files changed, 193 insertions(+) - create mode 100644 sound/soc/bcm/rpi-dac.c - create mode 100644 sound/soc/codecs/pcm1794a.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 94ce8fc..fb955755 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,20 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+static struct platform_device snd_rpi_dac_device = { -+ .name = "snd-rpi-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm1794a_codec_device = { -+ .name = "pcm1794a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -807,6 +821,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_dac_device); -+ bcm_register_device_dt(&snd_pcm1794a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index a92adb2..64c61ac 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -25,3 +25,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - select SND_SOC_PCM5102A - help - Say Y or M if you want to add support for HifiBerry DAC. -+ -+config SND_BCM2708_SOC_RPI_DAC -+ tristate "Support for RPi-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM1794A -+ help -+ Say Y or M if you want to add support for RPi-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index be90a49cb..ccc9809 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,5 +10,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-rpi-dac-objs := rpi-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c -new file mode 100644 -index 0000000..6d6e0ba ---- /dev/null -+++ b/sound/soc/bcm/rpi-dac.c -@@ -0,0 +1,97 @@ -+/* -+ * ASoC Driver for RPi-DAC. -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_rpi_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_rpi_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_rpi_dac_ops = { -+ .hw_params = snd_rpi_rpi_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = { -+{ -+ .name = "RPi-DAC", -+ .stream_name = "RPi-DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm1794a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm1794a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_rpi_dac_ops, -+ .init = snd_rpi_rpi_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_rpi_dac = { -+ .name = "snd_rpi_rpi_dac", -+ .dai_link = snd_rpi_rpi_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_rpi_dac_dai), -+}; -+ -+static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_rpi_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_rpi_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_rpi_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_rpi_dac); -+} -+ -+static struct platform_driver snd_rpi_rpi_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_rpi_dac_probe, -+ .remove = snd_rpi_rpi_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_rpi_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index bc39bbc..8682bcf 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -83,6 +83,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM512x_SPI if SPI_MASTER - select SND_SOC_RT286 if I2C - select SND_SOC_PCM5102A if I2C -+ select SND_SOC_PCM1794A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -507,6 +508,9 @@ config SND_SOC_RT286 - tristate - depends on I2C - -+config SND_SOC_PCM1794A -+ tristate -+ - config SND_SOC_PCM5102A - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 905ef6f..c9bceba 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -77,6 +77,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o - snd-soc-pcm512x-spi-objs := pcm512x-spi.o - snd-soc-rl6231-objs := rl6231.o - snd-soc-rt286-objs := rt286.o -+snd-soc-pcm1794a-objs := pcm1794a.o - snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o -@@ -260,6 +261,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o - obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o - obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o - obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o -+obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o - obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o -diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c -new file mode 100644 -index 0000000..b4eaa44 ---- /dev/null -+++ b/sound/soc/codecs/pcm1794a.c -@@ -0,0 +1,62 @@ -+/* -+ * Driver for the PCM1794A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm1794a_dai = { -+ .name = "pcm1794a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm1794a; -+ -+static int pcm1794a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm1794a, -+ &pcm1794a_dai, 1); -+} -+ -+static int pcm1794a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm1794a_codec_driver = { -+ .probe = pcm1794a_probe, -+ .remove = pcm1794a_remove, -+ .driver = { -+ .name = "pcm1794a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm1794a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 11dea4325311685b8d38b791b519e74a561476ca Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 036/216] 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 - additional mclk_div divider, it is now possible to control the behaviour. - This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It - should allow lower jitter and better signal quality. The behavior has to be - controlled by the sound card driver, because some sample frequency share the - same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only - difference is the MCLK divider. - -This also added support for 32bit data. - -Signed-off-by: Daniel Matuschek ---- - sound/soc/codecs/wm8804.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index b2b0e68..ba2a0f8 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -278,6 +278,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, - blen = 0x1; - break; - case 24: -+ case 32: - blen = 0x2; - break; - default: -@@ -621,7 +622,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { - }; - - #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ -- SNDRV_PCM_FMTBIT_S24_LE) -+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) - - #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ - -From 84aed3cc8e8d60407b60cd132fe7a673024fb1a4 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 037/216] ASoC: BCM:Add support for HiFiBerry Digi. Driver is - based on the patched WM8804 driver. - -Signed-off-by: Daniel Matuschek ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 153 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 162 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_digi.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 64c61ac..d4a00fc 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - help - Say Y or M if you want to add support for HifiBerry DAC. - -+config SND_BCM2708_SOC_HIFIBERRY_DIGI -+ tristate "Support for HifiBerry Digi" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index ccc9809..826df7d 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,7 +10,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -new file mode 100644 -index 0000000..446ecdd ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,153 @@ -+/* -+ * ASoC Driver for HifiBerry Digi -+ * -+ * Author: Daniel Matuschek -+ * based on the HifiBerry DAC driver by Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/wm8804.h" -+ -+static int samplerate=44100; -+ -+static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ /* enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ int sysclk = 27000000; /* This is fixed on this board */ -+ -+ long mclk_freq=0; -+ int mclk_div=1; -+ -+ int ret; -+ -+ samplerate = params_rate(params); -+ -+ switch (samplerate) { -+ case 44100: -+ case 48000: -+ case 88200: -+ case 96000: -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ break; -+ case 176400: -+ case 192000: -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate\n"); -+ } -+ -+ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -+ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); -+ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, -+ sysclk, SND_SOC_CLOCK_OUT); -+ if (ret < 0) { -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK: %d\n", ret); -+ return ret; -+ } -+ -+ /* Enable TX output */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); -+ -+ /* Power on */ -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { -+ .hw_params = snd_rpi_hifiberry_digi_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { -+{ -+ .name = "HifiBerry Digi", -+ .stream_name = "HifiBerry Digi HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "wm8804-spdif", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_rpi_hifiberry_digi_ops, -+ .init = snd_rpi_hifiberry_digi_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_digi = { -+ .name = "snd_rpi_hifiberry_digi", -+ .dai_link = snd_rpi_hifiberry_digi_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), -+}; -+ -+static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_digi.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_digi_driver = { -+ .driver = { -+ .name = "snd-hifiberry-digi", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_digi_probe, -+ .remove = snd_rpi_hifiberry_digi_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_digi_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); -+MODULE_LICENSE("GPL v2"); - -From 4d5dd3c3d6019cf233add726cbe3aac6e543c540 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Thu, 16 Jan 2014 07:26:08 +0100 -Subject: [PATCH 038/216] BCM2708: Added support for HiFiBerry Digi board Board - initalization by I2C - -Signed-off-by: Daniel Matuschek ---- - arch/arm/mach-bcm2708/bcm2708.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index fb955755..0ad5343 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,21 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+static struct platform_device snd_hifiberry_digi_device = { -+ .name = "snd-hifiberry-digi", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("wm8804", 0x3b) -+ }, -+}; -+ -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - static struct platform_device snd_rpi_dac_device = { - .name = "snd-rpi-dac", -@@ -821,6 +836,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_digi_device); -+ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - bcm_register_device_dt(&snd_rpi_dac_device); - bcm_register_device_dt(&snd_pcm1794a_codec_device); - -From 963fd96f5747dd0c693a87cbb23bc1239d3bda72 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Thu, 16 Jan 2014 07:36:35 +0100 -Subject: [PATCH 039/216] ASoC: wm8804: Set idle_bias_off to false Idle bias - has been change to remove warning on driver startup - -Signed-off-by: Daniel Matuschek ---- - sound/soc/codecs/wm8804.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index ba2a0f8..91974f9 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -653,7 +653,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { - .probe = wm8804_probe, - .remove = wm8804_remove, - .set_bias_level = wm8804_set_bias_level, -- .idle_bias_off = true, -+ .idle_bias_off = false, - - .controls = wm8804_snd_controls, - .num_controls = ARRAY_SIZE(wm8804_snd_controls), - -From f5995e9c2cc2d801d5b05e3f4be0bdafb184943a Mon Sep 17 00:00:00 2001 -From: Gordon Garrity -Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 040/216] Add IQaudIO Sound Card support for Raspberry Pi - ---- - arch/arm/mach-bcm2708/bcm2708.c | 22 ++++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio-dac.c | 111 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 142 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio-dac.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 0ad5343..a812b51 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -678,6 +678,22 @@ static struct platform_device snd_pcm1794a_codec_device = { - }; - #endif - -+ -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+static struct platform_device snd_rpi_iqaudio_dac_device = { -+ .name = "snd-rpi-iqaudio-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+// Use the actual device name rather than generic driver name -+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4c) -+ }, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -846,6 +862,12 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm1794a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) -+ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); -+#endif -+ -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index d4a00fc..faa89ef 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -39,3 +39,10 @@ config SND_BCM2708_SOC_RPI_DAC - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. -+ -+config SND_BCM2708_SOC_IQAUDIO_DAC -+ tristate "Support for IQaudIO-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ help -+ Say Y or M if you want to add support for IQaudIO-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 826df7d..d597fb0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,7 +12,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -new file mode 100644 -index 0000000..8d0e2ae ---- /dev/null -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,111 @@ -+/* -+ * ASoC Driver for IQaudIO DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { -+ .hw_params = snd_rpi_iqaudio_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { -+{ -+ .name = "IQaudIO DAC", -+ .stream_name = "IQaudIO DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_iqaudio_dac_ops, -+ .init = snd_rpi_iqaudio_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_dac = { -+ .name = "IQaudIODAC", -+ .dai_link = snd_rpi_iqaudio_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), -+}; -+ -+static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); -+} -+ -+static const struct of_device_id iqaudio_of_match[] = { -+ { .compatible = "iqaudio,iqaudio-dac", }, -+ {}, -+}; -+ -+static struct platform_driver snd_rpi_iqaudio_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-iqaudio-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = iqaudio_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_dac_probe, -+ .remove = snd_rpi_iqaudio_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); -+MODULE_LICENSE("GPL v2"); - -From 5d1809ba161ed01404974ad13403d23a008bd181 Mon Sep 17 00:00:00 2001 -From: Howard Mitchell -Date: Mon, 2 Mar 2015 17:28:02 +0000 -Subject: [PATCH 041/216] Set a limit of 0dB on Digital Volume Control - -The main volume control in the PCM512x DAC has a range up to -+24dB. This is dangerously loud and can potentially cause massive -clipping in the output stages. Therefore this sets a sensible -limit of 0dB for this control. ---- - sound/soc/bcm/iqaudio-dac.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -index 8d0e2ae..aff7377 100644 ---- a/sound/soc/bcm/iqaudio-dac.c -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -25,7 +25,13 @@ - - static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) - { --// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ ret = snd_soc_limit_volume(codec, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); - - return 0; - } - -From 8dbd2bddafe5d604e9f03a702d5ae50c0dd791e6 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 042/216] vmstat: Workaround for issue where dirty page count - goes negative - -See: -https://github.com/raspberrypi/linux/issues/617 -http://www.spinics.net/lists/linux-mm/msg72236.html ---- - include/linux/vmstat.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h -index 82e7db7..f87d16d 100644 ---- a/include/linux/vmstat.h -+++ b/include/linux/vmstat.h -@@ -241,7 +241,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) - static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) - { - atomic_long_dec(&zone->vm_stat[item]); -+ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&zone->vm_stat[item]) < 0)) -+ atomic_long_set(&zone->vm_stat[item], 0); - atomic_long_dec(&vm_stat[item]); -+ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&vm_stat[item]) < 0)) -+ atomic_long_set(&vm_stat[item], 0); - } - - static inline void __inc_zone_page_state(struct page *page, - -From 15bf30debd62320326c6a474f69eabbf3b43029e Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 18:55:53 +0100 -Subject: [PATCH 043/216] BCM2708: armctrl: Add IRQ Device Tree support - -Add Device Tree IRQ support for BCM2708. -Usage is the same as for irq-bcm2835. -See binding document: brcm,bcm2835-armctrl-ic.txt - -A bank 3 is added to handle GPIO interrupts. This is done because -armctrl also handles GPIO interrupts. - -Signed-off-by: Noralf Tronnes - -BCM2708: armctrl: remove irq bank 3 - -irq bank 3 was needed by the pinctrl-bcm2708 and bcm2708_gpio -combination. It is no longer required. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/mach-bcm2708/armctrl.c | 96 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 96 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index 96fa9b9..74bacb3 100644 ---- a/arch/arm/mach-bcm2708/armctrl.c -+++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -23,6 +23,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -79,6 +81,99 @@ static void armctrl_unmask_irq(struct irq_data *d) - } - } - -+#ifdef CONFIG_OF -+ -+#define NR_IRQS_BANK0 21 -+#define NR_BANKS 3 -+#define IRQS_PER_BANK 32 -+ -+/* from drivers/irqchip/irq-bcm2835.c */ -+static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, -+ const u32 *intspec, unsigned int intsize, -+ unsigned long *out_hwirq, unsigned int *out_type) -+{ -+ if (WARN_ON(intsize != 2)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[0] >= NR_BANKS)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) -+ return -EINVAL; -+ -+ if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) -+ return -EINVAL; -+ -+ if (intspec[0] == 0) -+ *out_hwirq = ARM_IRQ0_BASE + intspec[1]; -+ else if (intspec[0] == 1) -+ *out_hwirq = ARM_IRQ1_BASE + intspec[1]; -+ else -+ *out_hwirq = ARM_IRQ2_BASE + intspec[1]; -+ -+ /* reverse remap_irqs[] */ -+ switch (*out_hwirq) { -+ case INTERRUPT_VC_JPEG: -+ *out_hwirq = INTERRUPT_JPEG; -+ break; -+ case INTERRUPT_VC_USB: -+ *out_hwirq = INTERRUPT_USB; -+ break; -+ case INTERRUPT_VC_3D: -+ *out_hwirq = INTERRUPT_3D; -+ break; -+ case INTERRUPT_VC_DMA2: -+ *out_hwirq = INTERRUPT_DMA2; -+ break; -+ case INTERRUPT_VC_DMA3: -+ *out_hwirq = INTERRUPT_DMA3; -+ break; -+ case INTERRUPT_VC_I2C: -+ *out_hwirq = INTERRUPT_I2C; -+ break; -+ case INTERRUPT_VC_SPI: -+ *out_hwirq = INTERRUPT_SPI; -+ break; -+ case INTERRUPT_VC_I2SPCM: -+ *out_hwirq = INTERRUPT_I2SPCM; -+ break; -+ case INTERRUPT_VC_SDIO: -+ *out_hwirq = INTERRUPT_SDIO; -+ break; -+ case INTERRUPT_VC_UART: -+ *out_hwirq = INTERRUPT_UART; -+ break; -+ case INTERRUPT_VC_ARASANSDIO: -+ *out_hwirq = INTERRUPT_ARASANSDIO; -+ break; -+ } -+ -+ *out_type = IRQ_TYPE_NONE; -+ return 0; -+} -+ -+static struct irq_domain_ops armctrl_ops = { -+ .xlate = armctrl_xlate -+}; -+ -+void __init armctrl_dt_init(void) -+{ -+ struct device_node *np; -+ struct irq_domain *domain; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); -+ if (!np) -+ return; -+ -+ domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, -+ IRQ_ARMCTRL_START, 0, -+ &armctrl_ops, NULL); -+ WARN_ON(!domain); -+} -+#else -+void __init armctrl_dt_init(void) { } -+#endif /* CONFIG_OF */ -+ - #if defined(CONFIG_PM) - - /* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ -@@ -215,5 +310,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, - - armctrl_pm_register(base, irq_start, resume_sources); - init_FIQ(FIQ_START); -+ armctrl_dt_init(); - return 0; - } - -From e85c6248222486f0aca8f09ea4bf7ad463b15487 Mon Sep 17 00:00:00 2001 -From: notro -Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 044/216] BCM2708: use pinctrl-bcm2835 - -Use pinctrl-bcm2835 instead of the pinctrl-bcm2708 and bcm2708_gpio -combination. - -Signed-off-by: Noralf Tronnes ---- - arch/arm/mach-bcm2708/Kconfig | 3 +++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - drivers/pinctrl/pinctrl-bcm2835.c | 2 +- - 3 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 182e7ba..4cfae55 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -14,6 +14,9 @@ config BCM2708_DT - depends on MACH_BCM2708 - default n - select USE_OF -+ select ARCH_REQUIRE_GPIOLIB -+ select PINCTRL -+ select PINCTRL_BCM2835 - help - Enable Device Tree support for BCM2708 - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a812b51..a207ad8 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -816,7 +816,7 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO -- bcm_register_device(&bcm2708_gpio_device); -+ bcm_register_device_dt(&bcm2708_gpio_device); - #endif - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index 9aa8a3f..9d1149e 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -382,7 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = { - .get = bcm2835_gpio_get, - .set = bcm2835_gpio_set, - .to_irq = bcm2835_gpio_to_irq, -- .base = -1, -+ .base = 0, - .ngpio = BCM2835_NUM_GPIOS, - .can_sleep = false, - }; - -From d00f2dcc5c02b51e10e6516e12570db41509ffe5 Mon Sep 17 00:00:00 2001 -From: notro -Date: Sun, 27 Jul 2014 20:12:58 +0200 -Subject: [PATCH 045/216] spi: bcm2708: add device tree support - -Add DT support to driver and add to .dtsi file. -Setup pins and spidev in .dts file. -SPI is disabled by default. - -Signed-off-by: Noralf Tronnes - -BCM2708: don't register SPI controller when using DT - -The device for the SPI controller is in the Device Tree. -Only register the device when not using DT. - -Signed-off-by: Noralf Tronnes - -spi: bcm2835: make driver available on ARCH_BCM2708 - -Make this driver available on ARCH_BCM2708 - -Signed-off-by: Noralf Tronnes - -bcm2708: Remove the prohibition on mixing SPIDEV and DT ---- - arch/arm/boot/dts/bcm2708.dtsi | 8 ++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 7 ++++--- - drivers/spi/Kconfig | 4 ++-- - drivers/spi/spi-bcm2708.c | 8 ++++++++ - 4 files changed, 22 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 96b7311..93f009a 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -82,5 +82,13 @@ - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; - }; - }; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a207ad8..e366bb4 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -836,7 +836,7 @@ void __init bcm2708_init(void) - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device(&bcm2708_alsa_devices[i]); - -- bcm_register_device(&bcm2708_spi_device); -+ bcm_register_device_dt(&bcm2708_spi_device); - bcm_register_device(&bcm2708_bsc0_device); - bcm_register_device(&bcm2708_bsc1_device); - -@@ -876,8 +876,9 @@ void __init bcm2708_init(void) - system_serial_low = serial; - - #ifdef CONFIG_BCM2708_SPIDEV -- spi_register_board_info(bcm2708_spi_devices, -- ARRAY_SIZE(bcm2708_spi_devices)); -+ if (!use_dt) -+ spi_register_board_info(bcm2708_spi_devices, -+ ARRAY_SIZE(bcm2708_spi_devices)); - #endif - } - -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 9628e75..113bf64 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -77,7 +77,7 @@ config SPI_ATMEL - - config SPI_BCM2835 - tristate "BCM2835 SPI controller" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - help - This selects a driver for the Broadcom BCM2835 SPI master. - -@@ -88,7 +88,7 @@ config SPI_BCM2835 - - config SPI_BCM2708 - tristate "BCM2708 SPI controller driver (SPI0)" -- depends on MACH_BCM2708 -+ depends on MACH_BCM2708 || MACH_BCM2709 - help - This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This - driver is not compatible with the "Universal SPI Master" or the SPI slave -diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c -index 349d21f..041b5e2 100644 ---- a/drivers/spi/spi-bcm2708.c -+++ b/drivers/spi/spi-bcm2708.c -@@ -512,6 +512,7 @@ static int bcm2708_spi_probe(struct platform_device *pdev) - master->setup = bcm2708_spi_setup; - master->transfer = bcm2708_spi_transfer; - master->cleanup = bcm2708_spi_cleanup; -+ master->dev.of_node = pdev->dev.of_node; - platform_set_drvdata(pdev, master); - - bs = spi_master_get_devdata(master); -@@ -596,10 +597,17 @@ static int bcm2708_spi_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm2708_spi_match[] = { -+ { .compatible = "brcm,bcm2708-spi", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_spi_match); -+ - static struct platform_driver bcm2708_spi_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_spi_match, - }, - .probe = bcm2708_spi_probe, - .remove = bcm2708_spi_remove, - -From 13cf0c2ef8f80ef3e128343e2d07cd3d31eb9860 Mon Sep 17 00:00:00 2001 -From: notro -Date: Tue, 29 Jul 2014 11:04:49 +0200 -Subject: [PATCH 046/216] i2c: bcm2708: add device tree support - -Add DT support to driver and add to .dtsi file. -Setup pins in .dts file. -i2c is disabled by default. - -Signed-off-by: Noralf Tronnes - -bcm2708: don't register i2c controllers when using DT - -The devices for the i2c controllers are in the Device Tree. -Only register devices when not using DT. - -Signed-off-by: Noralf Tronnes - -i2c: bcm2835: make driver available on ARCH_BCM2708 - -Make this driver available on ARCH_BCM2708 - -Signed-off-by: Noralf Tronnes ---- - arch/arm/boot/dts/bcm2708.dtsi | 7 +++++++ - arch/arm/mach-bcm2708/bcm2708.c | 4 ++-- - drivers/i2c/busses/Kconfig | 4 ++-- - drivers/i2c/busses/i2c-bcm2708.c | 24 ++++++++++++++++++++++++ - 4 files changed, 35 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 93f009a..0a916a4 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -83,6 +83,13 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ - clk_spi: clock@2 { - compatible = "fixed-clock"; - reg = <2>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e366bb4..a81200e 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -837,8 +837,8 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device(&bcm2708_bsc0_device); -- bcm_register_device(&bcm2708_bsc1_device); -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 00c7baa..92009dc 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -10,7 +10,7 @@ comment "PC SMBus host controller drivers" - - config I2C_BCM2708 - tristate "BCM2708 BSC" -- depends on MACH_BCM2708 -+ depends on MACH_BCM2708 || MACH_BCM2709 - help - Enabling this option will add BSC (Broadcom Serial Controller) - support for the BCM2708. BSC is a Broadcom proprietary bus compatible -@@ -381,7 +381,7 @@ config I2C_AXXIA - - config I2C_BCM2835 - tristate "Broadcom BCM2835 I2C controller" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - help - If you say yes to this option, support will be included for the - BCM2835 I2C controller. -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 7d385a3..526129b 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -303,6 +304,21 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - unsigned long bus_hz; - u32 cdiv; - -+ if (pdev->dev.of_node) { -+ u32 bus_clk_rate; -+ pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c"); -+ if (pdev->id < 0) { -+ dev_err(&pdev->dev, "alias is missing\n"); -+ return -EINVAL; -+ } -+ if (!of_property_read_u32(pdev->dev.of_node, -+ "clock-frequency", &bus_clk_rate)) -+ baudrate = bus_clk_rate; -+ else -+ dev_warn(&pdev->dev, -+ "Could not read clock-frequency property\n"); -+ } -+ - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(&pdev->dev, "could not get IO memory\n"); -@@ -336,6 +352,7 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; - strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ adap->dev.of_node = pdev->dev.of_node; - - switch (pdev->id) { - case 0: -@@ -416,10 +433,17 @@ static int bcm2708_i2c_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm2708_i2c_of_match[] = { -+ { .compatible = "brcm,bcm2708-i2c" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match); -+ - static struct platform_driver bcm2708_i2c_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_i2c_of_match, - }, - .probe = bcm2708_i2c_probe, - .remove = bcm2708_i2c_remove, - -From b36757e9c2eb66112c0cebce20ac608f1f94cbe4 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 047/216] hid: Reduce default mouse polling interval to 60Hz - -Reduces overhead when using X ---- - drivers/hid/usbhid/hid-core.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index bfbe1be..a738b25 100644 ---- a/drivers/hid/usbhid/hid-core.c -+++ b/drivers/hid/usbhid/hid-core.c -@@ -49,7 +49,7 @@ - * Module parameters. - */ - --static unsigned int hid_mousepoll_interval; -+static unsigned int hid_mousepoll_interval = ~0; - module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); - MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -@@ -1090,8 +1090,12 @@ static int usbhid_start(struct hid_device *hid) - } - - /* Change the polling interval of mice. */ -- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) -- interval = hid_mousepoll_interval; -+ if (hid->collection->usage == HID_GD_MOUSE) { -+ if (hid_mousepoll_interval == ~0 && interval < 16) -+ interval = 16; -+ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) -+ interval = hid_mousepoll_interval; -+ } - - ret = -ENOMEM; - if (usb_endpoint_dir_in(endpoint)) { - -From 72f91c3f7d8b2944ccadbe7d3d57128c1fc08a8b Mon Sep 17 00:00:00 2001 -From: P33M -Date: Thu, 24 Jul 2014 21:24:03 +0100 -Subject: [PATCH 048/216] usb: core: make overcurrent messages more prominent - -Hub overcurrent messages are more serious than "debug". Increase loglevel. ---- - drivers/usb/core/hub.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 3b71516..8324c14 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4922,7 +4922,7 @@ static void port_event(struct usb_hub *hub, int port1) - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - u16 status = 0, unused; - -- dev_dbg(&port_dev->dev, "over-current change\n"); -+ dev_notice(&port_dev->dev, "over-current change\n"); - usb_clear_port_feature(hdev, port1, - USB_PORT_FEAT_C_OVER_CURRENT); - msleep(100); /* Cool down */ - -From cf880d700f626df4e4910b8dedea887720bf6018 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 7 Aug 2014 02:03:50 +0100 -Subject: [PATCH 049/216] Revert "ARM: dma: Use dma_pfn_offset for dma address - translation" - -This reverts commit 6ce0d20016925d031f1e24d64302e4c976d7cec6. ---- - arch/arm/include/asm/dma-mapping.h | 18 +----------------- - 1 file changed, 1 insertion(+), 17 deletions(-) - -diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h -index b52101d3..f5572d9 100644 ---- a/arch/arm/include/asm/dma-mapping.h -+++ b/arch/arm/include/asm/dma-mapping.h -@@ -58,37 +58,21 @@ static inline int dma_set_mask(struct device *dev, u64 mask) - #ifndef __arch_pfn_to_dma - static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) - { -- if (dev) -- pfn -= dev->dma_pfn_offset; - return (dma_addr_t)__pfn_to_bus(pfn); - } - - static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) - { -- unsigned long pfn = __bus_to_pfn(addr); -- -- if (dev) -- pfn += dev->dma_pfn_offset; -- -- return pfn; -+ return __bus_to_pfn(addr); - } - - static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) - { -- if (dev) { -- unsigned long pfn = dma_to_pfn(dev, addr); -- -- return phys_to_virt(__pfn_to_phys(pfn)); -- } -- - return (void *)__bus_to_virt((unsigned long)addr); - } - - static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) - { -- if (dev) -- return pfn_to_dma(dev, virt_to_pfn(addr)); -- - return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); - } - - -From 3492b141fbae950fd9614cb643257658e5d89329 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 050/216] 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. ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 119 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 147 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dacplus.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a81200e..5f7df9e 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -649,6 +649,20 @@ static struct platform_device snd_pcm5102a_codec_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+static struct platform_device snd_rpi_hifiberry_dacplus_device = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("pcm5122", 0x4d) -+ }, -+}; -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) - static struct platform_device snd_hifiberry_digi_device = { - .name = "snd-hifiberry-digi", -@@ -852,6 +866,11 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) -+ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); -+ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) - bcm_register_device_dt(&snd_hifiberry_digi_device); - i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index faa89ef..7675501 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - help - Say Y or M if you want to add support for HifiBerry DAC. - -+config SND_BCM2708_SOC_HIFIBERRY_DACPLUS -+ tristate "Support for HifiBerry DAC+" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM512x -+ help -+ Say Y or M if you want to add support for HifiBerry DAC+. -+ - config SND_BCM2708_SOC_HIFIBERRY_DIGI - tristate "Support for HifiBerry Digi" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index d597fb0..c02e3a2 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -new file mode 100644 -index 0000000..c63387b ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,119 @@ -+/* -+ * ASoC Driver for HiFiBerry DAC+ -+ * -+ * Author: Daniel Matuschek -+ * Copyright 2014 -+ * based on code by Florian Meier -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "../codecs/pcm512x.h" -+ -+static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+static int snd_rpi_hifiberry_dacplus_startup(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_dacplus_shutdown(struct snd_pcm_substream *substream) { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { -+ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, -+ .startup = snd_rpi_hifiberry_dacplus_startup, -+ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { -+{ -+ .name = "HiFiBerry DAC+", -+ .stream_name = "HiFiBerry DAC+ HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004d", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dacplus_ops, -+ .init = snd_rpi_hifiberry_dacplus_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dacplus = { -+ .name = "snd_rpi_hifiberry_dacplus", -+ .dai_link = snd_rpi_hifiberry_dacplus_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -+}; -+ -+static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { -+ .driver = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_dacplus_probe, -+ .remove = snd_rpi_hifiberry_dacplus_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dacplus_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); -+MODULE_LICENSE("GPL v2"); - -From 3663a863bd1a077dfe48177181118e464a1d6f08 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 051/216] 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. ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 +++ - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 106 ++++++++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 362 ++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/tas5713.h | 210 +++++++++++++++++++++++ - 8 files changed, 712 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_amp.c - create mode 100644 sound/soc/codecs/tas5713.c - create mode 100644 sound/soc/codecs/tas5713.h - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5f7df9e..66bc839 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -678,6 +678,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { - - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+static struct platform_device snd_hifiberry_amp_device = { -+ .name = "snd-hifiberry-amp", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { -+ { -+ I2C_BOARD_INFO("tas5713", 0x1b) -+ }, -+}; -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - static struct platform_device snd_rpi_dac_device = { - .name = "snd-rpi-dac", -@@ -876,6 +890,11 @@ void __init bcm2708_init(void) - i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) -+ bcm_register_device_dt(&snd_hifiberry_amp_device); -+ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); -+#endif -+ - #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) - bcm_register_device_dt(&snd_rpi_dac_device); - bcm_register_device_dt(&snd_pcm1794a_codec_device); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7675501..40d27c1 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - -+config SND_BCM2708_SOC_HIFIBERRY_AMP -+ tristate "Support for the HifiBerry Amp" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_TAS5713 -+ help -+ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index c02e3a2..17ea2b0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -new file mode 100644 -index 0000000..1e87ee06 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,106 @@ -+/* -+ * ASoC Driver for HifiBerry AMP -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ // ToDo: init of the dsp-registers. -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params ) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+} -+ -+static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -+ .hw_params = snd_rpi_hifiberry_amp_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -+ { -+ .name = "HifiBerry AMP", -+ .stream_name = "HifiBerry AMP HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "tas5713-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "tas5713.1-001b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_amp_ops, -+ .init = snd_rpi_hifiberry_amp_init, -+ }, -+}; -+ -+ -+static struct snd_soc_card snd_rpi_hifiberry_amp = { -+ .name = "snd_rpi_hifiberry_amp", -+ .dai_link = snd_rpi_hifiberry_amp_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -+}; -+ -+ -+static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_amp.dev = &pdev->dev; -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -+ -+ if (ret != 0) { -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); -+} -+ -+ -+static struct platform_driver snd_rpi_hifiberry_amp_driver = { -+ .driver = { -+ .name = "snd-hifiberry-amp", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_amp_probe, -+ .remove = snd_rpi_hifiberry_amp_remove, -+}; -+ -+ -+module_platform_driver(snd_rpi_hifiberry_amp_driver); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 8682bcf..f49e15d 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -108,6 +108,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -+ select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4 if I2C -@@ -618,6 +619,9 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - -+config SND_SOC_TAS5713 -+ tristate -+ - config SND_SOC_TLV320AIC23 - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index c9bceba..078943d 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -108,6 +108,7 @@ snd-soc-sta529-objs := sta529.o - snd-soc-stac9766-objs := stac9766.o - snd-soc-tas5086-objs := tas5086.o - snd-soc-tfa9879-objs := tfa9879.o -+snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -289,6 +290,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o - obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o - obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o -+obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -new file mode 100644 -index 0000000..a24c1da ---- /dev/null -+++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,362 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "tas5713.h" -+ -+ -+static struct i2c_client *i2c; -+ -+struct tas5713_priv { -+ struct regmap *regmap; -+ int mclk_div; -+ struct snd_soc_codec *codec; -+}; -+ -+static struct tas5713_priv *priv_data; -+ -+ -+ -+ -+/* -+ * _ _ ___ _ ___ _ _ -+ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -+ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -+ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -+ * -+ */ -+ -+static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -+ -+ -+static const struct snd_kcontrol_new tas5713_snd_controls[] = { -+ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -+ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) -+}; -+ -+ -+ -+ -+/* -+ * __ __ _ _ ___ _ -+ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -+ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -+ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ u16 blen = 0x00; -+ -+ struct snd_soc_codec *codec; -+ codec = dai->codec; -+ priv_data->codec = dai->codec; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ blen = 0x03; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ blen = 0x1; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ blen = 0x04; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ blen = 0x05; -+ break; -+ default: -+ dev_err(dai->dev, "Unsupported word length: %u\n", -+ params_format(params)); -+ return -EINVAL; -+ } -+ -+ // set word length -+ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -+ -+ return 0; -+} -+ -+ -+static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ unsigned int val = 0; -+ -+ struct tas5713_priv *tas5713; -+ struct snd_soc_codec *codec = dai->codec; -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ if (mute) { -+ val = TAS5713_SOFT_MUTE_ALL; -+ } -+ -+ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); -+} -+ -+ -+static const struct snd_soc_dai_ops tas5713_dai_ops = { -+ .hw_params = tas5713_hw_params, -+ .mute_stream = tas5713_mute_stream, -+}; -+ -+ -+static struct snd_soc_dai_driver tas5713_dai = { -+ .name = "tas5713-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_48000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -+ }, -+ .ops = &tas5713_dai_ops, -+}; -+ -+ -+ -+ -+/* -+ * ___ _ ___ _ -+ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -+ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -+ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_remove(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ return 0; -+} -+ -+ -+static int tas5713_probe(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ int i, ret; -+ -+ i2c = container_of(codec->dev, struct i2c_client, dev); -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ -+ // Trim oscillator -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ msleep(1000); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ -+ // Clock mode: 44/48kHz, MCLK=64xfs -+ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ -+ // I2S 24bit -+ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ -+ // Set volume to 0db -+ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ -+ // Now start programming the default initialization sequence -+ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -+ ret = i2c_master_send(i2c, -+ tas5713_init_sequence[i].data, -+ tas5713_init_sequence[i].size); -+ -+ if (ret < 0) { -+ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -+ } -+ } -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -+ .probe = tas5713_probe, -+ .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+}; -+ -+ -+ -+ -+/* -+ * ___ ___ ___ ___ _ -+ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -+ * | | / / (__ | |) | '_| \ V / -_) '_| -+ * |___/___\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static const struct reg_default tas5713_reg_defaults[] = { -+ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -+ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -+ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -+ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB -+}; -+ -+ -+static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case TAS5713_DEVICE_ID: -+ case TAS5713_ERROR_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+ -+static const struct of_device_id tas5713_of_match[] = { -+ { .compatible = "ti,tas5713", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, tas5713_of_match); -+ -+ -+static struct regmap_config tas5713_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = TAS5713_MAX_REGISTER, -+ .volatile_reg = tas5713_reg_volatile, -+ -+ .cache_type = REGCACHE_RBTREE, -+ .reg_defaults = tas5713_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), -+}; -+ -+ -+static int tas5713_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ int ret; -+ -+ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -+ if (IS_ERR(priv_data->regmap)) { -+ ret = PTR_ERR(priv_data->regmap); -+ return ret; -+ } -+ -+ i2c_set_clientdata(i2c, priv_data); -+ -+ ret = snd_soc_register_codec(&i2c->dev, -+ &soc_codec_dev_tas5713, &tas5713_dai, 1); -+ -+ return ret; -+} -+ -+ -+static int tas5713_i2c_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_codec(&i2c->dev); -+ i2c_set_clientdata(i2c, NULL); -+ -+ kfree(priv_data); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id tas5713_i2c_id[] = { -+ { "tas5713", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -+ -+ -+static struct i2c_driver tas5713_i2c_driver = { -+ .driver = { -+ .name = "tas5713", -+ .owner = THIS_MODULE, -+ .of_match_table = tas5713_of_match, -+ }, -+ .probe = tas5713_i2c_probe, -+ .remove = tas5713_i2c_remove, -+ .id_table = tas5713_i2c_id -+}; -+ -+ -+static int __init tas5713_modinit(void) -+{ -+ int ret = 0; -+ -+ ret = i2c_add_driver(&tas5713_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -+ ret); -+ } -+ -+ return ret; -+} -+module_init(tas5713_modinit); -+ -+ -+static void __exit tas5713_exit(void) -+{ -+ i2c_del_driver(&tas5713_i2c_driver); -+} -+module_exit(tas5713_exit); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for TAS5713"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h -new file mode 100644 -index 0000000..8f019e0 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.h -@@ -0,0 +1,210 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#ifndef _TAS5713_H -+#define _TAS5713_H -+ -+ -+// TAS5713 I2C-bus register addresses -+ -+#define TAS5713_CLOCK_CTRL 0x00 -+#define TAS5713_DEVICE_ID 0x01 -+#define TAS5713_ERROR_STATUS 0x02 -+#define TAS5713_SYSTEM_CTRL1 0x03 -+#define TAS5713_SERIAL_DATA_INTERFACE 0x04 -+#define TAS5713_SYSTEM_CTRL2 0x05 -+#define TAS5713_SOFT_MUTE 0x06 -+#define TAS5713_VOL_MASTER 0x07 -+#define TAS5713_VOL_CH1 0x08 -+#define TAS5713_VOL_CH2 0x09 -+#define TAS5713_VOL_HEADPHONE 0x0A -+#define TAS5713_VOL_CONFIG 0x0E -+#define TAS5713_MODULATION_LIMIT 0x10 -+#define TAS5713_IC_DLY_CH1 0x11 -+#define TAS5713_IC_DLY_CH2 0x12 -+#define TAS5713_IC_DLY_CH3 0x13 -+#define TAS5713_IC_DLY_CH4 0x14 -+ -+#define TAS5713_START_STOP_PERIOD 0x1A -+#define TAS5713_OSC_TRIM 0x1B -+#define TAS5713_BKND_ERR 0x1C -+ -+#define TAS5713_INPUT_MUX 0x20 -+#define TAS5713_SRC_SELECT_CH4 0x21 -+#define TAS5713_PWM_MUX 0x25 -+ -+#define TAS5713_CH1_BQ0 0x29 -+#define TAS5713_CH1_BQ1 0x2A -+#define TAS5713_CH1_BQ2 0x2B -+#define TAS5713_CH1_BQ3 0x2C -+#define TAS5713_CH1_BQ4 0x2D -+#define TAS5713_CH1_BQ5 0x2E -+#define TAS5713_CH1_BQ6 0x2F -+#define TAS5713_CH1_BQ7 0x58 -+#define TAS5713_CH1_BQ8 0x59 -+ -+#define TAS5713_CH2_BQ0 0x30 -+#define TAS5713_CH2_BQ1 0x31 -+#define TAS5713_CH2_BQ2 0x32 -+#define TAS5713_CH2_BQ3 0x33 -+#define TAS5713_CH2_BQ4 0x34 -+#define TAS5713_CH2_BQ5 0x35 -+#define TAS5713_CH2_BQ6 0x36 -+#define TAS5713_CH2_BQ7 0x5C -+#define TAS5713_CH2_BQ8 0x5D -+ -+#define TAS5713_CH4_BQ0 0x5A -+#define TAS5713_CH4_BQ1 0x5B -+#define TAS5713_CH3_BQ0 0x5E -+#define TAS5713_CH3_BQ1 0x5F -+ -+#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B -+#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C -+#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E -+#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F -+#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 -+#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 -+#define TAS5713_DRC_CTRL 0x46 -+ -+#define TAS5713_BANK_SW_CTRL 0x50 -+#define TAS5713_CH1_OUTPUT_MIXER 0x51 -+#define TAS5713_CH2_OUTPUT_MIXER 0x52 -+#define TAS5713_CH1_INPUT_MIXER 0x53 -+#define TAS5713_CH2_INPUT_MIXER 0x54 -+#define TAS5713_OUTPUT_POST_SCALE 0x56 -+#define TAS5713_OUTPUT_PRESCALE 0x57 -+ -+#define TAS5713_IDF_POST_SCALE 0x62 -+ -+#define TAS5713_CH1_INLINE_MIXER 0x70 -+#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 -+#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 -+#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 -+#define TAS5713_CH2_INLINE_MIXER 0x74 -+#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 -+#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 -+#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -+ -+#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 -+#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -+ -+#define TAS5713_REGISTER_COUNT 0x46 -+#define TAS5713_MAX_REGISTER 0xF9 -+ -+ -+// Bitmasks for registers -+#define TAS5713_SOFT_MUTE_ALL 0x07 -+ -+ -+ -+struct tas5713_init_command { -+ const int size; -+ const char *const data; -+}; -+ -+static const struct tas5713_init_command tas5713_init_sequence[] = { -+ -+ // Trim oscillator -+ { .size = 2, .data = "\x1B\x00" }, -+ // System control register 1 (0x03): block DC -+ { .size = 2, .data = "\x03\x80" }, -+ // Mute everything -+ { .size = 2, .data = "\x05\x40" }, -+ // Modulation limit register (0x10): 97.7% -+ { .size = 2, .data = "\x10\x02" }, -+ // Interchannel delay registers -+ // (0x11, 0x12, 0x13, and 0x14): BD mode -+ { .size = 2, .data = "\x11\xB8" }, -+ { .size = 2, .data = "\x12\x60" }, -+ { .size = 2, .data = "\x13\xA0" }, -+ { .size = 2, .data = "\x14\x48" }, -+ // PWM shutdown group register (0x19): no shutdown -+ { .size = 2, .data = "\x19\x00" }, -+ // Input multiplexer register (0x20): BD mode -+ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -+ // PWM output mux register (0x25) -+ // Channel 1 --> OUTA, channel 1 neg --> OUTB -+ // Channel 2 --> OUTC, channel 2 neg --> OUTD -+ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -+ // DRC control (0x46): DRC off -+ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -+ // BKND_ERR register (0x1C): 299ms reset period -+ { .size = 2, .data = "\x1C\x07" }, -+ // Mute channel 3 -+ { .size = 2, .data = "\x0A\xFF" }, -+ // Volume configuration register (0x0E): volume slew 512 steps -+ { .size = 2, .data = "\x0E\x90" }, -+ // Clock control register (0x00): 44/48kHz, MCLK=64xfs -+ { .size = 2, .data = "\x00\x60" }, -+ // Bank switch and eq control (0x50): no bank switching -+ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -+ // Volume registers (0x07, 0x08, 0x09, 0x0A) -+ { .size = 2, .data = "\x07\x20" }, -+ { .size = 2, .data = "\x08\x30" }, -+ { .size = 2, .data = "\x09\x30" }, -+ { .size = 2, .data = "\x0A\xFF" }, -+ // 0x72, 0x73, 0x76, 0x77 input mixer: -+ // no intermix between channels -+ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -+ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -+ // no inline DRC inmix -+ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -+ // 0x56, 0x57 Output scale -+ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -+ // 0x3B, 0x3c -+ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ // 0x51, 0x52: output mixer -+ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ // PEQ defaults -+ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+}; -+ -+ -+#endif /* _TAS5713_H */ - -From 5cd70cb7da74d3817f6037213f1a79ff31254d89 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Apr 2015 19:14:18 +0100 -Subject: [PATCH 052/216] bcm2708: Allow option card devices to be configured - via DT - -If the kernel is built with Device Tree support, and if a DT blob -is provided for the kernel at boot time, then the platform devices -for option cards are not created. This avoids both the need to -blacklist unwanted devices, and the need to update the board -support code with each new device. ---- - sound/soc/bcm/bcm2835-i2s.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 03fa1cb..c816526 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -861,6 +861,7 @@ static const struct of_device_id bcm2835_i2s_of_match[] = { - { .compatible = "brcm,bcm2835-i2s", }, - {}, - }; -+MODULE_DEVICE_TABLE(of, bcm2835_i2s_of_match); - - static struct platform_driver bcm2835_i2s_driver = { - .probe = bcm2835_i2s_probe, - -From b2ee40fa3d362faf4071abda9f1e273b6e80ec78 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 18:45:39 +0100 -Subject: [PATCH 053/216] Adding Device Tree support for some RPi audio cards - ---- - arch/arm/boot/dts/hifiberry-dac-overlay.dts | 34 +++++++++++++++++++++ - arch/arm/boot/dts/hifiberry-dacplus-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/hifiberry-digi-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/iqaudio-dac-overlay.dts | 39 +++++++++++++++++++++++++ - arch/arm/boot/dts/iqaudio-dacplus-overlay.dts | 39 +++++++++++++++++++++++++ - sound/soc/bcm/hifiberry_dac.c | 22 ++++++++++++++ - sound/soc/bcm/hifiberry_dacplus.c | 22 ++++++++++++++ - sound/soc/bcm/hifiberry_digi.c | 22 ++++++++++++++ - sound/soc/bcm/iqaudio-dac.c | 16 ++++++++++ - sound/soc/codecs/pcm5102a.c | 7 +++++ - 10 files changed, 279 insertions(+) - create mode 100644 arch/arm/boot/dts/hifiberry-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/hifiberry-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/hifiberry-digi-overlay.dts - create mode 100644 arch/arm/boot/dts/iqaudio-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/iqaudio-dacplus-overlay.dts - -diff --git a/arch/arm/boot/dts/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -new file mode 100644 -index 0000000..5e7633a ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for HiFiBerry DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -new file mode 100644 -index 0000000..deb9c625 ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dacplus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4d { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4d>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -new file mode 100644 -index 0000000..d0e0d8a ---- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Digi -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-digi"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8804@3b { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -new file mode 100644 -index 0000000..ea8173e ---- /dev/null -+++ b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -new file mode 100644 -index 0000000..735d8ab ---- /dev/null -+++ b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -index 4b70b45..3ab0f47 100644 ---- a/sound/soc/bcm/hifiberry_dac.c -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -72,6 +72,21 @@ static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -@@ -84,10 +99,17 @@ static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); - } - -+static const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_dac_driver = { - .driver = { - .name = "snd-hifiberry-dac", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dac_of_match, - }, - .probe = snd_rpi_hifiberry_dac_probe, - .remove = snd_rpi_hifiberry_dac_remove, -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -index c63387b..11e4f39 100644 ---- a/sound/soc/bcm/hifiberry_dacplus.c -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -90,6 +90,21 @@ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dacplus_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); - if (ret) - dev_err(&pdev->dev, -@@ -103,10 +118,17 @@ static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); - } - -+static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dacplus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { - .driver = { - .name = "snd-rpi-hifiberry-dacplus", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, - }, - .probe = snd_rpi_hifiberry_dacplus_probe, - .remove = snd_rpi_hifiberry_dacplus_remove, -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 446ecdd..74a8c73 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -125,6 +125,21 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_hifiberry_digi.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -@@ -137,10 +152,17 @@ static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) - return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); - } - -+static const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); -+ - static struct platform_driver snd_rpi_hifiberry_digi_driver = { - .driver = { - .name = "snd-hifiberry-digi", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_digi_of_match, - }, - .probe = snd_rpi_hifiberry_digi_probe, - .remove = snd_rpi_hifiberry_digi_remove, -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -index aff7377..a38e874 100644 ---- a/sound/soc/bcm/iqaudio-dac.c -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -82,6 +82,21 @@ static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) - int ret = 0; - - snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); - if (ret) - dev_err(&pdev->dev, -@@ -99,6 +114,7 @@ static const struct of_device_id iqaudio_of_match[] = { - { .compatible = "iqaudio,iqaudio-dac", }, - {}, - }; -+MODULE_DEVICE_TABLE(of, iqaudio_of_match); - - static struct platform_driver snd_rpi_iqaudio_dac_driver = { - .driver = { -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -index 126f1e9..7c6598e 100644 ---- a/sound/soc/codecs/pcm5102a.c -+++ b/sound/soc/codecs/pcm5102a.c -@@ -47,12 +47,19 @@ static int pcm5102a_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id pcm5102a_of_match[] = { -+ { .compatible = "ti,pcm5102a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm5102a_of_match); -+ - static struct platform_driver pcm5102a_codec_driver = { - .probe = pcm5102a_probe, - .remove = pcm5102a_remove, - .driver = { - .name = "pcm5102a-codec", - .owner = THIS_MODULE, -+ .of_match_table = pcm5102a_of_match, - }, - }; - - -From ea3aad745389e9631e71c1b175e37d6874ee980b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 054/216] fdt: Add support for the CONFIG_CMDLINE_EXTEND option - ---- - drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- - 1 file changed, 24 insertions(+), 5 deletions(-) - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 3a896c9..0320a6f 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -915,19 +915,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); -- if (p != NULL && l > 0) -- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE - * is set in which case we override whatever was found earlier. -+ * -+ * However, it can be useful to be able to treat the default as -+ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. - */ -+ ((char *)data)[0] = '\0'; -+ - #ifdef CONFIG_CMDLINE --#ifndef CONFIG_CMDLINE_FORCE -- if (!((char *)data)[0]) -+ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ -+ if (p != NULL && l > 0) { -+#if defined(CONFIG_CMDLINE_EXTEND) -+ int len = strlen(data); -+ if (len > 0) { -+ strlcat(data, " ", COMMAND_LINE_SIZE); -+ len++; -+ } -+ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); -+#elif defined(CONFIG_CMDLINE_FORCE) -+ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); -+#else -+ /* Neither extend nor force - just override */ -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ } -+#else /* CONFIG_CMDLINE */ -+ if (p != NULL && l > 0) { -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", (char*)data); - -From a9a57c353bdccbc5cd60d995c53d6146addf78fc Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 16 Dec 2014 10:23:48 +0000 -Subject: [PATCH 055/216] DT: Add overrides to enable i2c0, i2c1, spi and i2s - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 10 ++++++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 10 ++++++++++ - 2 files changed, 20 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 983c23f..d9886c3 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -79,3 +79,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; -+ -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index d8c6d15..167b22b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -79,3 +79,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&i2s_pins>; - }; -+ -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ }; -+}; - -From 4bdc71b8c2f9444a8ec6fe833cb92ba4fd4130f7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 18 Dec 2014 16:48:32 +0000 -Subject: [PATCH 056/216] lirc-rpi: Add device tree support, and a suitable - overlay - -The overlay supports DT parameters that match the old module -parameters, except that gpio_in_pull should be set using the -strings "up", "down" or "off". - -lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode ---- - arch/arm/boot/dts/lirc-rpi-overlay.dts | 57 ++++++++++++ - drivers/staging/media/lirc/lirc_rpi.c | 154 +++++++++++++++++++++++++++------ - 2 files changed, 183 insertions(+), 28 deletions(-) - create mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts - -diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts -new file mode 100644 -index 0000000..7d5d82b ---- /dev/null -+++ b/arch/arm/boot/dts/lirc-rpi-overlay.dts -@@ -0,0 +1,57 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ lirc_rpi: lirc_rpi { -+ compatible = "rpi,lirc-rpi"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lirc_pins>; -+ status = "okay"; -+ -+ // Override autodetection of IR receiver circuit -+ // (0 = active high, 1 = active low, -1 = no override ) -+ rpi,sense = <0xffffffff>; -+ -+ // Software carrier -+ // (0 = off, 1 = on) -+ rpi,softcarrier = <1>; -+ -+ // Invert output -+ // (0 = off, 1 = on) -+ rpi,invert = <0>; -+ -+ // Enable debugging messages -+ // (0 = off, 1 = on) -+ rpi,debug = <0>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ lirc_pins: lirc_pins { -+ brcm,pins = <17 18>; -+ brcm,function = <1 0>; // out in -+ brcm,pull = <0 1>; // off down -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -+ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -+ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -+ -+ sense = <&lirc_rpi>,"rpi,sense:0"; -+ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -+ invert = <&lirc_rpi>,"rpi,invert:0"; -+ debug = <&lirc_rpi>,"rpi,debug:0"; -+ }; -+}; -diff --git a/drivers/staging/media/lirc/lirc_rpi.c b/drivers/staging/media/lirc/lirc_rpi.c -index 8aa452d..24563ec 100644 ---- a/drivers/staging/media/lirc/lirc_rpi.c -+++ b/drivers/staging/media/lirc/lirc_rpi.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - - #include - -@@ -303,32 +304,117 @@ static int is_right_chip(struct gpio_chip *chip, void *data) - return 0; - } - -+static inline int read_bool_property(const struct device_node *np, -+ const char *propname, -+ bool *out_value) -+{ -+ u32 value = 0; -+ int err = of_property_read_u32(np, propname, &value); -+ if (err == 0) -+ *out_value = (value != 0); -+ return err; -+} -+ -+static void read_pin_settings(struct device_node *node) -+{ -+ u32 pin; -+ int index; -+ -+ for (index = 0; -+ of_property_read_u32_index( -+ node, -+ "brcm,pins", -+ index, -+ &pin) == 0; -+ index++) { -+ u32 function; -+ int err; -+ err = of_property_read_u32_index( -+ node, -+ "brcm,function", -+ index, -+ &function); -+ if (err == 0) { -+ if (function == 1) /* Output */ -+ gpio_out_pin = pin; -+ else if (function == 0) /* Input */ -+ gpio_in_pin = pin; -+ } -+ } -+} -+ - static int init_port(void) - { - int i, nlow, nhigh, ret; -+ struct device_node *node; -+ -+ node = lirc_rpi_dev->dev.of_node; - - gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip); - -- if (!gpiochip) -+ /* -+ * Because of the lack of a setpull function, only support -+ * pinctrl-bcm2835 if using device tree. -+ */ -+ if (!gpiochip && node) -+ gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip); -+ -+ if (!gpiochip) { -+ pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n"); - return -ENODEV; -+ } -+ -+ if (node) { -+ struct device_node *pins_node; -+ -+ pins_node = of_parse_phandle(node, "pinctrl-0", 0); -+ if (!pins_node) { -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": pinctrl settings not found!\n"); -+ ret = -EINVAL; -+ goto exit_init_port; -+ } -+ -+ read_pin_settings(pins_node); -+ -+ of_property_read_u32(node, "rpi,sense", &sense); -+ -+ read_bool_property(node, "rpi,softcarrier", &softcarrier); -+ -+ read_bool_property(node, "rpi,invert", &invert); -+ -+ read_bool_property(node, "rpi,debug", &debug); - -- if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -- printk(KERN_ALERT LIRC_DRIVER_NAME -- ": cant claim gpio pin %d\n", gpio_out_pin); -- ret = -ENODEV; -- goto exit_init_port; - } -+ else -+ { -+ if (gpio_in_pin >= BCM2708_NR_GPIOS || -+ gpio_out_pin >= BCM2708_NR_GPIOS) { -+ ret = -EINVAL; -+ printk(KERN_ERR LIRC_DRIVER_NAME -+ ": invalid GPIO pin(s) specified!\n"); -+ goto exit_init_port; -+ } - -- if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -- printk(KERN_ALERT LIRC_DRIVER_NAME -- ": cant claim gpio pin %d\n", gpio_in_pin); -- ret = -ENODEV; -- goto exit_gpio_free_out_pin; -+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_out_pin); -+ ret = -ENODEV; -+ goto exit_init_port; -+ } -+ -+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) { -+ printk(KERN_ALERT LIRC_DRIVER_NAME -+ ": cant claim gpio pin %d\n", gpio_in_pin); -+ ret = -ENODEV; -+ goto exit_gpio_free_out_pin; -+ } -+ -+ bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -+ gpiochip->direction_input(gpiochip, gpio_in_pin); -+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1); - } - -- bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull); -- gpiochip->direction_input(gpiochip, gpio_in_pin); -- gpiochip->direction_output(gpiochip, gpio_out_pin, 1); - gpiochip->set(gpiochip, gpio_out_pin, invert); - - irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin); -@@ -522,15 +608,23 @@ static struct lirc_driver driver = { - .owner = THIS_MODULE, - }; - -+static const struct of_device_id lirc_rpi_of_match[] = { -+ { .compatible = "rpi,lirc-rpi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, lirc_rpi_of_match); -+ - static struct platform_driver lirc_rpi_driver = { - .driver = { - .name = LIRC_DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(lirc_rpi_of_match), - }, - }; - - static int __init lirc_rpi_init(void) - { -+ struct device_node *node; - int result; - - /* Init read buffer. */ -@@ -545,15 +639,26 @@ static int __init lirc_rpi_init(void) - goto exit_buffer_free; - } - -- lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -- if (!lirc_rpi_dev) { -- result = -ENOMEM; -- goto exit_driver_unregister; -+ node = of_find_compatible_node(NULL, NULL, -+ lirc_rpi_of_match[0].compatible); -+ -+ if (node) { -+ /* DT-enabled */ -+ lirc_rpi_dev = of_find_device_by_node(node); -+ WARN_ON(lirc_rpi_dev->dev.of_node != node); -+ of_node_put(node); - } -+ else { -+ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); -+ if (!lirc_rpi_dev) { -+ result = -ENOMEM; -+ goto exit_driver_unregister; -+ } - -- result = platform_device_add(lirc_rpi_dev); -- if (result) -- goto exit_device_put; -+ result = platform_device_add(lirc_rpi_dev); -+ if (result) -+ goto exit_device_put; -+ } - - return 0; - -@@ -585,13 +690,6 @@ static int __init lirc_rpi_init_module(void) - if (result) - return result; - -- if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) { -- result = -EINVAL; -- printk(KERN_ERR LIRC_DRIVER_NAME -- ": invalid GPIO pin(s) specified!\n"); -- goto exit_rpi; -- } -- - result = init_port(); - if (result < 0) - goto exit_rpi; - -From fb3c953810dfcbba431ad3c70eb5751d014db152 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Jan 2015 12:06:55 +0000 -Subject: [PATCH 057/216] Fix the activity LED in DT mode - -Add a "leds" node to the base DTBs, and a subnode for the activity -LED. You can change the LED function like this: - - dtparam=act_led_trigger=heartbeat - -Add aliases for the other main nodes (soc, intc). - -Issue: linux #757 ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 18 ++++++++++++++---- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 18 ++++++++++++++---- - arch/arm/boot/dts/bcm2708.dtsi | 11 ++++++++++- - 3 files changed, 38 insertions(+), 9 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index d9886c3..95f03ba 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -7,11 +7,14 @@ - model = "Raspberry Pi Model B+"; - - aliases { -+ soc = &soc; - spi0 = &spi0; - i2c0 = &i2c0; - i2c1 = &i2c1; - i2s = &i2s; - gpio = &gpio; -+ intc = &intc; -+ leds = &leds; - sound = &sound; - }; - -@@ -80,12 +83,19 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&act_led { -+ gpios = <&gpio 47 0>; -+}; - - / { - __overrides__ { -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 167b22b..0631f45 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -7,11 +7,14 @@ - model = "Raspberry Pi Model B"; - - aliases { -+ soc = &soc; - spi0 = &spi0; - i2c0 = &i2c0; - i2c1 = &i2c1; - i2s = &i2s; - gpio = &gpio; -+ intc = &intc; -+ leds = &leds; - sound = &sound; - }; - -@@ -80,12 +83,19 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&act_led { -+ gpios = <&gpio 16 1>; -+}; - - / { - __overrides__ { -- i2s = <&i2s>,"status"; -- spi = <&spi0>,"status"; -- i2c0 = <&i2c0>,"status"; -- i2c1 = <&i2c1>,"status"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 0a916a4..d879316 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -11,7 +11,7 @@ - bootargs = ""; - }; - -- soc { -+ soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; -@@ -76,6 +76,15 @@ - #size-cells = <0>; - status = "disabled"; - }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ -+ act_led: act { -+ label = "ACT"; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; - }; - - clocks { - -From 1c9f91aafc02bd624edc56899972cb13f48f921d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 15 Jan 2015 10:39:06 +0000 -Subject: [PATCH 058/216] Adding w1-gpio device tree overlays - -N.B. Requires firmware supporting multi-target overrides - -w1-gpio-overlay: - Use if a pullup pin is not required. - Parameters: - gpiopin= // default 4 - -w1-gpio-pullup-overlay: - Use if a pullup pin is required. - Parameters: - gpiopin= // default 4 - pullup= // default 5 ---- - arch/arm/boot/dts/w1-gpio-overlay.dts | 37 ++++++++++++++++++++++++++ - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 39 ++++++++++++++++++++++++++++ - 2 files changed, 76 insertions(+) - create mode 100644 arch/arm/boot/dts/w1-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/w1-gpio-pullup-overlay.dts - -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -new file mode 100644 -index 0000000..b2c5ee2 ---- /dev/null -+++ b/arch/arm/boot/dts/w1-gpio-overlay.dts -@@ -0,0 +1,37 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4>; -+ brcm,function = <0>; // in (initially) -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -new file mode 100644 -index 0000000..b3e97c2 ---- /dev/null -+++ b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>, <&gpio 5 1>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4 5>; -+ brcm,function = <0 1>; // in out -+ brcm,pull = <0 0>; // off off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"gpios:16", -+ <&w1_pins>,"brcm,pins:4"; -+ }; -+}; - -From 740e2da8a9fa6f84e95707ee0a10b4a4cfeaed4a Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Fri, 23 Jan 2015 16:41:17 +0100 -Subject: [PATCH 059/216] TAS5713: return error if initialisation fails - -Existing TAS5713 driver logs errors during initialisation, but does not return -an error code. Therefore even if initialisation fails, the driver will still be -loaded, but won't work. This patch fixes this. I2C communication error will now -reported correctly by a non-zero return code. ---- - sound/soc/codecs/tas5713.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -index a24c1da..9b27138 100644 ---- a/sound/soc/codecs/tas5713.c -+++ b/sound/soc/codecs/tas5713.c -@@ -182,33 +182,40 @@ static int tas5713_probe(struct snd_soc_codec *codec) - - // Reset error - ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; - - // Trim oscillator -- ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ if (ret < 0) return ret; - msleep(1000); - - // Reset error - ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; - - // Clock mode: 44/48kHz, MCLK=64xfs - ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ if (ret < 0) return ret; - - // I2S 24bit - ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ if (ret < 0) return ret; - - // Unmute - ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; - ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ if (ret < 0) return ret; - - // Set volume to 0db - ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ if (ret < 0) return ret; - - // Now start programming the default initialization sequence - for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { - ret = i2c_master_send(i2c, - tas5713_init_sequence[i].data, - tas5713_init_sequence[i].size); -- - if (ret < 0) { - printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); - } -@@ -216,7 +223,7 @@ static int tas5713_probe(struct snd_soc_codec *codec) - - // Unmute - ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -- -+ if (ret < 0) return ret; - - return 0; - } - -From 9615583a44fc9449d77a247d0207b35eab1db982 Mon Sep 17 00:00:00 2001 +From 0ecc87e37d9107eb533346a4a482bbf78920d16c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 23 Jan 2015 14:48:55 +0000 -Subject: [PATCH 060/216] scripts/dtc: Update to upstream version with overlay +Subject: [PATCH 23/77] scripts/dtc: Update to upstream version with overlay patches --- @@ -123717,736 +117880,716 @@ index 54d4e904..d644002 100644 -#define DTC_VERSION "DTC 1.4.0-dirty" +#define DTC_VERSION "DTC 1.4.1-g36c70742" -From 453099dc662c02d1308039ab2dabb176e052eabf Mon Sep 17 00:00:00 2001 +From 4cccd63c16e3ef4e2a35144e2806d1d1c56bc381 Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 23 Jan 2015 15:18:03 +0000 -Subject: [PATCH 061/216] BCM2708_DT: Build the overlays as well +Date: Mon, 11 May 2015 09:00:42 +0100 +Subject: [PATCH 24/77] scripts: Add mkknlimg and knlinfo scripts from tools + repo +The Raspberry Pi firmware looks for a trailer on the kernel image to +determine whether it was compiled with Device Tree support enabled. +If the firmware finds a kernel without this trailer, or which has a +trailer indicating that it isn't DT-capable, it disables DT support +and reverts to using ATAGs. + +The mkknlimg utility adds that trailer, having first analysed the +image to look for signs of DT support and the kernel version string. + +knlinfo displays the contents of the trailer in the given kernel image. + +scripts/mkknlimg: Add support for ARCH_BCM2835 + +Add a new trailer field indicating whether this is an ARCH_BCM2835 +build, as opposed to MACH_BCM2708/9. If the loader finds this flag +is set it changes the default base dtb file name from bcm270x... +to bcm283y... + +Also update knlinfo to show the status of the field. --- - arch/arm/boot/dts/Makefile | 9 +++++++++ - 1 file changed, 9 insertions(+) + scripts/knlinfo | 168 +++++++++++++++++++++++++++++++++ + scripts/mkknlimg | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 443 insertions(+) + create mode 100755 scripts/knlinfo + create mode 100755 scripts/mkknlimg -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 25fbf52..63d902c 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,15 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+ - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC - -From b39dde193e6242ec53938122e553e3af4cd528ed Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Sun, 25 Jan 2015 19:41:06 +0100 -Subject: [PATCH 062/216] Add device tree overlay for HiFiBerry Amp/Amp+ - -This patch add the missing device tree file for the HiFiBerry Amp and Amp+ boards. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hifiberry-amp-overlay.dts | 39 +++++++++++++++++++++++++++++ - 2 files changed, 40 insertions(+) - create mode 100644 arch/arm/boot/dts/hifiberry-amp-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 63d902c..63d89df 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -15,6 +15,7 @@ endif - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -new file mode 100644 -index 0000000..2c81448 +diff --git a/scripts/knlinfo b/scripts/knlinfo +new file mode 100755 +index 0000000..a0e8663 --- /dev/null -+++ b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Amp/Amp+ -+/dts-v1/; -+/plugin/; ++++ b/scripts/knlinfo +@@ -0,0 +1,168 @@ ++#!/usr/bin/env perl ++# ---------------------------------------------------------------------- ++# knlinfo by Phil Elwell for Raspberry Pi ++# ++# (c) 2014,2015 Raspberry Pi (Trading) Limited ++# ++# Licensed under the terms of the GNU General Public License. ++# ---------------------------------------------------------------------- + -+/ { -+ compatible = "brcm,bcm2708"; ++use strict; ++use integer; + -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-amp"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; ++use Fcntl ":seek"; + -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; ++my $trailer_magic = 'RPTL'; + -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; ++my %atom_formats = ++( ++ 'DTOK' => \&format_bool, ++ 'KVer' => \&format_string, ++ '283x' => \&format_bool, ++); + -+ tas5713@1b { -+ #sound-dai-cells = <0>; -+ compatible = "ti,tas5713"; -+ reg = <0x1b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From da11da093a2c65a9faa481e0688b0f242476ee78 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 26 Jan 2015 09:18:24 +0000 -Subject: [PATCH 063/216] Add pps-gpio DT overlay - -Parameters: - gpiopin= // Default 18 ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pps-gpio-overlay.dts | 34 ++++++++++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+) - create mode 100644 arch/arm/boot/dts/pps-gpio-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 63d89df..18637de 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - -diff --git a/arch/arm/boot/dts/pps-gpio-overlay.dts b/arch/arm/boot/dts/pps-gpio-overlay.dts -new file mode 100644 -index 0000000..40bf0e1 ---- /dev/null -+++ b/arch/arm/boot/dts/pps-gpio-overlay.dts -@@ -0,0 +1,34 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ pps: pps { -+ compatible = "pps-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pps_pins>; -+ gpios = <&gpio 18 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pps_pins: pps_pins { -+ brcm,pins = <18>; -+ brcm,function = <0>; // in -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&pps>,"gpios:4", -+ <&pps_pins>,"brcm,pins:0"; -+ }; -+}; - -From 4cddfa6e3758e34eaeeb8457e0f012965436bc1c Mon Sep 17 00:00:00 2001 -From: Timo Kokkonen -Date: Wed, 29 Oct 2014 23:30:30 -0700 -Subject: [PATCH 064/216] Added support to reserve/enable a GPIO pin to be used - from pps-gpio module (LinuxPPS). Enable PPS modules in default config for - RPi. - ---- - arch/arm/mach-bcm2708/bcm2708.c | 27 +++++++++++++++++++++++++++ - arch/arm/mach-bcm2709/bcm2709.c | 27 +++++++++++++++++++++++++++ - 2 files changed, 54 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 66bc839..cc3e56c 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -93,6 +94,7 @@ static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; -+static int pps_gpio_pin = -1; - - static unsigned use_dt = 0; - -@@ -278,6 +280,19 @@ static struct platform_device w1_device = { - }; - #endif - -+static struct pps_gpio_platform_data pps_gpio_info = { -+ .assert_falling_edge = false, -+ .capture_clear = false, -+ .gpio_pin = -1, -+ .gpio_label = "PPS", -+}; -+ -+static struct platform_device pps_gpio_device = { -+ .name = "pps-gpio", -+ .id = PLATFORM_DEVID_NONE, -+ .dev.platform_data = &pps_gpio_info, -+}; -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -846,6 +861,16 @@ void __init bcm2708_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -+ -+#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) -+ if (!use_dt && (pps_gpio_pin >= 0)) { -+ pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); -+ pps_gpio_info.gpio_pin = pps_gpio_pin; -+ pps_gpio_device.id = pps_gpio_pin; -+ bcm_register_device(&pps_gpio_device); -+ } -+#endif -+ - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -@@ -1099,3 +1124,5 @@ module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); - module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); -+module_param(pps_gpio_pin, int, 0644); -+MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index c4bd0a4..914c970 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -95,6 +96,7 @@ static unsigned disk_led_active_low = 1; - static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; -+static int pps_gpio_pin = -1; - - static unsigned use_dt = 0; - -@@ -288,6 +290,19 @@ static struct platform_device w1_device = { - }; - #endif - -+static struct pps_gpio_platform_data pps_gpio_info = { -+ .assert_falling_edge = false, -+ .capture_clear = false, -+ .gpio_pin = -1, -+ .gpio_label = "PPS", -+}; -+ -+static struct platform_device pps_gpio_device = { -+ .name = "pps-gpio", -+ .id = PLATFORM_DEVID_NONE, -+ .dev.platform_data = &pps_gpio_info, -+}; -+ - static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_fb_device = { -@@ -868,6 +883,16 @@ void __init bcm2709_init(void) - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -+ -+#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) -+ if (!use_dt && (pps_gpio_pin >= 0)) { -+ pr_info("bcm2709: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); -+ pps_gpio_info.gpio_pin = pps_gpio_pin; -+ pps_gpio_device.id = pps_gpio_pin; -+ bcm_register_device(&pps_gpio_device); -+ } -+#endif -+ - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - w1_gpio_pdata.pin = w1_gpio_pin; - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; -@@ -1267,3 +1292,5 @@ module_param(disk_led_active_low, uint, 0644); - module_param(reboot_part, uint, 0644); - module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); -+module_param(pps_gpio_pin, int, 0644); -+MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); - -From 2ff35a0e682880dbae67c842805ea848285b373f Mon Sep 17 00:00:00 2001 -From: Serge Schneider -Date: Wed, 3 Sep 2014 14:44:22 +0100 -Subject: [PATCH 065/216] I2C: Only register the I2C device for the current - board revision - ---- - arch/arm/mach-bcm2708/bcm2708.c | 14 ++++++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 14 ++++++++++++-- - 2 files changed, 24 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cc3e56c..c8aea5b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -95,6 +95,7 @@ static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; - static int pps_gpio_pin = -1; -+static bool vc_i2c_override = false; - - static unsigned use_dt = 0; - -@@ -890,8 +891,15 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device_dt(&bcm2708_bsc0_device); -- bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ if (vc_i2c_override) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ } else { -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -@@ -1126,3 +1134,5 @@ module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); - module_param(pps_gpio_pin, int, 0644); - MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -+module_param(vc_i2c_override, bool, 0644); -+MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 914c970..259d552 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -97,6 +97,7 @@ static unsigned reboot_part = 0; - static unsigned w1_gpio_pin = W1_GPIO; - static unsigned w1_gpio_pullup = W1_PULLUP; - static int pps_gpio_pin = -1; -+static bool vc_i2c_override = false; - - static unsigned use_dt = 0; - -@@ -914,8 +915,15 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); -- bcm_register_device_dt(&bcm2708_bsc0_device); -- bcm_register_device_dt(&bcm2708_bsc1_device); -+ -+ if (vc_i2c_override) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { -+ bcm_register_device_dt(&bcm2708_bsc0_device); -+ } else { -+ bcm_register_device_dt(&bcm2708_bsc1_device); -+ } - - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); -@@ -1294,3 +1302,5 @@ module_param(w1_gpio_pin, uint, 0644); - module_param(w1_gpio_pullup, uint, 0644); - module_param(pps_gpio_pin, int, 0644); - MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -+module_param(vc_i2c_override, bool, 0644); -+MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); - -From 32bee38e1fca47be55a48205e850c16901127982 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 28 Jan 2015 16:22:04 +0000 -Subject: [PATCH 066/216] BCM2708_DT: Add pcf8523-rtc overlay - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pcf8523-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/pcf8523-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 18637de..c909f7b 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -diff --git a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -new file mode 100644 -index 0000000..0071f62 ---- /dev/null -+++ b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF8523 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From 7358633426ec4c3897c26cb1575a0ab7309e4f73 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Sat, 31 Jan 2015 16:07:56 +0100 -Subject: [PATCH 067/216] Add a parameter to turn off SPDIF output if no audio - is playing - -This patch adds the paramater auto_shutdown_output to the kernel module. -Default behaviour of the module is the same, but when auto_shutdown_output -is set to 1, the SPDIF oputput will shutdown if no stream is playing. ---- - sound/soc/bcm/hifiberry_digi.c | 29 ++++++++++++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 74a8c73..a245995 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -26,6 +26,11 @@ - - #include "../codecs/wm8804.h" - -+static short int auto_shutdown_output = 0; -+module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); -+ -+ - static int samplerate=44100; - - static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) -@@ -38,6 +43,25 @@ static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) - return 0; - } - -+static int snd_rpi_hifiberry_digi_startup(struct snd_pcm_substream *substream) { -+ /* turn on digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ return 0; ++if (@ARGV != 1) ++{ ++ print ("Usage: knlinfo \n"); ++ exit(1); +} + -+static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { -+ /* turn off output */ -+ if (auto_shutdown_output) { -+ /* turn off output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++my $kernel_file = $ARGV[0]; ++ ++ ++my ($atoms, $pos) = read_trailer($kernel_file); ++ ++exit(1) if (!$atoms); ++ ++printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos); ++ ++foreach my $atom (@$atoms) ++{ ++ printf(" %s: %s\n", $atom->[0], format_atom($atom)); ++} ++ ++exit(0); ++ ++sub read_trailer ++{ ++ my ($kernel_file) = @_; ++ my $fh; ++ ++ if (!open($fh, '<', $kernel_file)) ++ { ++ print ("* Failed to open '$kernel_file'\n"); ++ return undef; + } ++ ++ if (!seek($fh, -12, SEEK_END)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ my $last_bytes; ++ sysread($fh, $last_bytes, 12); ++ ++ my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes); ++ ++ if (($magic ne $trailer_magic) || ($data_len != 4)) ++ { ++ print ("* no trailer\n"); ++ return undef; ++ } ++ if (!seek($fh, -12, SEEK_END)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ $trailer_len -= 12; ++ ++ while ($trailer_len > 0) ++ { ++ if ($trailer_len < 8) ++ { ++ print ("* truncated atom header in trailer\n"); ++ return undef; ++ } ++ if (!seek($fh, -8, SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ $trailer_len -= 8; ++ ++ my $atom_hdr; ++ sysread($fh, $atom_hdr, 8); ++ my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr); ++ ++ if ($trailer_len < $atom_len) ++ { ++ print ("* truncated atom data in trailer\n"); ++ return undef; ++ } ++ ++ my $rounded_len = (($atom_len + 3) & ~3); ++ if (!seek($fh, -(8 + $rounded_len), SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ $trailer_len -= $rounded_len; ++ ++ my $atom_data; ++ sysread($fh, $atom_data, $atom_len); ++ ++ if (!seek($fh, -$atom_len, SEEK_CUR)) ++ { ++ print ("* seek error in '$kernel_file'\n"); ++ return undef; ++ } ++ ++ push @$atoms, [ $atom_type, $atom_data ]; ++ } ++ ++ if (($$atoms[-1][0] eq "\x00\x00\x00\x00") && ++ ($$atoms[-1][1] eq "")) ++ { ++ pop @$atoms; ++ } ++ else ++ { ++ print ("* end marker missing from trailer\n"); ++ } ++ ++ return ($atoms, tell($fh)); ++} ++ ++sub format_atom ++{ ++ my ($atom) = @_; ++ ++ my $format_func = $atom_formats{$atom->[0]} || \&format_hex; ++ return $format_func->($atom->[1]); ++} ++ ++sub format_bool ++{ ++ my ($data) = @_; ++ return unpack('V', $data) ? 'true' : 'false'; ++} ++ ++sub format_int ++{ ++ my ($data) = @_; ++ return unpack('V', $data); ++} ++ ++sub format_string ++{ ++ my ($data) = @_; ++ return '"'.$data.'"'; ++} ++ ++sub format_hex ++{ ++ my ($data) = @_; ++ return unpack('H*', $data); ++} +diff --git a/scripts/mkknlimg b/scripts/mkknlimg +new file mode 100755 +index 0000000..3dff948 +--- /dev/null ++++ b/scripts/mkknlimg +@@ -0,0 +1,275 @@ ++#!/usr/bin/env perl ++# ---------------------------------------------------------------------- ++# mkknlimg by Phil Elwell for Raspberry Pi ++# based on extract-ikconfig by Dick Streefland ++# ++# (c) 2009,2010 Dick Streefland ++# (c) 2014,2015 Raspberry Pi (Trading) Limited ++# ++# Licensed under the terms of the GNU General Public License. ++# ---------------------------------------------------------------------- ++ ++use strict; ++use warnings; ++use integer; ++ ++my $trailer_magic = 'RPTL'; ++ ++my $tmpfile1 = "/tmp/mkknlimg_$$.1"; ++my $tmpfile2 = "/tmp/mkknlimg_$$.2"; ++ ++my $dtok = 0; ++my $is_283x = 0; ++ ++while (@ARGV && ($ARGV[0] =~ /^-/)) ++{ ++ my $arg = shift(@ARGV); ++ if ($arg eq '--dtok') ++ { ++ $dtok = 1; ++ } ++ elsif ($arg eq '--283x') ++ { ++ $is_283x = 1; ++ } ++ else ++ { ++ print ("* Unknown option '$arg'\n"); ++ usage(); ++ } ++} ++ ++usage() if (@ARGV != 2); ++ ++my $kernel_file = $ARGV[0]; ++my $out_file = $ARGV[1]; ++ ++if (! -r $kernel_file) ++{ ++ print ("* File '$kernel_file' not found\n"); ++ usage(); ++} ++ ++my @wanted_config_lines = ++( ++ 'CONFIG_BCM2708_DT', ++ 'CONFIG_ARCH_BCM2835' ++); ++ ++my @wanted_strings = ++( ++ 'bcm2708_fb', ++ 'brcm,bcm2835-mmc', ++ 'brcm,bcm2835-sdhost', ++ 'brcm,bcm2708-pinctrl', ++ 'brcm,bcm2835-gpio', ++ 'brcm,bcm2835-pm-wdt' ++); ++ ++my $res = try_extract($kernel_file, $tmpfile1); ++$res = try_decompress('\037\213\010', 'xy', 'gunzip', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('BZh', 'xy', 'bunzip2', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\211\114\132', 'xy', 'lzop -d', 0, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++$res = try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1, ++ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); ++ ++my $append_trailer; ++my $trailer; ++my $kver = '?'; ++ ++$append_trailer = $dtok; ++ ++if ($res) ++{ ++ $kver = $res->{''} || '?'; ++ print("Version: $kver\n"); ++ ++ $append_trailer = $dtok; ++ if (!$dtok) ++ { ++ if (config_bool($res, 'bcm2708_fb') || ++ config_bool($res, 'brcm,bcm2835-mmc') || ++ config_bool($res, 'brcm,bcm2835-sdhost')) ++ { ++ $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); ++ $dtok ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); ++ $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); ++ $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); ++ $is_283x ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); ++ $is_283x ||= config_bool($res, 'brcm,bcm2835-pm-wdt'); ++ $append_trailer = 1; ++ } ++ else ++ { ++ print ("* This doesn't look like a Raspberry Pi kernel. In pass-through mode.\n"); ++ } ++ } ++} ++elsif (!$dtok) ++{ ++ print ("* Is this a valid kernel? In pass-through mode.\n"); ++} ++ ++if ($append_trailer) ++{ ++ printf("DT: %s\n", $dtok ? "y" : "n"); ++ printf("283x: %s\n", $is_283x ? "y" : "n"); ++ ++ my @atoms; ++ ++ push @atoms, [ $trailer_magic, pack('V', 0) ]; ++ push @atoms, [ 'KVer', $kver ]; ++ push @atoms, [ 'DTOK', pack('V', $dtok) ]; ++ push @atoms, [ '283x', pack('V', $is_283x) ]; ++ ++ $trailer = pack_trailer(\@atoms); ++ $atoms[0]->[1] = pack('V', length($trailer)); ++ ++ $trailer = pack_trailer(\@atoms); ++} ++ ++my $ofh; ++my $total_len = 0; ++ ++if ($out_file eq $kernel_file) ++{ ++ die "* Failed to open '$out_file' for append\n" ++ if (!open($ofh, '>>', $out_file)); ++ $total_len = tell($ofh); ++} ++else ++{ ++ die "* Failed to open '$kernel_file'\n" ++ if (!open(my $ifh, '<', $kernel_file)); ++ die "* Failed to create '$out_file'\n" ++ if (!open($ofh, '>', $out_file)); ++ ++ my $copybuf; ++ while (1) ++ { ++ my $bytes = sysread($ifh, $copybuf, 64*1024); ++ last if (!$bytes); ++ syswrite($ofh, $copybuf, $bytes); ++ $total_len += $bytes; ++ } ++ close($ifh); ++} ++ ++if ($trailer) ++{ ++ # Pad to word-alignment ++ syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3)); ++ syswrite($ofh, $trailer); ++} ++ ++close($ofh); ++ ++exit($trailer ? 0 : 1); ++ ++END { ++ unlink($tmpfile1) if ($tmpfile1); ++ unlink($tmpfile2) if ($tmpfile2); +} + + - static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) - { -@@ -70,7 +94,8 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - break; - default: - dev_err(codec->dev, -- "Failed to set WM8804 SYSCLK, unsupported samplerate\n"); -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); - } - - snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); -@@ -96,6 +121,8 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - /* machine stream operations */ - static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { - .hw_params = snd_rpi_hifiberry_digi_hw_params, -+ .startup = snd_rpi_hifiberry_digi_startup, -+ .shutdown = snd_rpi_hifiberry_digi_shutdown, - }; - - static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { - -From fdcfdf08df6289445d33e8acaf68faa5f5b4923b Mon Sep 17 00:00:00 2001 -From: Joerg Hohensohn -Date: Sun, 1 Feb 2015 22:08:03 +0100 -Subject: [PATCH 068/216] bugfix for 32kHz sample rate, was missing - ---- - sound/soc/bcm/hifiberry_digi.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index a245995..a294a1b 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -80,6 +80,7 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - samplerate = params_rate(params); - - switch (samplerate) { -+ case 32000: - case 44100: - case 48000: - case 88200: - -From 601bc9883a6bf209e736d2b1cc5991176ed1abf3 Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 069/216] Update ds1307 driver for device-tree support - -Signed-off-by: Ryan Coe ---- - drivers/rtc/rtc-ds1307.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index 4ffabb3..c6789a7 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -1242,6 +1242,14 @@ static int ds1307_remove(struct i2c_client *client) - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id ds1307_of_match[] = { -+ { .compatible = "maxim,ds1307" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ds1307_of_match); -+#endif ++sub usage ++{ ++ print ("Usage: mkknlimg [--dtok] [--283x] \n"); ++ exit(1); ++} + - static struct i2c_driver ds1307_driver = { - .driver = { - .name = "rtc-ds1307", - -From c6e4ebd2dec4446f061cab8fa0a860e0fe7fd30a Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:26:03 -0700 -Subject: [PATCH 070/216] Add device-tree overlay for ds1307 - -Signed-off-by: Ryan Coe ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/ds1307-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/ds1307-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index c909f7b..7755a84 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -diff --git a/arch/arm/boot/dts/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -new file mode 100644 -index 0000000..7d27044 ---- /dev/null -+++ b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for DS1307 Real Time Clock -+/dts-v1/; -+/plugin/; ++sub try_extract ++{ ++ my ($knl, $tmp) = @_; + -+/ { -+ compatible = "brcm,bcm2708"; ++ my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`; + -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; ++ return undef if (!$ver); + -+ ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; ++ chomp($ver); ++ ++ my $res = { ''=>$ver }; ++ my $string_pattern = '^('.join('|', @wanted_strings).')$'; ++ ++ my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`; ++ foreach my $match (@matches) ++ { ++ chomp($match); ++ $res->{$match} = 1; ++ } ++ ++ my $config_pattern = '^('.join('|', @wanted_config_lines).')=(.*)$'; ++ my $cf1 = 'IKCFG_ST\037\213\010'; ++ my $cf2 = '0123456789'; ++ ++ my $pos = `tr "$cf1\n$cf2" "\n$cf2=" < "$knl" | grep -abo "^$cf2"`; ++ if ($pos) ++ { ++ $pos =~ s/:.*[\r\n]*$//s; ++ $pos += 8; ++ my $err = (system("tail -c+$pos \"$knl\" | zcat > $tmp 2> /dev/null") >> 8); ++ if (($err == 0) || ($err == 2)) ++ { ++ if (open(my $fh, '<', $tmp)) ++ { ++ while (my $line = <$fh>) ++ { ++ chomp($line); ++ $res->{$1} = $2 if ($line =~ /$config_pattern/); ++ } ++ ++ close($fh); ++ } ++ } ++ } ++ ++ return $res; ++} ++ ++ ++sub try_decompress ++{ ++ my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_; ++ ++ my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`; ++ if ($pos) ++ { ++ chomp($pos); ++ $pos = (split(/[\r\n]+/, $pos))[$idx]; ++ return undef if (!defined($pos)); ++ $pos =~ s/:.*[\r\n]*$//s; ++ my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null"; ++ my $err = (system($cmd) >> 8); ++ return undef if (($err != 0) && ($err != 2)); ++ ++ return try_extract($tmp2, $tmp1); ++ } ++ ++ return undef; ++} ++ ++sub pack_trailer ++{ ++ my ($atoms) = @_; ++ my $trailer = pack('VV', 0, 0); ++ for (my $i = $#$atoms; $i>=0; $i--) ++ { ++ my $atom = $atoms->[$i]; ++ $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]); ++ } ++ return $trailer; ++} ++ ++sub config_bool ++{ ++ my ($configs, $wanted) = @_; ++ my $val = $configs->{$wanted} || 'n'; ++ return (($val eq 'y') || ($val eq '1')); ++} -From 7abd2997600af8ee74045e490c6db3a41f716636 Mon Sep 17 00:00:00 2001 +From 780d72c0e43679ff58f9f3f005ef17a5fa79ee9f Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 071/216] BCM270x_DT: Add pwr_led, and the required "input" - trigger +Date: Fri, 5 Dec 2014 17:26:26 +0000 +Subject: [PATCH 25/77] fdt: Add support for the CONFIG_CMDLINE_EXTEND option -The "input" trigger makes the associated GPIO an input. This is to support -the Raspberry Pi PWR LED, which is driven by external hardware in normal use. - -N.B. pwr_led is not available on Model A or B boards. --- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 18 ++++- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 8 ++- - arch/arm/boot/dts/bcm2708.dtsi | 7 +- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 115 +++++++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 5 -- - drivers/leds/trigger/Kconfig | 7 ++ - drivers/leds/trigger/Makefile | 1 + - drivers/leds/trigger/ledtrig-input.c | 65 +++++++++++++++++ - 8 files changed, 213 insertions(+), 13 deletions(-) + drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index cde35c5d01..dd7fbfe 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -933,19 +933,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, + + /* Retrieve command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); +- if (p != NULL && l > 0) +- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else + * managed to set the command line, unless CONFIG_CMDLINE_FORCE + * is set in which case we override whatever was found earlier. ++ * ++ * However, it can be useful to be able to treat the default as ++ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. + */ ++ ((char *)data)[0] = '\0'; ++ + #ifdef CONFIG_CMDLINE +-#ifndef CONFIG_CMDLINE_FORCE +- if (!((char *)data)[0]) ++ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); ++ ++ if (p != NULL && l > 0) { ++#if defined(CONFIG_CMDLINE_EXTEND) ++ int len = strlen(data); ++ if (len > 0) { ++ strlcat(data, " ", COMMAND_LINE_SIZE); ++ len++; ++ } ++ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); ++#elif defined(CONFIG_CMDLINE_FORCE) ++ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); ++#else ++ /* Neither extend nor force - just override */ ++ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + #endif +- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); ++ } ++#else /* CONFIG_CMDLINE */ ++ if (p != NULL && l > 0) { ++ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + #endif /* CONFIG_CMDLINE */ + + pr_debug("Command line is: %s\n", (char*)data); + +From 7ff1afbc6732a16d87c5640be8fec1de73a39770 Mon Sep 17 00:00:00 2001 +From: notro +Date: Wed, 9 Jul 2014 14:46:08 +0200 +Subject: [PATCH 26/77] BCM2708: Add core Device Tree support + +Add the bare minimum needed to boot BCM2708 from a Device Tree. + +Signed-off-by: Noralf Tronnes + +BCM2708: DT: change 'axi' nodename to 'soc' + +Change DT node named 'axi' to 'soc' so it matches ARCH_BCM2835. +The VC4 bootloader fills in certain properties in the 'axi' subtree, +but since this is part of an upstreaming effort, the name is changed. + +Signed-off-by: Noralf Tronnes notro@tronnes.org + +BCM2708_DT: Correct length of the peripheral space +--- + arch/arm/boot/dts/Makefile | 27 ++ + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 140 ++++++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 130 ++++++ + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 18 + + arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 51 +++ + arch/arm/boot/dts/bcm2708.dtsi | 19 + + arch/arm/boot/dts/bcm2708_common.dtsi | 230 ++++++++++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 140 ++++++ + arch/arm/boot/dts/bcm2709.dtsi | 70 +++ + arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 45 +- + arch/arm/boot/dts/bcm2835-rpi-b.dts | 29 +- + arch/arm/boot/dts/bcm2835-rpi.dtsi | 97 +++- + arch/arm/boot/dts/bcm2835.dtsi | 45 +- + arch/arm/boot/dts/overlays/Makefile | 57 +++ + arch/arm/boot/dts/overlays/README | 493 +++++++++++++++++++++ + arch/arm/boot/dts/overlays/ads7846-overlay.dts | 83 ++++ + .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + + arch/arm/boot/dts/overlays/dht11-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 50 +++ + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 ++ + .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 ++ + .../dts/overlays/hifiberry-dacplus-overlay.dts | 39 ++ + .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 87 ++++ + arch/arm/boot/dts/overlays/hy28b-overlay.dts | 142 ++++++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 49 ++ + arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts | 13 + + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 39 ++ + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 +++ + .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 69 +++ + arch/arm/boot/dts/overlays/mmc-overlay.dts | 19 + + arch/arm/boot/dts/overlays/mz61581-overlay.dts | 109 +++++ + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 96 ++++ + .../dts/overlays/pitft28-resistive-overlay.dts | 115 +++++ + arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 34 ++ + arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 34 ++ + arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 82 ++++ + arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 ++ + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 78 ++++ + arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts | 18 + + arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts | 18 + + arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 216 +++++++++ + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 ++ + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 ++ + 45 files changed, 3316 insertions(+), 54 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts + create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708.dtsi + create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi create mode 100644 arch/arm/boot/dts/bcm2709-rpi-2-b.dts - create mode 100644 drivers/leds/trigger/ledtrig-input.c + create mode 100644 arch/arm/boot/dts/bcm2709.dtsi + create mode 100644 arch/arm/boot/dts/overlays/Makefile + create mode 100644 arch/arm/boot/dts/overlays/README + create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/dht11-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-dac-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-display-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 992736b..12de305 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1,5 +1,21 @@ + ifeq ($(CONFIG_OF),y) + ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb ++dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb ++dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb ++ ++# Raspberry Pi ++ifeq ($(CONFIG_BCM2708_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_BCM2709_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_ARCH_BCM2835),y) ++ RPI_DT_OVERLAYS=y ++endif ++ + dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb + dtb-$(CONFIG_MACH_ASM9260) += \ +@@ -660,7 +676,18 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt6592-evb.dtb \ + mt8127-moose.dtb \ + mt8135-evbp1.dtb ++ ++targets += dtbs dtbs_install ++targets += $(dtb-y) ++ + endif + + always := $(dtb-y) + clean-files := *.dtb ++ ++# Enable fixups to support overlays on BCM2708 platforms ++ifeq ($(RPI_DT_OVERLAYS),y) ++ DTC_FLAGS ?= -@ ++endif ++ ++subdir-y += overlays diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 95f03ba..b409c2c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -83,8 +83,18 @@ - pinctrl-0 = <&i2s_pins>; - }; - --&act_led { -- gpios = <&gpio 47 0>; -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+ -+ pwr_led: pwr { -+ label = "led1"; -+ linux,default-trigger = "input"; -+ gpios = <&gpio 35 0>; -+ }; - }; - - / { -@@ -97,5 +107,9 @@ - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ pwr_led_gpio = <&pwr_led>,"gpios:4"; -+ pwr_led_activelow = <&pwr_led>,"gpios:8"; -+ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 0631f45..1ecd1a1 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -83,8 +83,12 @@ - pinctrl-0 = <&i2s_pins>; - }; - --&act_led { -- gpios = <&gpio 16 1>; -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 16 1>; -+ }; - }; - - / { -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index d879316..0713a1ed 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -79,11 +79,10 @@ - - leds: leds { - compatible = "gpio-leds"; -+ }; - -- act_led: act { -- label = "ACT"; -- linux,default-trigger = "mmc0"; -- }; -+ arm-pmu { -+ compatible = "arm,arm1176-pmu"; - }; - }; - -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000..46f4908 +index 0000000..0fa2210 --- /dev/null -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,115 @@ ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -0,0 +1,140 @@ +/dts-v1/; + -+/include/ "bcm2709.dtsi" ++/include/ "bcm2708.dtsi" + +/ { -+ compatible = "brcm,bcm2709"; -+ model = "Raspberry Pi 2 Model B"; ++ compatible = "brcm,bcm2708"; ++ model = "Raspberry Pi Model B+"; + + aliases { + soc = &soc; @@ -124457,7 +118600,11 @@ index 0000000..46f4908 + gpio = &gpio; + intc = &intc; + leds = &leds; ++ audio = &audio; + sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; + }; + + sound: sound { @@ -124486,6 +118633,19 @@ index 0000000..46f4908 + }; +}; + ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; @@ -124541,10 +118701,14 @@ index 0000000..46f4908 + +/ { + __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; @@ -124553,24 +118717,8655 @@ index 0000000..46f4908 + pwr_led_gpio = <&pwr_led>,"gpios:4"; + pwr_led_activelow = <&pwr_led>,"gpios:8"; + pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts +new file mode 100644 +index 0000000..3fd49d0 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -0,0 +1,130 @@ ++/dts-v1/; ++ ++/include/ "bcm2708.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ model = "Raspberry Pi Model B"; ++ ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <28 29 30 31>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 16 1>; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +new file mode 100755 +index 0000000..238bd65 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -0,0 +1,18 @@ ++/dts-v1/; ++ ++/include/ "bcm2708-rpi-cm.dtsi" ++ ++/ { ++ model = "Raspberry Pi Compute Module"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi +new file mode 100644 +index 0000000..3da7d3b +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi +@@ -0,0 +1,51 @@ ++/include/ "bcm2708.dtsi" ++ ++/ { ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&audio { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi +new file mode 100644 +index 0000000..0d47427 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708.dtsi +@@ -0,0 +1,19 @@ ++/include/ "bcm2708_common.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ model = "BCM2708"; ++ ++ chosen { ++ /* No padding required - the boot loader can do that. */ ++ bootargs = ""; ++ }; ++ ++ soc { ++ ranges = <0x7e000000 0x20000000 0x01000000>; ++ ++ arm-pmu { ++ compatible = "arm,arm1176-pmu"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi +new file mode 100644 +index 0000000..8caa234 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708_common.dtsi +@@ -0,0 +1,230 @@ ++/include/ "skeleton.dtsi" ++ ++/ { ++ interrupt-parent = <&intc>; ++ ++ /* Onboard audio */ ++ audio: audio { ++ compatible = "brcm,bcm2835-audio"; ++ brcm,pwm-channels = <8>; ++ status = "disabled"; ++ }; ++ ++ soc: soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ dma: dma@7e007000 { ++ compatible = "brcm,bcm2835-dma"; ++ reg = <0x7e007000 0xf00>; ++ interrupts = <1 16>, ++ <1 17>, ++ <1 18>, ++ <1 19>, ++ <1 20>, ++ <1 21>, ++ <1 22>, ++ <1 23>, ++ <1 24>, ++ <1 25>, ++ <1 26>, ++ <1 27>, ++ <1 28>; ++ ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ ++ intc: interrupt-controller { ++ compatible = "brcm,bcm2708-armctrl-ic"; ++ reg = <0x7e00b200 0x200>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ watchdog: watchdog@7e100000 { ++ compatible = "brcm,bcm2835-pm-wdt"; ++ reg = <0x7e100000 0x28>; ++ status = "disabled"; ++ }; ++ ++ random: rng@7e104000 { ++ compatible = "brcm,bcm2835-rng"; ++ reg = <0x7e104000 0x10>; ++ status = "disabled"; ++ }; ++ ++ mailbox: mailbox@7e00b800 { ++ compatible = "brcm,bcm2708-vcio"; ++ reg = <0x7e00b880 0x40>; ++ interrupts = <0 1>; ++ }; ++ ++ gpio: gpio { ++ compatible = "brcm,bcm2835-gpio"; ++ reg = <0x7e200000 0xb4>; ++ interrupts = <2 17>, <2 18>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; ++ reg = <0x7e300000 0x100>; ++ interrupts = <2 30>; ++ clocks = <&clk_mmc>; ++ dmas = <&dma 11>, ++ <&dma 11>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@7e201000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7e201000 0x1000>; ++ interrupts = <2 25>; ++ clocks = <&clk_uart0 &clk_apb_p>; ++ clock-names = "uartclk","apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; // For an explanation, see ++ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 ++ status = "disabled"; ++ }; ++ ++ i2s: i2s@7e203000 { ++ compatible = "brcm,bcm2708-i2s"; ++ reg = <0x7e203000 0x20>, ++ <0x7e101098 0x02>; ++ ++ //dmas = <&dma 2>, ++ // <&dma 3>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@7e204000 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7e204000 0x1000>; ++ interrupts = <2 22>; ++ clocks = <&clk_spi>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ /* the dma channels */ ++ dmas = <&dma 6>, <&dma 7>; ++ dma-names = "tx", "rx"; ++ /* the chipselects used - <0> means native GPIO ++ * add more gpios if necessary as <&gpio 6 1> ++ * (but do not forget to make them output!) ++ */ ++ cs-gpios = <0>, <0>; ++ }; ++ ++ i2c0: i2c@7e205000 { ++ compatible = "brcm,bcm2708-i2c"; ++ reg = <0x7e205000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clk_i2c>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@7e215040 { ++ compatible = "brcm,bcm2835-aux-uart", "ns16550"; ++ reg = <0x7e215040 0x40>; ++ interrupts = <1 29>; ++ clock-frequency = <500000000>; ++ reg-shift = <2>; ++ no-loopback-test; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@7e804000 { ++ compatible = "brcm,bcm2708-i2c"; ++ reg = <0x7e804000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clk_i2c>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usb: usb@7e980000 { ++ compatible = "brcm,bcm2708-usb"; ++ reg = <0x7e980000 0x10000>, ++ <0x7e006000 0x1000>; ++ interrupts = <2 0>, ++ <1 9>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ status = "disabled"; ++ }; ++ ++ vchiq: vchiq { ++ compatible = "brcm,bcm2835-vchiq"; ++ reg = <0x7e00b840 0xf>; ++ interrupts = <0 2>; ++ }; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2835-thermal"; ++ }; ++ }; ++ ++ clocks: clocks { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_mmc: clock@0 { ++ compatible = "fixed-clock"; ++ reg = <0>; ++ #clock-cells = <0>; ++ clock-output-names = "mmc"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_i2c: clock@1 { ++ compatible = "fixed-clock"; ++ reg = <1>; ++ #clock-cells = <0>; ++ clock-output-names = "i2c"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_spi: clock@2 { ++ compatible = "fixed-clock"; ++ reg = <2>; ++ #clock-cells = <0>; ++ clock-output-names = "spi"; ++ clock-frequency = <250000000>; ++ }; ++ ++ clk_uart0: clock@3 { ++ compatible = "fixed-clock"; ++ reg = <3>; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <3000000>; ++ }; ++ ++ clk_apb_p: clock@4 { ++ compatible = "fixed-clock"; ++ reg = <4>; ++ #clock-cells = <0>; ++ clock-output-names = "apb_pclk"; ++ clock-frequency = <126000000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +new file mode 100644 +index 0000000..8aaaf1f +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -0,0 +1,140 @@ ++/dts-v1/; ++ ++/include/ "bcm2709.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2709"; ++ model = "Raspberry Pi 2 Model B"; ++ ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ audio = &audio; ++ sound = &sound; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ clocks = &clocks; ++ }; ++ ++ sound: sound { ++ }; ++}; ++ ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&mmc { ++ status = "okay"; ++ bus-width = <4>; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++ ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&gpio 35 0>; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; + }; +}; diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 15c7e65..34d2226 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi +new file mode 100644 +index 0000000..5e0b935 +--- /dev/null +++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -79,11 +79,6 @@ +@@ -0,0 +1,70 @@ ++/include/ "bcm2708_common.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2709"; ++ model = "BCM2709"; ++ ++ chosen { ++ /* No padding required - the boot loader can do that. */ ++ bootargs = ""; ++ }; ++ ++ soc { ++ ranges = <0x7e000000 0x3f000000 0x01000000>; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <3 9>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ clock-frequency = <19200000>; ++ interrupts = <3 0>, // PHYS_SECURE_PPI ++ <3 1>, // PHYS_NONSECURE_PPI ++ <3 3>, // VIRT_PPI ++ <3 2>; // HYP_PPI ++ always-on; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ v7_cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf00>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf01>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf02>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf03>; ++ clock-frequency = <800000000>; ++ }; ++ }; ++ ++ __overrides__ { ++ arm_freq = <&v7_cpu0>, "clock-frequency:0", ++ <&v7_cpu1>, "clock-frequency:0", ++ <&v7_cpu2>, "clock-frequency:0", ++ <&v7_cpu3>, "clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +index e479515..b0fb0e8 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts +@@ -4,27 +4,40 @@ + / { + compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; + model = "Raspberry Pi Model B+"; ++}; ++ ++&gpio { ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; - leds: leds { - compatible = "gpio-leds"; +- leds { +- act { +- gpios = <&gpio 47 0>; +- }; ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&act_led { ++ gpios = <&gpio 47 0>; ++}; + +- pwr { +- label = "PWR"; +- gpios = <&gpio 35 0>; +- default-state = "keep"; +- linux,default-trigger = "default-on"; +- }; ++&leds { ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&gpio 35 0>; + }; + }; + +-&gpio { +- pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; + +- /* I2S interface */ +- i2s_alt0: i2s_alt0 { +- brcm,pins = <18 19 20 21>; +- brcm,function = <4>; /* alt0 */ ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; + }; + }; +diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts +index bafa46f..b867224 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts +@@ -5,19 +5,28 @@ + compatible = "raspberrypi,model-b", "brcm,bcm2835"; + model = "Raspberry Pi Model B"; + +- leds { +- act { +- gpios = <&gpio 16 1>; +- }; +- }; + }; + + &gpio { +- pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - -- act_led: act { -- label = "led0"; -- linux,default-trigger = "mmc0"; -- }; +- /* I2S interface */ +- i2s_alt2: i2s_alt2 { ++ i2s_pins: i2s { + brcm,pins = <28 29 30 31>; +- brcm,function = <6>; /* alt2 */ ++ brcm,function = <4>; /* alt0 */ ++ }; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&act_led { ++ gpios = <&gpio 16 1>; ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; + }; + }; +diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi +index c706448..466f02b 100644 +--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi +@@ -1,51 +1,112 @@ + /include/ "bcm2835.dtsi" + + / { ++ /* This is left here in case u-boot needs it */ + memory { + reg = <0 0x10000000>; + }; + +- leds { ++ aliases { ++ soc = &soc; ++ spi0 = &spi0; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2s = &i2s; ++ gpio = &gpio; ++ intc = &intc; ++ leds = &leds; ++ sound = &sound; ++ }; ++ ++ leds: leds { + compatible = "gpio-leds"; + +- act { +- label = "ACT"; +- default-state = "keep"; +- linux,default-trigger = "heartbeat"; ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; + }; + }; ++ ++ /* Onboard audio */ ++ audio: audio { ++ compatible = "brcm,bcm2835-audio"; ++ brcm,pwm-channels = <8>; ++ status = "disabled"; ++ }; ++ ++ /* External sound card */ ++ sound: sound { ++ }; + }; + + &gpio { +- pinctrl-names = "default"; ++ spi0_pins: spi0_pins { ++ brcm,pins = <7 8 9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; + +- gpioout: gpioout { +- brcm,pins = <6>; +- brcm,function = <1>; /* GPIO out */ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; + }; + +- alt0: alt0 { +- brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; +- brcm,function = <4>; /* alt0 */ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; + }; + +- alt3: alt3 { +- brcm,pins = <48 49 50 51 52 53>; +- brcm,function = <7>; /* alt3 */ ++ spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; + }; + }; + + &i2c0 { +- status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; + }; + + &i2c1 { +- status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; + }; + +-&sdhci { ++&mmc { + status = "okay"; + bus-width = <4>; + }; ++ ++&fb { ++ status = "okay"; ++}; ++ ++/ { ++ __overrides__ { ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ audio = <&audio>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi +index 3342cb1..4b6dd65f 100644 +--- a/arch/arm/boot/dts/bcm2835.dtsi ++++ b/arch/arm/boot/dts/bcm2835.dtsi +@@ -6,14 +6,15 @@ + interrupt-parent = <&intc>; + + chosen { +- bootargs = "earlyprintk console=ttyAMA0"; ++ bootargs = ""; + }; + +- soc { ++ soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x7e000000 0x20000000 0x02000000>; ++ dma-ranges = <0x40000000 0x00000000 0x20000000>; + + timer@7e003000 { + compatible = "brcm,bcm2835-system-timer"; +@@ -50,16 +51,22 @@ + #interrupt-cells = <2>; }; +- watchdog@7e100000 { ++ watchdog: watchdog@7e100000 { + compatible = "brcm,bcm2835-pm-wdt"; + reg = <0x7e100000 0x28>; + }; + +- rng@7e104000 { ++ random: rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + }; + ++ mailbox: mailbox@7e00b800 { ++ compatible = "brcm,bcm2708-vcio"; ++ reg = <0x7e00b880 0x40>; ++ interrupts = <0 1>; ++ }; ++ + gpio: gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; +@@ -83,7 +90,7 @@ + #interrupt-cells = <2>; + }; + +- uart@7e201000 { ++ uart0: uart@7e201000 { + compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; + reg = <0x7e201000 0x1000>; + interrupts = <2 25>; +@@ -102,7 +109,7 @@ + status = "disabled"; + }; + +- spi: spi@7e204000 { ++ spi0: spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; +@@ -122,11 +129,14 @@ + status = "disabled"; + }; + +- sdhci: sdhci@7e300000 { +- compatible = "brcm,bcm2835-sdhci"; ++ mmc: mmc@7e300000 { ++ compatible = "brcm,bcm2835-mmc"; + reg = <0x7e300000 0x100>; + interrupts = <2 30>; + clocks = <&clk_mmc>; ++ dmas = <&dma 11>, ++ <&dma 11>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -140,7 +150,7 @@ + status = "disabled"; + }; + +- usb@7e980000 { ++ usb: usb@7e980000 { + compatible = "brcm,bcm2835-usb"; + reg = <0x7e980000 0x10000>; + interrupts = <1 9>; +@@ -149,6 +159,21 @@ arm-pmu { + compatible = "arm,arm1176-pmu"; + }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ status = "disabled"; ++ }; ++ ++ vchiq: vchiq { ++ compatible = "brcm,bcm2835-vchiq"; ++ reg = <0x7e00b840 0xf>; ++ interrupts = <0 2>; ++ }; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2835-thermal"; ++ }; + }; + + clocks { +@@ -161,7 +186,7 @@ + reg = <0>; + #clock-cells = <0>; + clock-output-names = "mmc"; +- clock-frequency = <100000000>; ++ clock-frequency = <250000000>; + }; + + clk_i2c: clock@1 { +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +new file mode 100644 +index 0000000..6947556 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -0,0 +1,57 @@ ++ifeq ($(CONFIG_OF),y) ++ ++# Overlays for the Raspberry Pi platform ++ ++ifeq ($(CONFIG_BCM2708_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_BCM2709_DT),y) ++ RPI_DT_OVERLAYS=y ++endif ++ifeq ($(CONFIG_ARCH_BCM2835),y) ++ RPI_DT_OVERLAYS=y ++endif ++ ++dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += dht11-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += i2s-mmap-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mcp2515-can0-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb ++ ++targets += dtbs dtbs_install ++targets += $(dtb-y) ++ ++endif ++ ++always := $(dtb-y) ++clean-files := *.dtb ++ ++# Enable fixups to support overlays on BCM2708 platforms ++ifeq ($(RPI_DT_OVERLAYS),y) ++ DTC_FLAGS ?= -@ ++endif +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +new file mode 100644 +index 0000000..3e08f98 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/README +@@ -0,0 +1,493 @@ ++Introduction ++============ ++ ++This directory contains Device Tree overlays. Device Tree makes it possible ++to support many hardware configurations with a single kernel and without the ++need to explicitly load or blacklist kernel modules. Note that this isn't a ++"pure" Device Tree configuration (c.f. MACH_BCM2835) - some on-board devices ++are still configured by the board support code, but the intention is to ++eventually reach that goal. ++ ++On Raspberry Pi, Device Tree usage is controlled from /boot/config.txt. By ++default, the Raspberry Pi kernel boots with device tree enabled. You can ++completely disable DT usage (for now) by adding: ++ ++ device_tree= ++ ++to your config.txt, which should cause your Pi to revert to the old way of ++doing things after a reboot. ++ ++In /boot you will find a .dtb for each base platform. This describes the ++hardware that is part of the Raspberry Pi board. The loader (start.elf and its ++siblings) selects the .dtb file appropriate for the platform by name, and reads ++it into memory. At this point, all of the optional interfaces (i2c, i2s, spi) ++are disabled, but they can be enabled using Device Tree parameters: ++ ++ dtparam=i2c=on,i2s=on,spi=on ++ ++However, this shouldn't be necessary in many use cases because loading an ++overlay that requires one of those interfaces will cause it to be enabled ++automatically, and it is advisable to only enable interfaces if they are ++needed. ++ ++Configuring additional, optional hardware is done using Device Tree overlays ++(see below). ++ ++raspi-config ++============ ++ ++The Advanced Options section of the raspi-config utility can enable and disable ++Device Tree use, as well as toggling the I2C and SPI interfaces. Note that it ++is possible to both enable an interface and blacklist the driver, if for some ++reason you should want to defer the loading. ++ ++Modules ++======= ++ ++As well as describing the hardware, Device Tree also gives enough information ++to allow suitable driver modules to be located and loaded, with the corollary ++that unneeded modules are not loaded. As a result it should be possible to ++remove lines from /etc/modules, and /etc/modprobe.d/raspi-blacklist.conf can ++have its contents deleted (or commented out). ++ ++Using Overlays ++============== ++ ++Overlays are loaded using the "dtoverlay" directive. As an example, consider the ++popular lirc-rpi module, the Linux Infrared Remote Control driver. In the ++pre-DT world this would be loaded from /etc/modules, with an explicit ++"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled, ++this becomes a line in config.txt: ++ ++ dtoverlay=lirc-rpi ++ ++This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By ++default it will use GPIOs 17 (out) and 18 (in), but this can be modified using ++DT parameters: ++ ++ dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13 ++ ++Parameters always have default values, although in some cases (e.g. "w1-gpio") ++it is necessary to provided multiple overlays in order to get the desired ++behaviour. See the list of overlays below for a description of the parameters and their defaults. ++ ++The Overlay and Parameter Reference ++=================================== ++ ++Name: ++Info: Configures the base Raspberry Pi hardware ++Load: ++Params: ++ audio Set to "on" to disable the onboard ALSA audio ++ interface (default "off") ++ ++ i2c_arm Set to "on" to enable the ARM's i2c interface ++ (default "off") ++ ++ i2c_vc Set to "on" to enable the i2c interface ++ usually reserved for the VideoCore processor ++ (default "off") ++ ++ i2c An alias for i2c_arm ++ ++ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface ++ (default "100000") ++ ++ i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface ++ (default "100000") ++ ++ i2c_baudrate An alias for i2c_arm_baudrate ++ ++ i2s Set to "on" to enable the i2s interface ++ (default "off") ++ ++ spi Set to "on" to enable the spi interfaces ++ (default "off") ++ ++ random Set to "on" to enable the hardware random ++ number generator (default "off") ++ ++ uart0 Set to "off" to disable uart0 (default "on") ++ ++ watchdog Set to "on" to enable the hardware watchdog ++ (default "off") ++ ++ act_led_trigger Choose which activity the LED tracks. ++ Use "heartbeat" for a nice load indicator. ++ (default "mmc") ++ ++ act_led_activelow Set to "on" to invert the sense of the LED ++ (default "off") ++ ++ act_led_gpio Set which GPIO to use for the activity LED ++ (in case you want to connect it to an external ++ device) ++ (default "16" on a non-Plus board, "47" on a ++ Plus or Pi 2) ++ ++ pwr_led_trigger ++ pwr_led_activelow ++ pwr_led_gpio ++ As for act_led_*, but using the PWR LED. ++ Not available on Model A/B boards. ++ ++ N.B. It is recommended to only enable those interfaces that are needed. ++ Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc ++ interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.) ++ Note also that i2c, i2c_arm and i2c_vc are aliases for the physical ++ interfaces i2c0 and i2c1. Use of the numeric variants is still possible ++ but deprecated because the ARM/VC assignments differ between board ++ revisions. The same board-specific mapping applies to i2c_baudrate, ++ and the other i2c baudrate parameters. ++ ++ ++Name: ads7846 ++Info: ADS7846 Touch controller ++Load: dtoverlay=ads7846,= ++Params: cs SPI bus Chip Select (default 1) ++ speed SPI bus speed (default 2Mhz, max 3.25MHz) ++ penirq GPIO used for PENIRQ. REQUIRED ++ penirq_pull Set GPIO pull (default 0=none, 2=pullup) ++ swapxy Swap x and y axis ++ xmin Minimum value on the X axis (default 0) ++ ymin Minimum value on the Y axis (default 0) ++ xmax Maximum value on the X axis (default 4095) ++ ymax Maximum value on the Y axis (default 4095) ++ pmin Minimum reported pressure value (default 0) ++ pmax Maximum reported pressure value (default 65535) ++ xohms Touchpanel sensitivity (X-plate resistance) ++ (default 400) ++ ++ penirq is required and usually xohms (60-100) has to be set as well. ++ Apart from that, pmax (255) and swapxy are also common. ++ The rest of the calibration can be done with xinput-calibrator. ++ See: github.com/notro/fbtft/wiki/FBTFT-on-Raspian ++ Device Tree binding document: ++ www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt ++ ++ ++Name: bmp085_i2c-sensor ++Info: Configures the BMP085/BMP180 digital barometric pressure and temperature ++ sensors from Bosch Sensortec ++Load: dtoverlay=bmp085_i2c-sensor ++Params: ++ ++ ++[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++Name: enc28j60 ++Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) ++Load: dtoverlay=enc28j60,= ++Params: int_pin GPIO used for INT (default 25) ++ ++ speed SPI bus speed (default 12000000) ++ ++ ++Name: hifiberry-amp ++Info: Configures the HifiBerry Amp and Amp+ audio cards ++Load: dtoverlay=hifiberry-amp ++Params: ++ ++ ++Name: hifiberry-dac ++Info: Configures the HifiBerry DAC audio card ++Load: dtoverlay=hifiberry-dac ++Params: ++ ++ ++Name: hifiberry-dacplus ++Info: Configures the HifiBerry DAC+ audio card ++Load: dtoverlay=hifiberry-dacplus ++Params: ++ ++ ++Name: hifiberry-digi ++Info: Configures the HifiBerry Digi audio card ++Load: dtoverlay=hifiberry-digi ++Params: ++ ++ ++Name: hy28a ++Info: HY28A - 2.8" TFT LCD Display Module by HAOYU Electronics ++ Default values match Texy's display shield ++Load: dtoverlay=hy28a,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ resetgpio GPIO used to reset controller ++ ++ ledgpio GPIO used to control backlight ++ ++ ++Name: hy28b ++Info: HY28B - 2.8" TFT LCD Display Module by HAOYU Electronics ++ Default values match Texy's display shield ++Load: dtoverlay=hy28b,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ resetgpio GPIO used to reset controller ++ ++ ledgpio GPIO used to control backlight ++ ++ ++Name: i2c-rtc ++Info: Adds support for a number of I2C Real Time Clock devices ++Load: dtoverlay=i2c-rtc, ++Params: ds1307 Select the DS1307 device ++ ++ ds3231 Select the DS3231 device ++ ++ pcf2127 Select the PCF2127 device ++ ++ pcf8523 Select the PCF8523 device ++ ++ pcf8563 Select the PCF8563 device ++ ++ ++Name: iqaudio-dac ++Info: Configures the IQaudio DAC audio card ++Load: dtoverlay=iqaudio-dac ++Params: ++ ++ ++Name: iqaudio-dacplus ++Info: Configures the IQaudio DAC+ audio card ++Load: dtoverlay=iqaudio-dacplus ++Params: ++ ++ ++Name: lirc-rpi ++Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi) ++ Consult the module documentation for more details. ++Load: dtoverlay=lirc-rpi,=,... ++Params: gpio_out_pin GPIO for output (default "17") ++ ++ gpio_in_pin GPIO for input (default "18") ++ ++ gpio_in_pull Pull up/down/off on the input pin ++ (default "down") ++ ++ sense Override the IR receive auto-detection logic: ++ "1" = force active high ++ "0" = force active low ++ "-1" = use auto-detection ++ (default "-1") ++ ++ softcarrier Turn the software carrier "on" or "off" ++ (default "on") ++ ++ invert "on" = invert the output pin (default "off") ++ ++ debug "on" = enable additional debug messages ++ (default "off") ++ ++ ++Name: mcp2515-can0 ++Info: Configures the MCP2515 CAN controller ++Load: dtoverlay=mcp2515-can0,= ++Params: oscillator Clock frequency for the CAN controller (Hz) ++ ++ spimaxfrequency Maximum SPI frequence (Hz) ++ ++ interrupt GPIO for interrupt signal ++ ++ ++Name: mmc ++Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock ++Load: dtoverlay=mmc,= ++Params: overclock_50 Clock (in MHz) to use when the MMC framework ++ requests 50MHz ++ force_pio Disable DMA support ++ ++ ++Name: mz61581 ++Info: MZ61581 display by Tontec ++Load: dtoverlay=mz61581,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++[ The pcf8523-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++[ The pcf8563-rtc overlay has been deleted. See i2c-rtc. ] ++ ++ ++Name: piscreen ++Info: PiScreen display by OzzMaker.com ++Load: dtoverlay=piscreen,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++Name: pitft28-resistive ++Info: Adafruit PiTFT 2.8" resistive touch screen ++Load: dtoverlay=pitft28-resistive,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ ++Name: pps-gpio ++Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). ++Load: dtoverlay=pps-gpio,= ++Params: gpiopin Input GPIO (default "18") ++ ++ ++Name: rpi-dac ++Info: Configures the RPi DAC audio card ++Load: dtoverlay=rpi-dac ++Params: ++ ++ ++Name: rpi-display ++Info: RPi-Display - 2.8" Touch Display by Watterott ++Load: dtoverlay=rpi-display,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ xohms Touchpanel sensitivity (X-plate resistance) ++ ++ ++Name: rpi-proto ++Info: Configures the RPi Proto audio card ++Load: dtoverlay=rpi-proto ++Params: ++ ++ ++Name: sdhost ++Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock ++Load: dtoverlay=sdhost,= ++Params: overclock_50 Clock (in MHz) to use when the MMC framework ++ requests 50MHz ++ force_pio Disable DMA support ++ ++ ++Name: spi-bcm2708 ++Info: Selects the bcm2708-spi SPI driver ++Load: dtoverlay=spi-bcm2708 ++Params: ++ ++ ++Name: spi-bcm2835 ++Info: Selects the bcm2835-spi SPI driver ++Load: dtoverlay=spi-bcm2835 ++Params: ++ ++ ++Name: tinylcd35 ++Info: 3.5" Color TFT Display by www.tinylcd.com ++ Options: Touch, RTC, keypad ++Load: dtoverlay=tinylcd35,= ++Params: speed Display SPI bus speed ++ ++ rotate Display rotation {0,90,180,270} ++ ++ fps Delay between frame updates ++ ++ debug Debug output level {0-7} ++ ++ touch Enable touch panel ++ ++ touchgpio Touch controller IRQ GPIO ++ ++ xohms Touchpanel: Resistance of X-plate in ohms ++ ++ rtc-pcf PCF8563 Real Time Clock ++ ++ rtc-ds DS1307 Real Time Clock ++ ++ keypad Enable keypad ++ ++ Examples: ++ Display with touchpanel, PCF8563 RTC and keypad: ++ dtoverlay=tinylcd35,touch,rtc-pcf,keypad ++ Old touch display: ++ dtoverlay=tinylcd35,touch,touchgpio=3 ++ ++ ++Name: w1-gpio ++Info: Configures the w1-gpio Onewire interface module. ++ Use this overlay if you *don't* need a GPIO to drive an external pullup. ++Load: dtoverlay=w1-gpio,= ++Params: gpiopin GPIO for I/O (default "4") ++ ++ pullup Non-zero, "on", or "y" to enable the parasitic ++ power (2-wire, power-on-data) feature ++ ++ ++Name: w1-gpio-pullup ++Info: Configures the w1-gpio Onewire interface module. ++ Use this overlay if you *do* need a GPIO to drive an external pullup. ++Load: dtoverlay=w1-gpio-pullup,=,... ++Params: gpiopin GPIO for I/O (default "4") ++ ++ pullup Non-zero, "on", or "y" to enable the parasitic ++ power (2-wire, power-on-data) feature ++ ++ extpullup GPIO for external pullup (default "5") ++ ++ ++Troubleshooting ++=============== ++ ++If you are experiencing problems that you think are DT-related, enable DT ++diagnostic output by adding this to /boot/config.txt: ++ ++ dtdebug=on ++ ++and rebooting. Then run: ++ ++ sudo vcdbg log msg ++ ++and look for relevant messages. ++ ++Further reading ++=============== ++ ++This is only meant to be a quick introduction to the subject of Device Tree on ++Raspberry Pi. There is a more complete explanation here: ++ ++http://www.raspberrypi.org/documentation/configuration/device-tree.md +diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts +new file mode 100644 +index 0000000..6a92cd1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts +@@ -0,0 +1,83 @@ ++/* ++ * Generic Device Tree overlay for the ADS7846 touch controller ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ ads7846_pins: ads7846_pins { ++ brcm,pins = <255>; /* illegal default value */ ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ads7846: ads7846@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ads7846_pins>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <255 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 255 0>; ++ ++ /* driver defaults */ ++ ti,x-min = /bits/ 16 <0>; ++ ti,y-min = /bits/ 16 <0>; ++ ti,x-max = /bits/ 16 <0x0FFF>; ++ ti,y-max = /bits/ 16 <0x0FFF>; ++ ti,pressure-min = /bits/ 16 <0>; ++ ti,pressure-max = /bits/ 16 <0xFFFF>; ++ ti,x-plate-ohms = /bits/ 16 <400>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ cs = <&ads7846>,"reg:0"; ++ speed = <&ads7846>,"spi-max-frequency:0"; ++ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ ++ <&ads7846>,"interrupts:0", ++ <&ads7846>,"pendown-gpio:4"; ++ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; ++ swapxy = <&ads7846>,"ti,swap-xy?"; ++ xmin = <&ads7846>,"ti,x-min;0"; ++ ymin = <&ads7846>,"ti,y-min;0"; ++ xmax = <&ads7846>,"ti,x-max;0"; ++ ymax = <&ads7846>,"ti,y-max;0"; ++ pmin = <&ads7846>,"ti,pressure-min;0"; ++ pmax = <&ads7846>,"ti,pressure-max;0"; ++ xohms = <&ads7846>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts +new file mode 100644 +index 0000000..b830bf2 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts +@@ -0,0 +1,23 @@ ++// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/dht11-overlay.dts b/arch/arm/boot/dts/overlays/dht11-overlay.dts +new file mode 100644 +index 0000000..9bf67fd +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dht11-overlay.dts +@@ -0,0 +1,39 @@ ++/* ++ * Overlay for the DHT11/21/22 humidity/temperature sensor modules. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ dht11: dht11@0 { ++ compatible = "dht11"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dht11_pins>; ++ gpios = <&gpio 4 0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ dht11_pins: dht11_pins { ++ brcm,pins = <4>; ++ brcm,function = <0>; // in ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&dht11_pins>,"brcm,pins:0", ++ <&dht11>,"gpios:4"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts +new file mode 100644 +index 0000000..8fae869 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts +@@ -0,0 +1,50 @@ ++// Overlay for the Microchip ENC28J60 Ethernet Controller ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ eth1: enc28j60@0{ ++ compatible = "microchip,enc28j60"; ++ reg = <0>; /* CE0 */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð1_pins>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 0x2>; /* falling edge */ ++ spi-max-frequency = <12000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ eth1_pins: eth1_pins { ++ brcm,pins = <25>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <0>; /* none */ ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <ð1>, "interrupts:0", ++ <ð1_pins>, "brcm,pins:0"; ++ speed = <ð1>, "spi-max-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +new file mode 100644 +index 0000000..2c81448 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry Amp/Amp+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-amp"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ tas5713@1b { ++ #sound-dai-cells = <0>; ++ compatible = "ti,tas5713"; ++ reg = <0x1b>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +new file mode 100644 +index 0000000..5e7633a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for HiFiBerry DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +new file mode 100644 +index 0000000..deb9c625 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry DAC+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-dacplus"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4d { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4d>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +new file mode 100644 +index 0000000..d0e0d8a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for HiFiBerry Digi ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "hifiberry,hifiberry-digi"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8804@3b { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hy28a-overlay.dts b/arch/arm/boot/dts/overlays/hy28a-overlay.dts +new file mode 100644 +index 0000000..3cd3083 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts +@@ -0,0 +1,87 @@ ++/* ++ * Device Tree overlay for HY28A display ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ hy28a_pins: hy28a_pins { ++ brcm,pins = <17 25 18>; ++ brcm,function = <0 1 1>; /* in out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hy28a: hy28a@0{ ++ compatible = "ilitek,ili9320"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hy28a_pins>; ++ ++ spi-max-frequency = <32000000>; ++ spi-cpol; ++ spi-cpha; ++ rotate = <270>; ++ bgr; ++ fps = <50>; ++ buswidth = <8>; ++ startbyte = <0x70>; ++ reset-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ }; ++ ++ hy28a_ts: hy28a-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&hy28a>,"spi-max-frequency:0"; ++ rotate = <&hy28a>,"rotate:0"; ++ fps = <&hy28a>,"fps:0"; ++ debug = <&hy28a>,"debug:0"; ++ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; ++ resetgpio = <&hy28a>,"reset-gpios:4", ++ <&hy28a_pins>, "brcm,pins:1"; ++ ledgpio = <&hy28a>,"led-gpios:4", ++ <&hy28a_pins>, "brcm,pins:2"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/hy28b-overlay.dts b/arch/arm/boot/dts/overlays/hy28b-overlay.dts +new file mode 100644 +index 0000000..f774c4a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts +@@ -0,0 +1,142 @@ ++/* ++ * Device Tree overlay for HY28b display shield by Texy ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ hy28b_pins: hy28b_pins { ++ brcm,pins = <17 25 18>; ++ brcm,function = <0 1 1>; /* in out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hy28b: hy28b@0{ ++ compatible = "ilitek,ili9325"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hy28b_pins>; ++ ++ spi-max-frequency = <48000000>; ++ spi-cpol; ++ spi-cpha; ++ rotate = <270>; ++ bgr; ++ fps = <50>; ++ buswidth = <8>; ++ startbyte = <0x70>; ++ reset-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 1>; ++ ++ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; ++ ++ init = <0x10000e7 0x0010 ++ 0x1000000 0x0001 ++ 0x1000001 0x0100 ++ 0x1000002 0x0700 ++ 0x1000003 0x1030 ++ 0x1000004 0x0000 ++ 0x1000008 0x0207 ++ 0x1000009 0x0000 ++ 0x100000a 0x0000 ++ 0x100000c 0x0001 ++ 0x100000d 0x0000 ++ 0x100000f 0x0000 ++ 0x1000010 0x0000 ++ 0x1000011 0x0007 ++ 0x1000012 0x0000 ++ 0x1000013 0x0000 ++ 0x2000032 ++ 0x1000010 0x1590 ++ 0x1000011 0x0227 ++ 0x2000032 ++ 0x1000012 0x009c ++ 0x2000032 ++ 0x1000013 0x1900 ++ 0x1000029 0x0023 ++ 0x100002b 0x000e ++ 0x2000032 ++ 0x1000020 0x0000 ++ 0x1000021 0x0000 ++ 0x2000032 ++ 0x1000050 0x0000 ++ 0x1000051 0x00ef ++ 0x1000052 0x0000 ++ 0x1000053 0x013f ++ 0x1000060 0xa700 ++ 0x1000061 0x0001 ++ 0x100006a 0x0000 ++ 0x1000080 0x0000 ++ 0x1000081 0x0000 ++ 0x1000082 0x0000 ++ 0x1000083 0x0000 ++ 0x1000084 0x0000 ++ 0x1000085 0x0000 ++ 0x1000090 0x0010 ++ 0x1000092 0x0000 ++ 0x1000093 0x0003 ++ 0x1000095 0x0110 ++ 0x1000097 0x0000 ++ 0x1000098 0x0000 ++ 0x1000007 0x0133 ++ 0x1000020 0x0000 ++ 0x1000021 0x0000 ++ 0x2000064>; ++ debug = <0>; ++ }; ++ ++ hy28b_ts: hy28b-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&hy28b>,"spi-max-frequency:0"; ++ rotate = <&hy28b>,"rotate:0"; ++ fps = <&hy28b>,"fps:0"; ++ debug = <&hy28b>,"debug:0"; ++ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; ++ resetgpio = <&hy28b>,"reset-gpios:4", ++ <&hy28b_pins>, "brcm,pins:1"; ++ ledgpio = <&hy28b>,"led-gpios:4", ++ <&hy28b_pins>, "brcm,pins:2"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +new file mode 100644 +index 0000000..6bccfdc +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +@@ -0,0 +1,49 @@ ++// Definitions for several I2C based Real Time Clocks ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ds1307: ds1307@68 { ++ compatible = "maxim,ds1307"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ ds3231: ds3231@68 { ++ compatible = "maxim,ds3231"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ pcf2127: pcf2127@51 { ++ compatible = "nxp,pcf2127"; ++ reg = <0x51>; ++ status = "disable"; ++ }; ++ pcf8523: pcf8523@68 { ++ compatible = "nxp,pcf8523"; ++ reg = <0x68>; ++ status = "disable"; ++ }; ++ pcf8563: pcf8563@51 { ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ status = "disable"; ++ }; ++ }; ++ }; ++ __overrides__ { ++ ds1307 = <&ds1307>,"status"; ++ ds3231 = <&ds3231>,"status"; ++ pcf2127 = <&pcf2127>,"status"; ++ pcf8523 = <&pcf8523>,"status"; ++ pcf8563 = <&pcf8563>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts b/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts +new file mode 100644 +index 0000000..a11160a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ brcm,enable-mmap; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +new file mode 100644 +index 0000000..ea8173e +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for IQaudIO DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "iqaudio,iqaudio-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4c>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +new file mode 100644 +index 0000000..735d8ab +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for IQaudIO DAC+ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "iqaudio,iqaudio-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4c>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts +new file mode 100644 +index 0000000..7d5d82b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts +@@ -0,0 +1,57 @@ ++// Definitions for lirc-rpi module ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ lirc_rpi: lirc_rpi { ++ compatible = "rpi,lirc-rpi"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lirc_pins>; ++ status = "okay"; ++ ++ // Override autodetection of IR receiver circuit ++ // (0 = active high, 1 = active low, -1 = no override ) ++ rpi,sense = <0xffffffff>; ++ ++ // Software carrier ++ // (0 = off, 1 = on) ++ rpi,softcarrier = <1>; ++ ++ // Invert output ++ // (0 = off, 1 = on) ++ rpi,invert = <0>; ++ ++ // Enable debugging messages ++ // (0 = off, 1 = on) ++ rpi,debug = <0>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ lirc_pins: lirc_pins { ++ brcm,pins = <17 18>; ++ brcm,function = <1 0>; // out in ++ brcm,pull = <0 1>; // off down ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; ++ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; ++ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; ++ ++ sense = <&lirc_rpi>,"rpi,sense:0"; ++ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; ++ invert = <&lirc_rpi>,"rpi,invert:0"; ++ debug = <&lirc_rpi>,"rpi,debug:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts +new file mode 100755 +index 0000000..398d59c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts +@@ -0,0 +1,69 @@ ++/* ++ * Device tree overlay for mcp251x/can0 on spi0.0 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* disable spi-dev for spi0.0 */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ spidev@0{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ /* the interrupt pin of the can-controller */ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ can0_pins: can0_pins { ++ brcm,pins = <25>; ++ brcm,function = <0>; /* input */ ++ }; ++ }; ++ }; ++ ++ /* the clock/oscillator of the can-controller */ ++ fragment@2 { ++ target-path = "/clocks"; ++ __overlay__ { ++ /* external oscillator of mcp2515 on SPI0.0 */ ++ can0_osc: can0_osc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ /* the spi config of the can-controller itself binding everything together */ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ can0: mcp2515@0 { ++ reg = <0>; ++ compatible = "microchip,mcp2515"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&can0_pins>; ++ spi-max-frequency = <10000000>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 0x2>; ++ clocks = <&can0_osc>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ oscillator = <&can0_osc>,"clock-frequency:0"; ++ spimaxfrequency = <&can0>,"spi-max-frequency:0"; ++ interrupt = <&can0_pins>,"brcm,pins:0",<&can0>,"interrupts:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts +new file mode 100644 +index 0000000..0a37cf4 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts +@@ -0,0 +1,19 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&mmc>; ++ ++ __overlay__ { ++ brcm,overclock-50 = <0>; ++ }; ++ }; ++ ++ __overrides__ { ++ overclock_50 = <&mmc>,"brcm,overclock-50:0"; ++ force_pio = <&mmc>,"brcm,force-pio?"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/mz61581-overlay.dts b/arch/arm/boot/dts/overlays/mz61581-overlay.dts +new file mode 100644 +index 0000000..c06fe12 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts +@@ -0,0 +1,109 @@ ++/* ++ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ mz61581_pins: mz61581_pins { ++ brcm,pins = <4 15 18 25>; ++ brcm,function = <0 1 1 1>; /* in out out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mz61581: mz61581@0{ ++ compatible = "samsung,s6d02a1"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mz61581_pins>; ++ ++ spi-max-frequency = <128000000>; ++ spi-cpol; ++ spi-cpha; ++ ++ width = <320>; ++ height = <480>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ ++ reset-gpios = <&gpio 15 0>; ++ dc-gpios = <&gpio 25 0>; ++ led-gpios = <&gpio 18 0>; ++ ++ init = <0x10000b0 00 ++ 0x1000011 ++ 0x20000ff ++ 0x10000b3 0x02 0x00 0x00 0x00 ++ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 ++ 0x10000c1 0x08 0x16 0x08 0x08 ++ 0x10000c4 0x11 0x07 0x03 0x03 ++ 0x10000c6 0x00 ++ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 ++ 0x1000035 0x00 ++ 0x1000036 0xa0 ++ 0x100003a 0x55 ++ 0x1000044 0x00 0x01 ++ 0x10000d0 0x07 0x07 0x1d 0x03 ++ 0x10000d1 0x03 0x30 0x10 ++ 0x10000d2 0x03 0x14 0x04 ++ 0x1000029 ++ 0x100002c>; ++ ++ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ ++ debug = <3>; ++ }; ++ ++ mz61581_ts: mz61581_ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <4 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 4 0>; ++ ++ ti,x-plate-ohms = /bits/ 16 <60>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&mz61581>, "spi-max-frequency:0"; ++ rotate = <&mz61581>, "rotate:0"; ++ fps = <&mz61581>, "fps:0"; ++ debug = <&mz61581>, "debug:0"; ++ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts +new file mode 100644 +index 0000000..ba4ad33 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts +@@ -0,0 +1,96 @@ ++/* ++ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ piscreen_pins: piscreen_pins { ++ brcm,pins = <17 25 24 22>; ++ brcm,function = <0 1 1 1>; /* in out out out */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ piscreen: piscreen@0{ ++ compatible = "ilitek,ili9486"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&piscreen_pins>; ++ ++ spi-max-frequency = <24000000>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ regwidth = <16>; ++ reset-gpios = <&gpio 25 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 22 1>; ++ debug = <0>; ++ ++ init = <0x10000b0 0x00 ++ 0x1000011 ++ 0x20000ff ++ 0x100003a 0x55 ++ 0x1000036 0x28 ++ 0x10000c2 0x44 ++ 0x10000c5 0x00 0x00 0x00 0x00 ++ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 ++ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 ++ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 ++ 0x1000011 ++ 0x1000029>; ++ }; ++ ++ piscreen_ts: piscreen-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <17 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 17 0>; ++ ti,swap-xy; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&piscreen>,"spi-max-frequency:0"; ++ rotate = <&piscreen>,"rotate:0"; ++ fps = <&piscreen>,"fps:0"; ++ debug = <&piscreen>,"debug:0"; ++ xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts +new file mode 100644 +index 0000000..d506eae +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts +@@ -0,0 +1,115 @@ ++/* ++ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pitft_pins: pitft_pins { ++ brcm,pins = <24 25>; ++ brcm,function = <0 1>; /* in out */ ++ brcm,pull = <2 0>; /* pullup none */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pitft: pitft@0{ ++ compatible = "ilitek,ili9340"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pitft_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <90>; ++ fps = <25>; ++ bgr; ++ buswidth = <8>; ++ dc-gpios = <&gpio 25 0>; ++ debug = <0>; ++ }; ++ ++ pitft_ts@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "st,stmpe610"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ ++ interrupts = <24 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ interrupt-controller; ++ ++ stmpe_touchscreen { ++ compatible = "st,stmpe-ts"; ++ st,sample-time = <4>; ++ st,mod-12b = <1>; ++ st,ref-sel = <0>; ++ st,adc-freq = <2>; ++ st,ave-ctrl = <3>; ++ st,touch-det-delay = <4>; ++ st,settling = <2>; ++ st,fraction-z = <7>; ++ st,i-drive = <0>; ++ }; ++ ++ stmpe_gpio: stmpe_gpio { ++ #gpio-cells = <2>; ++ compatible = "st,stmpe-gpio"; ++ /* ++ * only GPIO2 is wired/available ++ * and it is wired to the backlight ++ */ ++ st,norequest-mask = <0x7b>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/soc"; ++ __overlay__ { ++ backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&stmpe_gpio 2 0>; ++ default-on; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&pitft>,"spi-max-frequency:0"; ++ rotate = <&pitft>,"rotate:0"; ++ fps = <&pitft>,"fps:0"; ++ debug = <&pitft>,"debug:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts +new file mode 100644 +index 0000000..40bf0e1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ pps: pps { ++ compatible = "pps-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pps_pins>; ++ gpios = <&gpio 18 0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pps_pins: pps_pins { ++ brcm,pins = <18>; ++ brcm,function = <0>; // in ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&pps>,"gpios:4", ++ <&pps_pins>,"brcm,pins:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts +new file mode 100644 +index 0000000..7fc6ac9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts +@@ -0,0 +1,34 @@ ++// Definitions for RPi DAC ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "rpi,rpi-dac"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ pcm1794a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm1794a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts +new file mode 100644 +index 0000000..a8fa974 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts +@@ -0,0 +1,82 @@ ++/* ++ * Device Tree overlay for rpi-display by Watterott ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ rpi_display_pins: rpi_display_pins { ++ brcm,pins = <18 23 24 25>; ++ brcm,function = <1 1 1 0>; /* out out out in */ ++ brcm,pull = <0 0 0 2>; /* - - - up */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rpidisplay: rpi-display@0{ ++ compatible = "ilitek,ili9341"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rpi_display_pins>; ++ ++ spi-max-frequency = <32000000>; ++ rotate = <270>; ++ bgr; ++ fps = <30>; ++ buswidth = <8>; ++ reset-gpios = <&gpio 23 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ }; ++ ++ rpidisplay_ts: rpi-display-ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <25 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 25 0>; ++ ti,x-plate-ohms = /bits/ 16 <60>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ __overrides__ { ++ speed = <&rpidisplay>,"spi-max-frequency:0"; ++ rotate = <&rpidisplay>,"rotate:0"; ++ fps = <&rpidisplay>,"fps:0"; ++ debug = <&rpidisplay>,"debug:0"; ++ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts +new file mode 100644 +index 0000000..2029930 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for Rpi-Proto ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "rpi,rpi-proto"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8731@1a { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8731"; ++ reg = <0x1a>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +new file mode 100644 +index 0000000..8fb28e9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -0,0 +1,78 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&soc>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ sdhost: sdhost@7e202000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7e202000 0x100>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdhost_pins>; ++ interrupts = <2 24>; ++ clocks = <&clk_sdhost>; ++ dmas = <&dma 13>, ++ <&dma 13>; ++ dma-names = "tx", "rx"; ++ brcm,delay-after-stop = <0>; ++ brcm,overclock-50 = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&clocks>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_sdhost: sdhost { ++ compatible = "fixed-clock"; ++ reg = <0>; ++ #clock-cells = <0>; ++ clock-output-names = "sdhost"; ++ clock-frequency = <250000000>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&gpio>; ++ __overlay__ { ++ sdhost_pins: sdhost_pins { ++ brcm,pins = <48 49 50 51 52 53>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&mmc>; ++ __overlay__ { ++ /* Find a way to disable the other driver */ ++ compatible = ""; ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/__overrides__"; ++ __overlay__ { ++ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; ++ }; ++ }; ++ ++ __overrides__ { ++ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; ++ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; ++ force_pio = <&sdhost>,"brcm,force-pio?"; ++ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts +new file mode 100644 +index 0000000..e378ef1 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts +@@ -0,0 +1,18 @@ ++/* ++ * Device tree overlay for spi-bcm2835 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ compatible = "brcm,bcm2708-spi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts +new file mode 100644 +index 0000000..fc1e39b +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts +@@ -0,0 +1,18 @@ ++/* ++ * Device tree overlay for spi-bcm2835 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ compatible = "brcm,bcm2835-spi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts +new file mode 100644 +index 0000000..f7102c8 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts +@@ -0,0 +1,216 @@ ++/* ++ * tinylcd35-overlay.dts ++ * ++ * ------------------------------------------------- ++ * www.tinlylcd.com ++ * ------------------------------------------------- ++ * Device---Driver-----BUS GPIO's ++ * display tinylcd35 spi0.0 25 24 18 ++ * touch ads7846 spi0.1 5 ++ * rtc ds1307 i2c1-0068 ++ * rtc pcf8563 i2c1-0051 ++ * keypad gpio-keys --------- 17 22 27 23 28 ++ * ++ * ++ * TinyLCD.com 3.5 inch TFT ++ * ++ * Version 001 ++ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework ++ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. ++ * ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ tinylcd35_pins: tinylcd35_pins { ++ brcm,pins = <25 24 18>; ++ brcm,function = <1>; /* out */ ++ }; ++ tinylcd35_ts_pins: tinylcd35_ts_pins { ++ brcm,pins = <5>; ++ brcm,function = <0>; /* in */ ++ }; ++ keypad_pins: keypad_pins { ++ brcm,pins = <4 17 22 23 27>; ++ brcm,function = <0>; /* in */ ++ brcm,pull = <1>; /* down */ ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tinylcd35: tinylcd35@0{ ++ compatible = "neosec,tinylcd"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&tinylcd35_pins>, ++ <&tinylcd35_ts_pins>; ++ ++ spi-max-frequency = <48000000>; ++ rotate = <270>; ++ fps = <20>; ++ bgr; ++ buswidth = <8>; ++ reset-gpios = <&gpio 25 0>; ++ dc-gpios = <&gpio 24 0>; ++ led-gpios = <&gpio 18 1>; ++ debug = <0>; ++ ++ init = <0x10000B0 0x80 ++ 0x10000C0 0x0A 0x0A ++ 0x10000C1 0x01 0x01 ++ 0x10000C2 0x33 ++ 0x10000C5 0x00 0x42 0x80 ++ 0x10000B1 0xD0 0x11 ++ 0x10000B4 0x02 ++ 0x10000B6 0x00 0x22 0x3B ++ 0x10000B7 0x07 ++ 0x1000036 0x58 ++ 0x10000F0 0x36 0xA5 0xD3 ++ 0x10000E5 0x80 ++ 0x10000E5 0x01 ++ 0x10000B3 0x00 ++ 0x10000E5 0x00 ++ 0x10000F0 0x36 0xA5 0x53 ++ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 ++ 0x100003A 0x55 ++ 0x1000011 ++ 0x2000001 ++ 0x1000029>; ++ }; ++ ++ tinylcd35_ts: tinylcd35_ts@1 { ++ compatible = "ti,ads7846"; ++ reg = <1>; ++ status = "disabled"; ++ ++ spi-max-frequency = <2000000>; ++ interrupts = <5 2>; /* high-to-low edge triggered */ ++ interrupt-parent = <&gpio>; ++ pendown-gpio = <&gpio 5 0>; ++ ti,x-plate-ohms = /bits/ 16 <100>; ++ ti,pressure-max = /bits/ 16 <255>; ++ }; ++ }; ++ }; ++ ++ /* RTC */ ++ ++ fragment@3 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pcf8563: pcf8563@51 { ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ds1307: ds1307@68 { ++ compatible = "maxim,ds1307"; ++ reg = <0x68>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ /* ++ * Values for input event code is found under the ++ * 'Keys and buttons' heading in include/uapi/linux/input.h ++ */ ++ fragment@5 { ++ target-path = "/soc"; ++ __overlay__ { ++ keypad: keypad { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&keypad_pins>; ++ status = "disabled"; ++ autorepeat; ++ ++ button@17 { ++ label = "GPIO KEY_UP"; ++ linux,code = <103>; ++ gpios = <&gpio 17 0>; ++ }; ++ button@22 { ++ label = "GPIO KEY_DOWN"; ++ linux,code = <108>; ++ gpios = <&gpio 22 0>; ++ }; ++ button@27 { ++ label = "GPIO KEY_LEFT"; ++ linux,code = <105>; ++ gpios = <&gpio 27 0>; ++ }; ++ button@23 { ++ label = "GPIO KEY_RIGHT"; ++ linux,code = <106>; ++ gpios = <&gpio 23 0>; ++ }; ++ button@4 { ++ label = "GPIO KEY_ENTER"; ++ linux,code = <28>; ++ gpios = <&gpio 4 0>; ++ }; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ speed = <&tinylcd35>,"spi-max-frequency:0"; ++ rotate = <&tinylcd35>,"rotate:0"; ++ fps = <&tinylcd35>,"fps:0"; ++ debug = <&tinylcd35>,"debug:0"; ++ touch = <&tinylcd35_ts>,"status"; ++ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", ++ <&tinylcd35_ts>,"interrupts:0", ++ <&tinylcd35_ts>,"pendown-gpio:4"; ++ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; ++ rtc-pcf = <&i2c1>,"status", ++ <&pcf8563>,"status"; ++ rtc-ds = <&i2c1>,"status", ++ <&ds1307>,"status"; ++ keypad = <&keypad>,"status"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts +new file mode 100644 +index 0000000..29a3b48 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for w1-gpio module (without external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&w1_pins>; ++ gpios = <&gpio 4 0>; ++ rpi,parasitic-power = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ w1_pins: w1_pins { ++ brcm,pins = <4>; ++ brcm,function = <0>; // in (initially) ++ brcm,pull = <0>; // off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&w1>,"gpios:4", ++ <&w1_pins>,"brcm,pins:0"; ++ pullup = <&w1>,"rpi,parasitic-power:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +new file mode 100644 +index 0000000..66a98f6 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts +@@ -0,0 +1,41 @@ ++// Definitions for w1-gpio module (with external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&w1_pins>; ++ gpios = <&gpio 4 0>, <&gpio 5 1>; ++ rpi,parasitic-power = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ w1_pins: w1_pins { ++ brcm,pins = <4 5>; ++ brcm,function = <0 1>; // in out ++ brcm,pull = <0 0>; // off off ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpiopin = <&w1>,"gpios:4", ++ <&w1_pins>,"brcm,pins:0"; ++ extpullup = <&w1>,"gpios:16", ++ <&w1_pins>,"brcm,pins:4"; ++ pullup = <&w1>,"rpi,parasitic-power:0"; ++ }; ++}; + +From 4bd17cf8893beb8fb36fe6e321abfe2bc091eb17 Mon Sep 17 00:00:00 2001 +From: Siarhei Siamashka +Date: Mon, 17 Jun 2013 13:32:11 +0300 +Subject: [PATCH 27/77] fbdev: add FBIOCOPYAREA ioctl + +Based on the patch authored by Ali Gholami Rudi at + https://lkml.org/lkml/2009/7/13/153 + +Provide an ioctl for userspace applications, but only if this operation +is hardware accelerated (otherwide it does not make any sense). + +Signed-off-by: Siarhei Siamashka +--- + drivers/video/fbdev/core/fbmem.c | 30 ++++++++++++++++++++++++++++++ + include/uapi/linux/fb.h | 5 +++++ + 2 files changed, 35 insertions(+) + +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c +index 0705d88..771992a 100644 +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) + } + EXPORT_SYMBOL(fb_blank); + ++static int fb_copyarea_user(struct fb_info *info, ++ struct fb_copyarea *copy) ++{ ++ int ret = 0; ++ if (!lock_fb_info(info)) ++ return -ENODEV; ++ if (copy->dx + copy->width > info->var.xres || ++ copy->sx + copy->width > info->var.xres || ++ copy->dy + copy->height > info->var.yres || ++ copy->sy + copy->height > info->var.yres) { ++ ret = -EINVAL; ++ goto out; ++ } ++ info->fbops->fb_copyarea(info, copy); ++out: ++ unlock_fb_info(info); ++ return ret; ++} ++ + static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) + { +@@ -1094,6 +1113,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + struct fb_cmap cmap_from; + struct fb_cmap_user cmap; + struct fb_event event; ++ struct fb_copyarea copy; + void __user *argp = (void __user *)arg; + long ret = 0; + +@@ -1211,6 +1231,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unlock_fb_info(info); + console_unlock(); + break; ++ case FBIOCOPYAREA: ++ if (info->flags & FBINFO_HWACCEL_COPYAREA) { ++ /* only provide this ioctl if it is accelerated */ ++ if (copy_from_user(©, argp, sizeof(copy))) ++ return -EFAULT; ++ ret = fb_copyarea_user(info, ©); ++ break; ++ } ++ /* fall through */ + default: + if (!lock_fb_info(info)) + return -ENODEV; +@@ -1365,6 +1394,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, + case FBIOPAN_DISPLAY: + case FBIOGET_CON2FBMAP: + case FBIOPUT_CON2FBMAP: ++ case FBIOCOPYAREA: + arg = (unsigned long) compat_ptr(arg); + case FBIOBLANK: + ret = do_fb_ioctl(info, cmd, arg); +diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h +index fb795c3..fa72af0 100644 +--- a/include/uapi/linux/fb.h ++++ b/include/uapi/linux/fb.h +@@ -34,6 +34,11 @@ + #define FBIOPUT_MODEINFO 0x4617 + #define FBIOGET_DISPINFO 0x4618 + #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) ++/* ++ * HACK: use 'z' in order not to clash with any other ioctl numbers which might ++ * be concurrently added to the mainline kernel ++ */ ++#define FBIOCOPYAREA _IOW('z', 0x21, struct fb_copyarea) + + #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ + #define FB_TYPE_PLANES 1 /* Non interleaved planes */ + +From 54459bf0dcbd9019a1bc98cdc77a5c37811c1be5 Mon Sep 17 00:00:00 2001 +From: Harm Hanemaaijer +Date: Thu, 20 Jun 2013 20:21:39 +0200 +Subject: [PATCH 30/77] 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 +console monochrome imageblit function used to draw console text is +suboptimal for common pixel depths such as 16bpp and 32bpp. The existing +code is quite general and can deal with several pixel depths. By creating +special case functions for 16bpp and 32bpp, by far the most common pixel +formats used on modern systems, a significant speed-up is attained +which can be readily felt on ARM-based devices like the Raspberry Pi +and the Allwinner platform, but should help any platform using the +fb layer. + +The special case functions allow constant folding, eliminating a number +of instructions including divide operations, and allow the use of an +unrolled loop, eliminating instructions with a variable shift size, +reducing source memory access instructions, and eliminating excessive +branching. These unrolled loops also allow much better code optimization +by the C compiler. The code that selects which optimized variant is used +is also simplified, eliminating integer divide instructions. + +The speed-up, measured by timing 'cat file.txt' in the console, varies +between 40% and 70%, when testing on the Raspberry Pi and Allwinner +ARM-based platforms, depending on font size and the pixel depth, with +the greater benefit for 32bpp. + +Signed-off-by: Harm Hanemaaijer +--- + drivers/video/fbdev/core/cfbimgblt.c | 152 +++++++++++++++++++++++++++++++++-- + 1 file changed, 147 insertions(+), 5 deletions(-) + +diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c +index a2bb276..436494f 100644 +--- a/drivers/video/fbdev/core/cfbimgblt.c ++++ b/drivers/video/fbdev/core/cfbimgblt.c +@@ -28,6 +28,11 @@ + * + * Also need to add code to deal with cards endians that are different than + * the native cpu endians. I also need to deal with MSB position in the word. ++ * Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013: ++ * - Provide optimized versions of fast_imageblit for 16 and 32bpp that are ++ * significantly faster than the previous implementation. ++ * - Simplify the fast/slow_imageblit selection code, avoiding integer ++ * divides. + */ + #include + #include +@@ -262,6 +267,133 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * + } + } + ++/* ++ * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded ++ * into the code, main loop unrolled. ++ */ ++ ++static inline void fast_imageblit16(const struct fb_image *image, ++ struct fb_info *p, u8 __iomem * dst1, ++ u32 fgcolor, u32 bgcolor) ++{ ++ u32 fgx = fgcolor, bgx = bgcolor; ++ u32 spitch = (image->width + 7) / 8; ++ u32 end_mask, eorx; ++ const char *s = image->data, *src; ++ u32 __iomem *dst; ++ const u32 *tab = NULL; ++ int i, j, k; ++ ++ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; ++ ++ fgx <<= 16; ++ bgx <<= 16; ++ fgx |= fgcolor; ++ bgx |= bgcolor; ++ ++ eorx = fgx ^ bgx; ++ k = image->width / 2; ++ ++ for (i = image->height; i--;) { ++ dst = (u32 __iomem *) dst1; ++ src = s; ++ ++ j = k; ++ while (j >= 4) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 6) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 4) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 2) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[bits & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ src++; ++ j -= 4; ++ } ++ if (j != 0) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 6) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ if (j >= 2) { ++ end_mask = tab[(bits >> 4) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ if (j == 3) { ++ end_mask = tab[(bits >> 2) & 3]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst); ++ } ++ } ++ } ++ dst1 += p->fix.line_length; ++ s += spitch; ++ } ++} ++ ++/* ++ * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded ++ * into the code, main loop unrolled. ++ */ ++ ++static inline void fast_imageblit32(const struct fb_image *image, ++ struct fb_info *p, u8 __iomem * dst1, ++ u32 fgcolor, u32 bgcolor) ++{ ++ u32 fgx = fgcolor, bgx = bgcolor; ++ u32 spitch = (image->width + 7) / 8; ++ u32 end_mask, eorx; ++ const char *s = image->data, *src; ++ u32 __iomem *dst; ++ const u32 *tab = NULL; ++ int i, j, k; ++ ++ tab = cfb_tab32; ++ ++ eorx = fgx ^ bgx; ++ k = image->width; ++ ++ for (i = image->height; i--;) { ++ dst = (u32 __iomem *) dst1; ++ src = s; ++ ++ j = k; ++ while (j >= 8) { ++ u8 bits = *src; ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 6) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 5) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 4) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 3) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 2) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[(bits >> 1) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ end_mask = tab[bits & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ src++; ++ j -= 8; ++ } ++ if (j != 0) { ++ u32 bits = (u32) * src; ++ while (j > 1) { ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst++); ++ bits <<= 1; ++ j--; ++ } ++ end_mask = tab[(bits >> 7) & 1]; ++ FB_WRITEL((end_mask & eorx) ^ bgx, dst); ++ } ++ dst1 += p->fix.line_length; ++ s += spitch; ++ } ++} ++ + void cfb_imageblit(struct fb_info *p, const struct fb_image *image) + { + u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; +@@ -294,11 +426,21 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) + bgcolor = image->bg_color; + } + +- if (32 % bpp == 0 && !start_index && !pitch_index && +- ((width & (32/bpp-1)) == 0) && +- bpp >= 8 && bpp <= 32) +- fast_imageblit(image, p, dst1, fgcolor, bgcolor); +- else ++ if (!start_index && !pitch_index) { ++ if (bpp == 32) ++ fast_imageblit32(image, p, dst1, fgcolor, ++ bgcolor); ++ else if (bpp == 16 && (width & 1) == 0) ++ fast_imageblit16(image, p, dst1, fgcolor, ++ bgcolor); ++ else if (bpp == 8 && (width & 3) == 0) ++ fast_imageblit(image, p, dst1, fgcolor, ++ bgcolor); ++ else ++ slow_imageblit(image, p, dst1, fgcolor, ++ bgcolor, ++ start_index, pitch_index); ++ } else + slow_imageblit(image, p, dst1, fgcolor, bgcolor, + start_index, pitch_index); + } else + +From b78abfc78e582f82fda5e69816eaa97b1097c853 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 26 Mar 2013 17:26:38 +0000 +Subject: [PATCH 31/77] Allow mac address to be set in smsc95xx + +Signed-off-by: popcornmix +--- + drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 26423ad..e29a323 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -59,6 +59,7 @@ + #define SUSPEND_SUSPEND3 (0x08) + #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ + SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) ++#define MAC_ADDR_LEN (6) + + struct smsc95xx_priv { + u32 mac_cr; +@@ -74,6 +75,10 @@ static bool turbo_mode = true; + module_param(turbo_mode, bool, 0644); + MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); + ++static char *macaddr = ":"; ++module_param(macaddr, charp, 0); ++MODULE_PARM_DESC(macaddr, "MAC address"); ++ + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + u32 *data, int in_pm) + { +@@ -763,8 +768,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); + } + ++/* Check the macaddr module parameter for a MAC address */ ++static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) ++{ ++ int i, j, got_num, num; ++ u8 mtbl[MAC_ADDR_LEN]; ++ ++ if (macaddr[0] == ':') ++ return 0; ++ ++ i = 0; ++ j = 0; ++ num = 0; ++ got_num = 0; ++ while (j < MAC_ADDR_LEN) { ++ if (macaddr[i] && macaddr[i] != ':') { ++ got_num++; ++ if ('0' <= macaddr[i] && macaddr[i] <= '9') ++ num = num * 16 + macaddr[i] - '0'; ++ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') ++ num = num * 16 + 10 + macaddr[i] - 'A'; ++ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') ++ num = num * 16 + 10 + macaddr[i] - 'a'; ++ else ++ break; ++ i++; ++ } else if (got_num == 2) { ++ mtbl[j++] = (u8) num; ++ num = 0; ++ got_num = 0; ++ i++; ++ } else { ++ break; ++ } ++ } ++ ++ if (j == MAC_ADDR_LEN) { ++ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " ++ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], ++ mtbl[3], mtbl[4], mtbl[5]); ++ for (i = 0; i < MAC_ADDR_LEN; i++) ++ dev_mac[i] = mtbl[i]; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ + static void smsc95xx_init_mac_address(struct usbnet *dev) + { ++ /* Check module parameters */ ++ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) ++ return; ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { + +From 468a5ebe451a5e3bc693fdbd67173f2fadb7d217 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 May 2013 11:46:50 +0100 +Subject: [PATCH 32/77] 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 +See: https://github.com/raspberrypi/linux/pull/457 + +Add bitbanging pullups, use them for w1-gpio + +Allows parasite power to work, uses module option pullup=1 + +bcm2708: Ensure 1-wire pullup is disabled by default, and expose as module parameter + +Signed-off-by: Alex J Lennon + +w1-gpio: Add gpiopin module parameter and correctly free up gpio pull-up pin, if set + +Signed-off-by: Alex J Lennon + +w1-gpio: Sort out the pullup/parasitic power tangle +--- + arch/arm/mach-bcm2708/bcm2708.c | 29 +++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 29 +++++++++++++++++ + drivers/w1/masters/w1-gpio.c | 69 +++++++++++++++++++++++++++++++++++++---- + drivers/w1/w1.h | 6 ++++ + drivers/w1/w1_int.c | 14 +++++++++ + drivers/w1/w1_io.c | 18 +++++++++-- + include/linux/w1-gpio.h | 1 + + 7 files changed, 157 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index efb3544..c7b4b61 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -77,12 +78,19 @@ + */ + #define DMA_MASK_BITS_COMMON 32 + ++// use GPIO 4 for the one-wire GPIO pin, if enabled ++#define W1_GPIO 4 ++// ensure one-wire GPIO pullup is disabled by default ++#define W1_PULLUP -1 ++ + /* command line parameters */ + static unsigned boardrev, serial; + static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static unsigned w1_gpio_pin = W1_GPIO; ++static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + + static unsigned use_dt = 0; +@@ -303,6 +311,20 @@ static struct platform_device bcm2708_dmaengine_device = { + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), + }; + ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++static struct w1_gpio_platform_data w1_gpio_pdata = { ++ .pin = W1_GPIO, ++ .ext_pullup_enable_pin = W1_PULLUP, ++ .is_open_drain = 0, ++}; ++ ++static struct platform_device w1_device = { ++ .name = "w1-gpio", ++ .id = -1, ++ .dev.platform_data = &w1_gpio_pdata, ++}; ++#endif ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -729,6 +751,11 @@ void __init bcm2708_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ w1_gpio_pdata.pin = w1_gpio_pin; ++ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; ++ bcm_register_device_dt(&w1_device); ++#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +@@ -942,5 +969,7 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(w1_gpio_pin, uint, 0644); ++module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 8017c50..03e208b 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -79,12 +80,19 @@ + */ + #define DMA_MASK_BITS_COMMON 32 + ++// use GPIO 4 for the one-wire GPIO pin, if enabled ++#define W1_GPIO 4 ++// ensure one-wire GPIO pullup is disabled by default ++#define W1_PULLUP -1 ++ + /* command line parameters */ + static unsigned boardrev, serial; + static unsigned uart_clock = UART0_CLOCK; + static unsigned disk_led_gpio = 16; + static unsigned disk_led_active_low = 1; + static unsigned reboot_part = 0; ++static unsigned w1_gpio_pin = W1_GPIO; ++static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + + static unsigned use_dt = 0; +@@ -313,6 +321,20 @@ static struct platform_device bcm2708_dmaengine_device = { + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), + }; + ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++static struct w1_gpio_platform_data w1_gpio_pdata = { ++ .pin = W1_GPIO, ++ .ext_pullup_enable_pin = W1_PULLUP, ++ .is_open_drain = 0, ++}; ++ ++static struct platform_device w1_device = { ++ .name = "w1-gpio", ++ .id = -1, ++ .dev.platform_data = &w1_gpio_pdata, ++}; ++#endif ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -749,6 +771,11 @@ void __init bcm2709_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ w1_gpio_pdata.pin = w1_gpio_pin; ++ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; ++ bcm_register_device_dt(&w1_device); ++#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +@@ -1110,5 +1137,7 @@ module_param(uart_clock, uint, 0644); + module_param(disk_led_gpio, uint, 0644); + module_param(disk_led_active_low, uint, 0644); + module_param(reboot_part, uint, 0644); ++module_param(w1_gpio_pin, uint, 0644); ++module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c +index 8f7848c6..2240f32 100644 +--- a/drivers/w1/masters/w1-gpio.c ++++ b/drivers/w1/masters/w1-gpio.c +@@ -23,6 +23,19 @@ + #include "../w1.h" + #include "../w1_int.h" + ++static int w1_gpio_pullup = 0; ++static int w1_gpio_pullup_orig = 0; ++module_param_named(pullup, w1_gpio_pullup, int, 0); ++MODULE_PARM_DESC(pullup, "Enable parasitic power (power on data) mode"); ++static int w1_gpio_pullup_pin = -1; ++static int w1_gpio_pullup_pin_orig = -1; ++module_param_named(extpullup, w1_gpio_pullup_pin, int, 0); ++MODULE_PARM_DESC(extpullup, "GPIO external pullup pin number"); ++static int w1_gpio_pin = -1; ++static int w1_gpio_pin_orig = -1; ++module_param_named(gpiopin, w1_gpio_pin, int, 0); ++MODULE_PARM_DESC(gpiopin, "GPIO pin number"); ++ + static u8 w1_gpio_set_pullup(void *data, int delay) + { + struct w1_gpio_platform_data *pdata = data; +@@ -67,6 +80,16 @@ static u8 w1_gpio_read_bit(void *data) + return gpio_get_value(pdata->pin) ? 1 : 0; + } + ++static void w1_gpio_bitbang_pullup(void *data, u8 on) ++{ ++ struct w1_gpio_platform_data *pdata = data; ++ ++ if (on) ++ gpio_direction_output(pdata->pin, 1); ++ else ++ gpio_direction_input(pdata->pin); ++} ++ + #if defined(CONFIG_OF) + static const struct of_device_id w1_gpio_dt_ids[] = { + { .compatible = "w1-gpio" }, +@@ -80,6 +103,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; + int gpio; ++ u32 value; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) +@@ -88,6 +112,9 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + if (of_get_property(np, "linux,open-drain", NULL)) + pdata->is_open_drain = 1; + ++ if (of_property_read_u32(np, "rpi,parasitic-power", &value) == 0) ++ pdata->parasitic_power = (value != 0); ++ + gpio = of_get_gpio(np, 0); + if (gpio < 0) { + if (gpio != -EPROBE_DEFER) +@@ -103,7 +130,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + if (gpio == -EPROBE_DEFER) + return gpio; + /* ignore other errors as the pullup gpio is optional */ +- pdata->ext_pullup_enable_pin = gpio; ++ pdata->ext_pullup_enable_pin = (gpio >= 0) ? gpio : -1; + + pdev->dev.platform_data = pdata; + +@@ -113,13 +140,15 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) + static int w1_gpio_probe(struct platform_device *pdev) + { + struct w1_bus_master *master; +- struct w1_gpio_platform_data *pdata; ++ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; + int err; + +- if (of_have_populated_dt()) { +- err = w1_gpio_probe_dt(pdev); +- if (err < 0) +- return err; ++ if(pdata == NULL) { ++ if (of_have_populated_dt()) { ++ err = w1_gpio_probe_dt(pdev); ++ if (err < 0) ++ return err; ++ } + } + + pdata = dev_get_platdata(&pdev->dev); +@@ -136,6 +165,22 @@ static int w1_gpio_probe(struct platform_device *pdev) + return -ENOMEM; + } + ++ w1_gpio_pin_orig = pdata->pin; ++ w1_gpio_pullup_pin_orig = pdata->ext_pullup_enable_pin; ++ w1_gpio_pullup_orig = pdata->parasitic_power; ++ ++ if(gpio_is_valid(w1_gpio_pin)) { ++ pdata->pin = w1_gpio_pin; ++ pdata->ext_pullup_enable_pin = -1; ++ pdata->parasitic_power = -1; ++ } ++ pdata->parasitic_power |= w1_gpio_pullup; ++ if(gpio_is_valid(w1_gpio_pullup_pin)) { ++ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin; ++ } ++ ++ dev_info(&pdev->dev, "gpio pin %d, external pullup pin %d, parasitic power %d\n", pdata->pin, pdata->ext_pullup_enable_pin, pdata->parasitic_power); ++ + err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); + if (err) { + dev_err(&pdev->dev, "gpio_request (pin) failed\n"); +@@ -165,6 +210,14 @@ static int w1_gpio_probe(struct platform_device *pdev) + master->set_pullup = w1_gpio_set_pullup; + } + ++ if (pdata->parasitic_power) { ++ if (pdata->is_open_drain) ++ printk(KERN_ERR "w1-gpio 'pullup'(parasitic power) " ++ "option doesn't work with open drain GPIO\n"); ++ else ++ master->bitbang_pullup = w1_gpio_bitbang_pullup; ++ } ++ + err = w1_add_master_device(master); + if (err) { + dev_err(&pdev->dev, "w1_add_master device failed\n"); +@@ -195,6 +248,10 @@ static int w1_gpio_remove(struct platform_device *pdev) + + w1_remove_master_device(master); + ++ pdata->pin = w1_gpio_pin_orig; ++ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin_orig; ++ pdata->parasitic_power = w1_gpio_pullup_orig; ++ + return 0; + } + +diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h +index 56a49ba..881d728 100644 +--- a/drivers/w1/w1.h ++++ b/drivers/w1/w1.h +@@ -171,6 +171,12 @@ struct w1_bus_master + + u8 (*set_pullup)(void *, int); + ++ /** ++ * Turns the pullup on/off in bitbanging mode, takes an on/off argument. ++ * @return -1=Error, 0=completed ++ */ ++ void (*bitbang_pullup) (void *, u8); ++ + void (*search)(void *, struct w1_master *, + u8, w1_slave_found_callback); + }; +diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c +index 47249a3..a4b4a8d 100644 +--- a/drivers/w1/w1_int.c ++++ b/drivers/w1/w1_int.c +@@ -123,6 +123,20 @@ int w1_add_master_device(struct w1_bus_master *master) + return(-EINVAL); + } + ++ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup ++ * and takes care of timing itself */ ++ if (!master->write_byte && !master->touch_bit && master->set_pullup) { ++ printk(KERN_ERR "w1_add_master_device: set_pullup requires " ++ "write_byte or touch_bit, disabling\n"); ++ master->set_pullup = NULL; ++ } ++ ++ if (master->set_pullup && master->bitbang_pullup) { ++ printk(KERN_ERR "w1_add_master_device: set_pullup should not " ++ "be set when bitbang_pullup is used, disabling\n"); ++ master->set_pullup = NULL; ++ } ++ + /* Lock until the device is added (or not) to w1_masters. */ + mutex_lock(&w1_mlock); + /* Search for the first available id (starting at 1). */ +diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c +index 2820924..fd0550f 100644 +--- a/drivers/w1/w1_io.c ++++ b/drivers/w1/w1_io.c +@@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) + static void w1_post_write(struct w1_master *dev) + { + if (dev->pullup_duration) { +- if (dev->enable_pullup && dev->bus_master->set_pullup) +- dev->bus_master->set_pullup(dev->bus_master->data, 0); +- else ++ if (dev->enable_pullup) { ++ if (dev->bus_master->set_pullup) { ++ dev->bus_master->set_pullup(dev-> ++ bus_master->data, ++ 0); ++ } else if (dev->bus_master->bitbang_pullup) { ++ dev->bus_master-> ++ bitbang_pullup(dev->bus_master->data, 1); ++ msleep(dev->pullup_duration); ++ dev->bus_master-> ++ bitbang_pullup(dev->bus_master->data, 0); ++ } ++ } else { + msleep(dev->pullup_duration); ++ } ++ + dev->pullup_duration = 0; + } + } +diff --git a/include/linux/w1-gpio.h b/include/linux/w1-gpio.h +index d58594a..feae942 100644 +--- a/include/linux/w1-gpio.h ++++ b/include/linux/w1-gpio.h +@@ -18,6 +18,7 @@ + struct w1_gpio_platform_data { + unsigned int pin; + unsigned int is_open_drain:1; ++ unsigned int parasitic_power:1; + void (*enable_external_pullup)(int enable); + unsigned int ext_pullup_enable_pin; + unsigned int pullup_duration; + +From 00d8013737c9e736f70e04e07b761517559e495e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 18 Dec 2013 22:16:19 +0000 +Subject: [PATCH 34/77] config: Enable CONFIG_MEMCG, but leave it disabled (due + to memory cost). Enable with cgroup_enable=memory. + +--- + kernel/cgroup.c | 23 +++++++++++++++++++++++ + mm/memcontrol.c | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 469dd54..c9684da 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -5395,6 +5395,29 @@ static int __init cgroup_disable(char *str) + } + __setup("cgroup_disable=", cgroup_disable); + ++static int __init cgroup_enable(char *str) ++{ ++ struct cgroup_subsys *ss; ++ char *token; ++ int i; ++ ++ while ((token = strsep(&str, ",")) != NULL) { ++ if (!*token) ++ continue; ++ ++ for_each_subsys(ss, i) { ++ if (!strcmp(token, ss->name)) { ++ ss->disabled = 0; ++ printk(KERN_INFO "Enabling %s control group" ++ " subsystem\n", ss->name); ++ break; ++ } ++ } ++ } ++ return 1; ++} ++__setup("cgroup_enable=", cgroup_enable); ++ + static int __init cgroup_set_legacy_files_on_dfl(char *str) + { + printk("cgroup: using legacy files on the default hierarchy\n"); +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index a04225d..a2ef8af 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5388,6 +5388,7 @@ struct cgroup_subsys memory_cgrp_subsys = { + .dfl_cftypes = memory_files, + .legacy_cftypes = mem_cgroup_legacy_files, + .early_init = 0, ++ .disabled = 1, + }; + + /** + +From 5e192d7296061c5d70da39b3fbd1eeedef467923 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:33:38 +0100 +Subject: [PATCH 35/77] ASoC: Add support for BCM2708 + +This driver adds support for digital audio (I2S) +for the BCM2708 SoC that is used by the +Raspberry Pi. External audio codecs can be +connected to the Raspberry Pi via P5 header. + +It relies on cyclic DMA engine support for BCM2708. + +Signed-off-by: Florian Meier + +ASoC: BCM2708: Add 24 bit support + +This adds 24 bit support to the I2S driver of the BCM2708. +Besides enabling the 24 bit flags, it includes two bug fixes: + +MMAP is not supported. Claiming this leads to strange issues +when the format of driver and file do not match. + +The datasheet states that the width extension bit should be set +for widths greater than 24, but greater or equal would be correct. +This follows from the definition of the width field. + +Signed-off-by: Florian Meier + +bcm2708-i2s: Update bclk_ratio to more correct values + +Move GPIO setup to hw_params. + +This is used to stop the I2S driver from breaking +the GPIO setup for other uses of the PCM interface + +Configure GPIOs for I2S based on revision/card settings + +With RPi model B+, assignment of the I2S GPIO pins has changed. +This patch uses the board revision to auto-detect the GPIOs used +for I2S. It also allows sound card drivers to set the GPIOs that +should be used. This is especially important with the Compute +Module. + +bcm2708-i2s: Avoid leak from iomap when accessing gpio + +bcm2708: Eliminate i2s debugfs directory error + +Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') +to avoid the name clash when registering debugfs entries. +--- + sound/soc/bcm/Kconfig | 11 + + sound/soc/bcm/Makefile | 4 + + sound/soc/bcm/bcm2708-i2s.c | 1009 +++++++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/bcm2708-i2s.h | 35 ++ + 4 files changed, 1059 insertions(+) + create mode 100644 sound/soc/bcm/bcm2708-i2s.c + create mode 100644 sound/soc/bcm/bcm2708-i2s.h + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 6a834e1..8642296 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -7,3 +7,14 @@ config SND_BCM2835_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2835 I2S interface. You will also need + to select the audio interfaces to support below. ++ ++config SND_BCM2708_SOC_I2S ++ tristate "SoC Audio support for the Broadcom BCM2708 I2S module" ++ depends on MACH_BCM2708 || MACH_BCM2709 ++ select REGMAP_MMIO ++ select SND_SOC_DMAENGINE_PCM ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ help ++ Say Y or M if you want to add support for codecs attached to ++ the BCM2708 I2S interface. You will also need ++ to select the audio interfaces to support below. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index bc816b7..f8bbe1f 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o + + obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + ++# BCM2708 Platform Support ++snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o ++ ++obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o +diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c +new file mode 100644 +index 0000000..a3b65dc +--- /dev/null ++++ b/sound/soc/bcm/bcm2708-i2s.c +@@ -0,0 +1,1009 @@ ++/* ++ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * Based on ++ * Raspberry Pi PCM I2S ALSA Driver ++ * Copyright (c) by Phil Poole 2013 ++ * ++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor ++ * Vladimir Barinov, ++ * Copyright (C) 2007 MontaVista Software, Inc., ++ * ++ * OMAP ALSA SoC DAI driver using McBSP port ++ * Copyright (C) 2008 Nokia Corporation ++ * Contact: Jarkko Nikula ++ * Peter Ujfalusi ++ * ++ * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver ++ * Author: Timur Tabi ++ * Copyright 2007-2010 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include "bcm2708-i2s.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* Clock registers */ ++#define BCM2708_CLK_PCMCTL_REG 0x00 ++#define BCM2708_CLK_PCMDIV_REG 0x04 ++ ++/* Clock register settings */ ++#define BCM2708_CLK_PASSWD (0x5a000000) ++#define BCM2708_CLK_PASSWD_MASK (0xff000000) ++#define BCM2708_CLK_MASH(v) ((v) << 9) ++#define BCM2708_CLK_FLIP BIT(8) ++#define BCM2708_CLK_BUSY BIT(7) ++#define BCM2708_CLK_KILL BIT(5) ++#define BCM2708_CLK_ENAB BIT(4) ++#define BCM2708_CLK_SRC(v) (v) ++ ++#define BCM2708_CLK_SHIFT (12) ++#define BCM2708_CLK_DIVI(v) ((v) << BCM2708_CLK_SHIFT) ++#define BCM2708_CLK_DIVF(v) (v) ++#define BCM2708_CLK_DIVF_MASK (0xFFF) ++ ++enum { ++ BCM2708_CLK_MASH_0 = 0, ++ BCM2708_CLK_MASH_1, ++ BCM2708_CLK_MASH_2, ++ BCM2708_CLK_MASH_3, ++}; ++ ++enum { ++ BCM2708_CLK_SRC_GND = 0, ++ BCM2708_CLK_SRC_OSC, ++ BCM2708_CLK_SRC_DBG0, ++ BCM2708_CLK_SRC_DBG1, ++ BCM2708_CLK_SRC_PLLA, ++ BCM2708_CLK_SRC_PLLC, ++ BCM2708_CLK_SRC_PLLD, ++ BCM2708_CLK_SRC_HDMI, ++}; ++ ++/* Most clocks are not useable (freq = 0) */ ++static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = { ++ [BCM2708_CLK_SRC_GND] = 0, ++ [BCM2708_CLK_SRC_OSC] = 19200000, ++ [BCM2708_CLK_SRC_DBG0] = 0, ++ [BCM2708_CLK_SRC_DBG1] = 0, ++ [BCM2708_CLK_SRC_PLLA] = 0, ++ [BCM2708_CLK_SRC_PLLC] = 0, ++ [BCM2708_CLK_SRC_PLLD] = 500000000, ++ [BCM2708_CLK_SRC_HDMI] = 0, ++}; ++ ++/* I2S registers */ ++#define BCM2708_I2S_CS_A_REG 0x00 ++#define BCM2708_I2S_FIFO_A_REG 0x04 ++#define BCM2708_I2S_MODE_A_REG 0x08 ++#define BCM2708_I2S_RXC_A_REG 0x0c ++#define BCM2708_I2S_TXC_A_REG 0x10 ++#define BCM2708_I2S_DREQ_A_REG 0x14 ++#define BCM2708_I2S_INTEN_A_REG 0x18 ++#define BCM2708_I2S_INTSTC_A_REG 0x1c ++#define BCM2708_I2S_GRAY_REG 0x20 ++ ++/* I2S register settings */ ++#define BCM2708_I2S_STBY BIT(25) ++#define BCM2708_I2S_SYNC BIT(24) ++#define BCM2708_I2S_RXSEX BIT(23) ++#define BCM2708_I2S_RXF BIT(22) ++#define BCM2708_I2S_TXE BIT(21) ++#define BCM2708_I2S_RXD BIT(20) ++#define BCM2708_I2S_TXD BIT(19) ++#define BCM2708_I2S_RXR BIT(18) ++#define BCM2708_I2S_TXW BIT(17) ++#define BCM2708_I2S_CS_RXERR BIT(16) ++#define BCM2708_I2S_CS_TXERR BIT(15) ++#define BCM2708_I2S_RXSYNC BIT(14) ++#define BCM2708_I2S_TXSYNC BIT(13) ++#define BCM2708_I2S_DMAEN BIT(9) ++#define BCM2708_I2S_RXTHR(v) ((v) << 7) ++#define BCM2708_I2S_TXTHR(v) ((v) << 5) ++#define BCM2708_I2S_RXCLR BIT(4) ++#define BCM2708_I2S_TXCLR BIT(3) ++#define BCM2708_I2S_TXON BIT(2) ++#define BCM2708_I2S_RXON BIT(1) ++#define BCM2708_I2S_EN (1) ++ ++#define BCM2708_I2S_CLKDIS BIT(28) ++#define BCM2708_I2S_PDMN BIT(27) ++#define BCM2708_I2S_PDME BIT(26) ++#define BCM2708_I2S_FRXP BIT(25) ++#define BCM2708_I2S_FTXP BIT(24) ++#define BCM2708_I2S_CLKM BIT(23) ++#define BCM2708_I2S_CLKI BIT(22) ++#define BCM2708_I2S_FSM BIT(21) ++#define BCM2708_I2S_FSI BIT(20) ++#define BCM2708_I2S_FLEN(v) ((v) << 10) ++#define BCM2708_I2S_FSLEN(v) (v) ++ ++#define BCM2708_I2S_CHWEX BIT(15) ++#define BCM2708_I2S_CHEN BIT(14) ++#define BCM2708_I2S_CHPOS(v) ((v) << 4) ++#define BCM2708_I2S_CHWID(v) (v) ++#define BCM2708_I2S_CH1(v) ((v) << 16) ++#define BCM2708_I2S_CH2(v) (v) ++ ++#define BCM2708_I2S_TX_PANIC(v) ((v) << 24) ++#define BCM2708_I2S_RX_PANIC(v) ((v) << 16) ++#define BCM2708_I2S_TX(v) ((v) << 8) ++#define BCM2708_I2S_RX(v) (v) ++ ++#define BCM2708_I2S_INT_RXERR BIT(3) ++#define BCM2708_I2S_INT_TXERR BIT(2) ++#define BCM2708_I2S_INT_RXR BIT(1) ++#define BCM2708_I2S_INT_TXW BIT(0) ++ ++/* I2S DMA interface */ ++#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004 ++#define BCM2708_DMA_DREQ_PCM_TX 2 ++#define BCM2708_DMA_DREQ_PCM_RX 3 ++ ++/* I2S pin configuration */ ++static int bcm2708_i2s_gpio=BCM2708_I2S_GPIO_AUTO; ++ ++/* General device struct */ ++struct bcm2708_i2s_dev { ++ struct device *dev; ++ struct snd_dmaengine_dai_dma_data dma_data[2]; ++ unsigned int fmt; ++ unsigned int bclk_ratio; ++ ++ struct regmap *i2s_regmap; ++ struct regmap *clk_regmap; ++}; ++ ++void bcm2708_i2s_set_gpio(int gpio) { ++ bcm2708_i2s_gpio=gpio; ++} ++EXPORT_SYMBOL(bcm2708_i2s_set_gpio); ++ ++ ++static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev) ++{ ++ /* Start the clock if in master mode */ ++ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; ++ ++ switch (master) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void bcm2708_i2s_stop_clock(struct bcm2708_i2s_dev *dev) ++{ ++ uint32_t clkreg; ++ int timeout = 1000; ++ ++ /* Stop clock */ ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD); ++ ++ /* Wait for the BUSY flag going down */ ++ while (--timeout) { ++ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); ++ if (!(clkreg & BCM2708_CLK_BUSY)) ++ break; ++ } ++ ++ if (!timeout) { ++ /* KILL the clock */ ++ dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD_MASK, ++ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD); ++ } ++} ++ ++static void bcm2708_i2s_clear_fifos(struct bcm2708_i2s_dev *dev, ++ bool tx, bool rx) ++{ ++ int timeout = 1000; ++ uint32_t syncval; ++ uint32_t csreg; ++ uint32_t i2s_active_state; ++ uint32_t clkreg; ++ uint32_t clk_active_state; ++ uint32_t off; ++ uint32_t clr; ++ ++ off = tx ? BCM2708_I2S_TXON : 0; ++ off |= rx ? BCM2708_I2S_RXON : 0; ++ ++ clr = tx ? BCM2708_I2S_TXCLR : 0; ++ clr |= rx ? BCM2708_I2S_RXCLR : 0; ++ ++ /* Backup the current state */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ i2s_active_state = csreg & (BCM2708_I2S_RXON | BCM2708_I2S_TXON); ++ ++ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); ++ clk_active_state = clkreg & BCM2708_CLK_ENAB; ++ ++ /* Start clock if not running */ ++ if (!clk_active_state) { ++ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, ++ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, ++ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); ++ } ++ ++ /* Stop I2S module */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, off, 0); ++ ++ /* ++ * Clear the FIFOs ++ * Requires at least 2 PCM clock cycles to take effect ++ */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, clr, clr); ++ ++ /* Wait for 2 PCM clock cycles */ ++ ++ /* ++ * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back ++ * FIXME: This does not seem to work for slave mode! ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &syncval); ++ syncval &= BCM2708_I2S_SYNC; ++ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_SYNC, ~syncval); ++ ++ /* Wait for the SYNC flag changing it's state */ ++ while (--timeout) { ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ if ((csreg & BCM2708_I2S_SYNC) != syncval) ++ break; ++ } ++ ++ if (!timeout) ++ dev_err(dev->dev, "I2S SYNC error!\n"); ++ ++ /* Stop clock if it was not running before */ ++ if (!clk_active_state) ++ bcm2708_i2s_stop_clock(dev); ++ ++ /* Restore I2S state */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_RXON | BCM2708_I2S_TXON, i2s_active_state); ++} ++ ++static int bcm2708_i2s_set_dai_fmt(struct snd_soc_dai *dai, ++ unsigned int fmt) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ dev->fmt = fmt; ++ return 0; ++} ++ ++static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, ++ unsigned int ratio) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ dev->bclk_ratio = ratio; ++ return 0; ++} ++ ++ ++static int bcm2708_i2s_set_function(unsigned offset, int function) ++{ ++ #define GPIOFSEL(x) (0x00+(x)*4) ++ void __iomem *gpio = __io_address(GPIO_BASE); ++ unsigned alt = function <= 3 ? function + 4: function == 4 ? 3 : 2; ++ unsigned gpiodir; ++ unsigned gpio_bank = offset / 10; ++ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; ++ ++ if (offset >= BCM2708_NR_GPIOS) ++ return -EINVAL; ++ ++ gpiodir = readl(gpio + GPIOFSEL(gpio_bank)); ++ gpiodir &= ~(7 << gpio_field_offset); ++ gpiodir |= alt << gpio_field_offset; ++ writel(gpiodir, gpio + GPIOFSEL(gpio_bank)); ++ return 0; ++} ++ ++static void bcm2708_i2s_setup_gpio(void) ++{ ++ /* ++ * This is the common way to handle the GPIO pins for ++ * the Raspberry Pi. ++ * TODO Better way would be to handle ++ * this in the device tree! ++ */ ++ int pin,pinconfig,startpin,alt; ++ ++ /* SPI is on different GPIOs on different boards */ ++ /* for Raspberry Pi B+, this is pin GPIO18-21, for original on 28-31 */ ++ if (bcm2708_i2s_gpio==BCM2708_I2S_GPIO_AUTO) { ++ if ((system_rev & 0xffffff) >= 0x10) { ++ /* Model B+ */ ++ pinconfig=BCM2708_I2S_GPIO_PIN18; ++ } else { ++ /* original */ ++ pinconfig=BCM2708_I2S_GPIO_PIN28; ++ } ++ } else { ++ pinconfig=bcm2708_i2s_gpio; ++ } ++ ++ if (pinconfig==BCM2708_I2S_GPIO_PIN18) { ++ startpin=18; ++ alt=BCM2708_I2S_GPIO_PIN18_ALT; ++ } else if (pinconfig==BCM2708_I2S_GPIO_PIN28) { ++ startpin=28; ++ alt=BCM2708_I2S_GPIO_PIN28_ALT; ++ } else { ++ printk(KERN_INFO "Can't configure I2S GPIOs, unknown pin mode for I2S: %i\n",pinconfig); ++ return; ++ } ++ ++ /* configure I2S pins to correct ALT mode */ ++ for (pin = startpin; pin <= startpin+3; pin++) { ++ bcm2708_i2s_set_function(pin, alt); ++ } ++} ++ ++static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ unsigned int sampling_rate = params_rate(params); ++ unsigned int data_length, data_delay, bclk_ratio; ++ unsigned int ch1pos, ch2pos, mode, format; ++ unsigned int mash = BCM2708_CLK_MASH_1; ++ unsigned int divi, divf, target_frequency; ++ int clk_src = -1; ++ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; ++ bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS ++ || master == SND_SOC_DAIFMT_CBS_CFM); ++ ++ bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS ++ || master == SND_SOC_DAIFMT_CBM_CFS); ++ uint32_t csreg; ++ ++ /* ++ * If a stream is already enabled, ++ * the registers are already set properly. ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); ++ ++ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON)) ++ return 0; ++ ++ ++ bcm2708_i2s_setup_gpio(); ++ ++ /* ++ * Adjust the data length according to the format. ++ * We prefill the half frame length with an integer ++ * divider of 2400 as explained at the clock settings. ++ * Maybe it is overwritten there, if the Integer mode ++ * does not apply. ++ */ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ data_length = 16; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ data_length = 24; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ data_length = 32; ++ bclk_ratio = 100; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* If bclk_ratio already set, use that one. */ ++ if (dev->bclk_ratio) ++ bclk_ratio = dev->bclk_ratio; ++ ++ /* ++ * Clock Settings ++ * ++ * The target frequency of the bit clock is ++ * sampling rate * frame length ++ * ++ * Integer mode: ++ * Sampling rates that are multiples of 8000 kHz ++ * can be driven by the oscillator of 19.2 MHz ++ * with an integer divider as long as the frame length ++ * is an integer divider of 19200000/8000=2400 as set up above. ++ * This is no longer possible if the sampling rate ++ * is too high (e.g. 192 kHz), because the oscillator is too slow. ++ * ++ * MASH mode: ++ * For all other sampling rates, it is not possible to ++ * have an integer divider. Approximate the clock ++ * with the MASH module that induces a slight frequency ++ * variance. To minimize that it is best to have the fastest ++ * clock here. That is PLLD with 500 MHz. ++ */ ++ target_frequency = sampling_rate * bclk_ratio; ++ clk_src = BCM2708_CLK_SRC_OSC; ++ mash = BCM2708_CLK_MASH_0; ++ ++ if (bcm2708_clk_freq[clk_src] % target_frequency == 0 ++ && bit_master && frame_master) { ++ divi = bcm2708_clk_freq[clk_src] / target_frequency; ++ divf = 0; ++ } else { ++ uint64_t dividend; ++ ++ if (!dev->bclk_ratio) { ++ /* ++ * Overwrite bclk_ratio, because the ++ * above trick is not needed or can ++ * not be used. ++ */ ++ bclk_ratio = 2 * data_length; ++ } ++ ++ target_frequency = sampling_rate * bclk_ratio; ++ ++ clk_src = BCM2708_CLK_SRC_PLLD; ++ mash = BCM2708_CLK_MASH_1; ++ ++ dividend = bcm2708_clk_freq[clk_src]; ++ dividend <<= BCM2708_CLK_SHIFT; ++ do_div(dividend, target_frequency); ++ divi = dividend >> BCM2708_CLK_SHIFT; ++ divf = dividend & BCM2708_CLK_DIVF_MASK; ++ } ++ ++ /* Clock should only be set up here if CPU is clock master */ ++ if (((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFS) || ++ ((dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBS_CFM)) { ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMDIV_REG, BCM2708_CLK_PASSWD ++ | BCM2708_CLK_DIVI(divi) ++ | BCM2708_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, BCM2708_CLK_PASSWD ++ | BCM2708_CLK_MASH(mash) ++ | BCM2708_CLK_SRC(clk_src)); ++ } ++ ++ /* Setup the frame format */ ++ format = BCM2708_I2S_CHEN; ++ ++ if (data_length >= 24) ++ format |= BCM2708_I2S_CHWEX; ++ ++ format |= BCM2708_I2S_CHWID((data_length-8)&0xf); ++ ++ switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ data_delay = 1; ++ break; ++ default: ++ /* ++ * TODO ++ * Others are possible but are not implemented at the moment. ++ */ ++ dev_err(dev->dev, "%s:bad format\n", __func__); ++ return -EINVAL; ++ } ++ ++ ch1pos = data_delay; ++ ch2pos = bclk_ratio / 2 + data_delay; ++ ++ switch (params_channels(params)) { ++ case 2: ++ format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format); ++ format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos)); ++ format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * Set format for both streams. ++ * We cannot set another frame length ++ * (and therefore word length) anyway, ++ * so the format will be the same. ++ */ ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_RXC_A_REG, format); ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_TXC_A_REG, format); ++ ++ /* Setup the I2S mode */ ++ mode = 0; ++ ++ if (data_length <= 16) { ++ /* ++ * Use frame packed mode (2 channels per 32 bit word) ++ * We cannot set another frame length in the second stream ++ * (and therefore word length) anyway, ++ * so the format will be the same. ++ */ ++ mode |= BCM2708_I2S_FTXP | BCM2708_I2S_FRXP; ++ } ++ ++ mode |= BCM2708_I2S_FLEN(bclk_ratio - 1); ++ mode |= BCM2708_I2S_FSLEN(bclk_ratio / 2); ++ ++ /* Master or slave? */ ++ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ /* CPU is master */ ++ break; ++ case SND_SOC_DAIFMT_CBM_CFS: ++ /* ++ * CODEC is bit clock master ++ * CPU is frame master ++ */ ++ mode |= BCM2708_I2S_CLKM; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFM: ++ /* ++ * CODEC is frame master ++ * CPU is bit clock master ++ */ ++ mode |= BCM2708_I2S_FSM; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ /* CODEC is master */ ++ mode |= BCM2708_I2S_CLKM; ++ mode |= BCM2708_I2S_FSM; ++ break; ++ default: ++ dev_err(dev->dev, "%s:bad master\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* ++ * Invert clocks? ++ * ++ * The BCM approach seems to be inverted to the classical I2S approach. ++ */ ++ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ /* None. Therefore, both for BCM */ ++ mode |= BCM2708_I2S_CLKI; ++ mode |= BCM2708_I2S_FSI; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ /* Both. Therefore, none for BCM */ ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ /* ++ * Invert only frame sync. Therefore, ++ * invert only bit clock for BCM ++ */ ++ mode |= BCM2708_I2S_CLKI; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ /* ++ * Invert only bit clock. Therefore, ++ * invert only frame sync for BCM ++ */ ++ mode |= BCM2708_I2S_FSI; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_write(dev->i2s_regmap, BCM2708_I2S_MODE_A_REG, mode); ++ ++ /* Setup the DMA parameters */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_RXTHR(1) ++ | BCM2708_I2S_TXTHR(1) ++ | BCM2708_I2S_DMAEN, 0xffffffff); ++ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_DREQ_A_REG, ++ BCM2708_I2S_TX_PANIC(0x10) ++ | BCM2708_I2S_RX_PANIC(0x30) ++ | BCM2708_I2S_TX(0x30) ++ | BCM2708_I2S_RX(0x20), 0xffffffff); ++ ++ /* Clear FIFOs */ ++ bcm2708_i2s_clear_fifos(dev, true, true); ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ uint32_t cs_reg; ++ ++ bcm2708_i2s_start_clock(dev); ++ ++ /* ++ * Clear both FIFOs if the one that should be started ++ * is not empty at the moment. This should only happen ++ * after overrun. Otherwise, hw_params would have cleared ++ * the FIFO. ++ */ ++ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &cs_reg); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ++ && !(cs_reg & BCM2708_I2S_TXE)) ++ bcm2708_i2s_clear_fifos(dev, true, false); ++ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE ++ && (cs_reg & BCM2708_I2S_RXD)) ++ bcm2708_i2s_clear_fifos(dev, false, true); ++ ++ return 0; ++} ++ ++static void bcm2708_i2s_stop(struct bcm2708_i2s_dev *dev, ++ struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ uint32_t mask; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ mask = BCM2708_I2S_RXON; ++ else ++ mask = BCM2708_I2S_TXON; ++ ++ regmap_update_bits(dev->i2s_regmap, ++ BCM2708_I2S_CS_A_REG, mask, 0); ++ ++ /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ ++ if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) ++ bcm2708_i2s_stop_clock(dev); ++} ++ ++static int bcm2708_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ uint32_t mask; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ bcm2708_i2s_start_clock(dev); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ mask = BCM2708_I2S_RXON; ++ else ++ mask = BCM2708_I2S_TXON; ++ ++ regmap_update_bits(dev->i2s_regmap, ++ BCM2708_I2S_CS_A_REG, mask, mask); ++ break; ++ ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ bcm2708_i2s_stop(dev, substream, dai); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ if (dai->active) ++ return 0; ++ ++ /* Should this still be running stop it */ ++ bcm2708_i2s_stop_clock(dev); ++ ++ /* Enable PCM block */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_EN, BCM2708_I2S_EN); ++ ++ /* ++ * Disable STBY. ++ * Requires at least 4 PCM clock cycles to take effect. ++ */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_STBY, BCM2708_I2S_STBY); ++ ++ return 0; ++} ++ ++static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ bcm2708_i2s_stop(dev, substream, dai); ++ ++ /* If both streams are stopped, disable module and clock */ ++ if (dai->active) ++ return; ++ ++ /* Disable the module */ ++ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, ++ BCM2708_I2S_EN, 0); ++ ++ /* ++ * Stopping clock is necessary, because stop does ++ * not stop the clock when SND_SOC_DAIFMT_CONT ++ */ ++ bcm2708_i2s_stop_clock(dev); ++} ++ ++static const struct snd_soc_dai_ops bcm2708_i2s_dai_ops = { ++ .startup = bcm2708_i2s_startup, ++ .shutdown = bcm2708_i2s_shutdown, ++ .prepare = bcm2708_i2s_prepare, ++ .trigger = bcm2708_i2s_trigger, ++ .hw_params = bcm2708_i2s_hw_params, ++ .set_fmt = bcm2708_i2s_set_dai_fmt, ++ .set_bclk_ratio = bcm2708_i2s_set_dai_bclk_ratio ++}; ++ ++static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; ++ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; ++ ++ return 0; ++} ++ ++static struct snd_soc_dai_driver bcm2708_i2s_dai = { ++ .name = "bcm2708-i2s", ++ .probe = bcm2708_i2s_dai_probe, ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE ++ | SNDRV_PCM_FMTBIT_S24_LE ++ | SNDRV_PCM_FMTBIT_S32_LE ++ }, ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE ++ | SNDRV_PCM_FMTBIT_S24_LE ++ | SNDRV_PCM_FMTBIT_S32_LE ++ }, ++ .ops = &bcm2708_i2s_dai_ops, ++ .symmetric_rates = 1 ++}; ++ ++static bool bcm2708_i2s_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_I2S_CS_A_REG: ++ case BCM2708_I2S_FIFO_A_REG: ++ case BCM2708_I2S_INTSTC_A_REG: ++ case BCM2708_I2S_GRAY_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static bool bcm2708_i2s_precious_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_I2S_FIFO_A_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static bool bcm2708_clk_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2708_CLK_PCMCTL_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static const struct regmap_config bcm2708_regmap_config[] = { ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2708_I2S_GRAY_REG, ++ .precious_reg = bcm2708_i2s_precious_reg, ++ .volatile_reg = bcm2708_i2s_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ .name = "i2s", ++ }, ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2708_CLK_PCMDIV_REG, ++ .volatile_reg = bcm2708_clk_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ .name = "clk", ++ }, ++}; ++ ++static const struct snd_soc_component_driver bcm2708_i2s_component = { ++ .name = "bcm2708-i2s-comp", ++}; ++ ++static const struct snd_pcm_hardware bcm2708_pcm_hardware = { ++ .info = SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_JOINT_DUPLEX, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ .period_bytes_min = 32, ++ .period_bytes_max = 64 * PAGE_SIZE, ++ .periods_min = 2, ++ .periods_max = 255, ++ .buffer_bytes_max = 128 * PAGE_SIZE, ++}; ++ ++static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &bcm2708_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ ++ ++static int bcm2708_i2s_probe(struct platform_device *pdev) ++{ ++ struct bcm2708_i2s_dev *dev; ++ int i; ++ int ret; ++ struct regmap *regmap[2]; ++ struct resource *mem[2]; ++ ++ /* Request both ioareas */ ++ for (i = 0; i <= 1; i++) { ++ void __iomem *base; ++ ++ mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); ++ base = devm_ioremap_resource(&pdev->dev, mem[i]); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, ++ &bcm2708_regmap_config[i]); ++ if (IS_ERR(regmap[i])) { ++ dev_err(&pdev->dev, "I2S probe: regmap init failed\n"); ++ return PTR_ERR(regmap[i]); ++ } ++ } ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), ++ GFP_KERNEL); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ dev->i2s_regmap = regmap[0]; ++ dev->clk_regmap = regmap[1]; ++ ++ /* Set the DMA address */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = ++ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; ++ ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = ++ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; ++ ++ /* Set the DREQ */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id = ++ BCM2708_DMA_DREQ_PCM_TX; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id = ++ BCM2708_DMA_DREQ_PCM_RX; ++ ++ /* Set the bus width */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = ++ DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = ++ DMA_SLAVE_BUSWIDTH_4_BYTES; ++ ++ /* Set burst */ ++ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; ++ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; ++ ++ /* BCLK ratio - use default */ ++ dev->bclk_ratio = 0; ++ ++ /* Store the pdev */ ++ dev->dev = &pdev->dev; ++ dev_set_drvdata(&pdev->dev, dev); ++ ++ ret = snd_soc_register_component(&pdev->dev, ++ &bcm2708_i2s_component, &bcm2708_i2s_dai, 1); ++ ++ if (ret) { ++ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); ++ ret = -ENOMEM; ++ return ret; ++ } ++ ++ ret = snd_dmaengine_pcm_register(&pdev->dev, ++ &bcm2708_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ if (ret) { ++ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); ++ snd_soc_unregister_component(&pdev->dev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bcm2708_i2s_remove(struct platform_device *pdev) ++{ ++ snd_dmaengine_pcm_unregister(&pdev->dev); ++ snd_soc_unregister_component(&pdev->dev); ++ return 0; ++} ++ ++static const struct of_device_id bcm2708_i2s_of_match[] = { ++ { .compatible = "brcm,bcm2708-i2s", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2708_i2s_of_match); ++ ++static struct platform_driver bcm2708_i2s_driver = { ++ .probe = bcm2708_i2s_probe, ++ .remove = bcm2708_i2s_remove, ++ .driver = { ++ .name = "bcm2708-i2s", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm2708_i2s_of_match, ++ }, ++}; ++ ++module_platform_driver(bcm2708_i2s_driver); ++ ++MODULE_ALIAS("platform:bcm2708-i2s"); ++MODULE_DESCRIPTION("BCM2708 I2S interface"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/bcm/bcm2708-i2s.h b/sound/soc/bcm/bcm2708-i2s.h +new file mode 100644 +index 0000000..6fdcbc1 +--- /dev/null ++++ b/sound/soc/bcm/bcm2708-i2s.h +@@ -0,0 +1,35 @@ ++/* ++ * I2S configuration for sound cards. ++ * ++ * Copyright (c) 2014 Daniel Matuschek ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef BCM2708_I2S_H ++#define BCM2708_I2S_H ++ ++/* I2S pin assignment */ ++#define BCM2708_I2S_GPIO_AUTO 0 ++#define BCM2708_I2S_GPIO_PIN18 1 ++#define BCM2708_I2S_GPIO_PIN28 2 ++ ++/* Alt mode to enable I2S */ ++#define BCM2708_I2S_GPIO_PIN18_ALT 0 ++#define BCM2708_I2S_GPIO_PIN28_ALT 2 ++ ++extern void bcm2708_i2s_set_gpio(int gpio); ++ ++#endif + +From 355253cae3f2e9200926bfeb8d21646600d0768e Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:59:51 +0100 +Subject: [PATCH 36/77] ASoC: Add support for PCM5102A codec + +Some definitions to support the PCM5102A codec +by Texas Instruments. + +Signed-off-by: Florian Meier +--- + sound/soc/codecs/Kconfig | 4 +++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/pcm5102a.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+) + create mode 100644 sound/soc/codecs/pcm5102a.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 061c465..a3d70f9 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -83,6 +83,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM512x_I2C if I2C + select SND_SOC_PCM512x_SPI if SPI_MASTER + select SND_SOC_RT286 if I2C ++ select SND_SOC_PCM5102A if I2C + select SND_SOC_RT5631 if I2C + select SND_SOC_RT5640 if I2C + select SND_SOC_RT5645 if I2C +@@ -511,6 +512,9 @@ config SND_SOC_RT286 + tristate + depends on I2C + ++config SND_SOC_PCM5102A ++ tristate ++ + config SND_SOC_RT5631 + tristate "Realtek ALC5631/RT5631 CODEC" + depends on I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index abe2d7e..a0fda52 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -78,6 +78,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o + snd-soc-pcm512x-spi-objs := pcm512x-spi.o + snd-soc-rl6231-objs := rl6231.o + snd-soc-rt286-objs := rt286.o ++snd-soc-pcm5102a-objs := pcm5102a.o + snd-soc-rt5631-objs := rt5631.o + snd-soc-rt5640-objs := rt5640.o + snd-soc-rt5645-objs := rt5645.o +@@ -263,6 +264,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o ++obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o + obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o + obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o +diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c +new file mode 100644 +index 0000000..126f1e9 +--- /dev/null ++++ b/sound/soc/codecs/pcm5102a.c +@@ -0,0 +1,63 @@ ++/* ++ * Driver for the PCM5102A codec ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver pcm5102a_dai = { ++ .name = "pcm5102a-hifi", ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; ++ ++static int pcm5102a_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, ++ &pcm5102a_dai, 1); ++} ++ ++static int pcm5102a_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver pcm5102a_codec_driver = { ++ .probe = pcm5102a_probe, ++ .remove = pcm5102a_remove, ++ .driver = { ++ .name = "pcm5102a-codec", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(pcm5102a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From 49e137bd21361ad8f4439f35956ceab424013411 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:04:54 +0100 +Subject: [PATCH 37/77] BCM2708: Add I2S support to board file + +Adds the required initializations for I2S +to the board file of mach-bcm2708. + +Signed-off-by: Florian Meier + +bcm2708-i2s: Enable MMAP support via a DT property and overlay + +The i2s driver used to claim to support MMAP, but that feature was disabled +when some problems were found. Add the ability to enable this feature +through Device Tree, using the i2s-mmap overlay. + +See: #1004 +--- + arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ + sound/soc/bcm/bcm2708-i2s.c | 7 ++++++- + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index c7b4b61..dc57983 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -616,6 +616,28 @@ static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++static struct resource bcm2708_i2s_resources[] = { ++ { ++ .start = I2S_BASE, ++ .end = I2S_BASE + 0x20, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = PCM_CLOCK_BASE, ++ .end = PCM_CLOCK_BASE + 0x02, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device bcm2708_i2s_device = { ++ .name = "bcm2708-i2s", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), ++ .resource = bcm2708_i2s_resources, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -780,6 +802,10 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2835_thermal_device); + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++ bcm_register_device_dt(&bcm2708_i2s_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c +index a3b65dc..a515992 100644 +--- a/sound/soc/bcm/bcm2708-i2s.c ++++ b/sound/soc/bcm/bcm2708-i2s.c +@@ -874,7 +874,7 @@ static const struct snd_soc_component_driver bcm2708_i2s_component = { + .name = "bcm2708-i2s-comp", + }; + +-static const struct snd_pcm_hardware bcm2708_pcm_hardware = { ++static struct snd_pcm_hardware bcm2708_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX, + .formats = SNDRV_PCM_FMTBIT_S16_LE | +@@ -902,6 +902,11 @@ static int bcm2708_i2s_probe(struct platform_device *pdev) + struct regmap *regmap[2]; + struct resource *mem[2]; + ++ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) ++ bcm2708_pcm_hardware.info |= ++ SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID; ++ + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { + void __iomem *base; + +From 5786483930fcb7863012d8bb81d1f73a67b258da Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:19:08 +0100 +Subject: [PATCH 38/77] ASoC: Add support for HifiBerry DAC + +This adds a machine driver for the HifiBerry DAC. +It is a sound card that can +be stacked onto the Raspberry Pi. + +Signed-off-by: Florian Meier +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 5 +++ + sound/soc/bcm/hifiberry_dac.c | 100 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 112 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8642296..a4a3e86 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -18,3 +18,10 @@ config SND_BCM2708_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2708 I2S interface. You will also need + to select the audio interfaces to support below. ++ ++config SND_BCM2708_SOC_HIFIBERRY_DAC ++ tristate "Support for HifiBerry DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5102A ++ help ++ Say Y or M if you want to add support for HifiBerry DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index f8bbe1f..be90a49cb 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,3 +7,8 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o + + obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o ++ ++# BCM2708 Machine Support ++snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++ ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c +new file mode 100644 +index 0000000..4b70b45 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -0,0 +1,100 @@ ++/* ++ * ASoC Driver for HifiBerry DAC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_hifiberry_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dac_ops = { ++ .hw_params = snd_rpi_hifiberry_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { ++{ ++ .name = "HifiBerry DAC", ++ .stream_name = "HifiBerry DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm5102a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm5102a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dac_ops, ++ .init = snd_rpi_hifiberry_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dac = { ++ .name = "snd_rpi_hifiberry_dac", ++ .dai_link = snd_rpi_hifiberry_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), ++}; ++ ++static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_dac_driver = { ++ .driver = { ++ .name = "snd-hifiberry-dac", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_dac_probe, ++ .remove = snd_rpi_hifiberry_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); ++MODULE_LICENSE("GPL v2"); + +From 47d7a2a48fd4b2da2f9400de4307febe755b2ef2 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:21:34 +0100 +Subject: [PATCH 39/77] BCM2708: Add HifiBerry DAC to board file + +This adds the initalization of the HifiBerry DAC +to the mach-bcm2708 board file. + +Signed-off-by: Florian Meier +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index dc57983..ef7c48d 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -638,6 +638,20 @@ static struct platform_device bcm2708_i2s_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++static struct platform_device snd_hifiberry_dac_device = { ++ .name = "snd-hifiberry-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm5102a_codec_device = { ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -806,6 +820,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&bcm2708_i2s_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_dac_device); ++ bcm_register_device_dt(&snd_pcm5102a_codec_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + +From 403dc5c76505dd5813174532b2f032e52cbe06b8 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 6 Dec 2013 20:50:28 +0100 +Subject: [PATCH 40/77] ASoC: BCM2708: Add support for RPi-DAC + +This adds a machine driver for the RPi-DAC. + +Signed-off-by: Florian Meier +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-dac.c | 97 +++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/Kconfig | 4 ++ + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/pcm1794a.c | 62 ++++++++++++++++++++++++++ + 7 files changed, 193 insertions(+) + create mode 100644 sound/soc/bcm/rpi-dac.c + create mode 100644 sound/soc/codecs/pcm1794a.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index ef7c48d..be27073 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++static struct platform_device snd_rpi_dac_device = { ++ .name = "snd-rpi-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm1794a_codec_device = { ++ .name = "pcm1794a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -825,6 +839,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_dac_device); ++ bcm_register_device_dt(&snd_pcm1794a_codec_device); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a4a3e86..cb7c0c2 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -25,3 +25,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + select SND_SOC_PCM5102A + help + Say Y or M if you want to add support for HifiBerry DAC. ++ ++config SND_BCM2708_SOC_RPI_DAC ++ tristate "Support for RPi-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM1794A ++ help ++ Say Y or M if you want to add support for RPi-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index be90a49cb..ccc9809 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,5 +10,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-rpi-dac-objs := rpi-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c +new file mode 100644 +index 0000000..6d6e0ba +--- /dev/null ++++ b/sound/soc/bcm/rpi-dac.c +@@ -0,0 +1,97 @@ ++/* ++ * ASoC Driver for RPi-DAC. ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_rpi_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_rpi_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_rpi_dac_ops = { ++ .hw_params = snd_rpi_rpi_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = { ++{ ++ .name = "RPi-DAC", ++ .stream_name = "RPi-DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm1794a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm1794a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_rpi_dac_ops, ++ .init = snd_rpi_rpi_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_rpi_dac = { ++ .name = "snd_rpi_rpi_dac", ++ .dai_link = snd_rpi_rpi_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_rpi_dac_dai), ++}; ++ ++static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_rpi_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_rpi_dac); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_rpi_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_rpi_dac); ++} ++ ++static struct platform_driver snd_rpi_rpi_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-dac", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_rpi_dac_probe, ++ .remove = snd_rpi_rpi_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_rpi_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index a3d70f9..dc3df1a 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -84,6 +84,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM512x_SPI if SPI_MASTER + select SND_SOC_RT286 if I2C + select SND_SOC_PCM5102A if I2C ++ select SND_SOC_PCM1794A if I2C + select SND_SOC_RT5631 if I2C + select SND_SOC_RT5640 if I2C + select SND_SOC_RT5645 if I2C +@@ -512,6 +513,9 @@ config SND_SOC_RT286 + tristate + depends on I2C + ++config SND_SOC_PCM1794A ++ tristate ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index a0fda52..c1f6ba6 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -78,6 +78,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o + snd-soc-pcm512x-spi-objs := pcm512x-spi.o + snd-soc-rl6231-objs := rl6231.o + snd-soc-rt286-objs := rt286.o ++snd-soc-pcm1794a-objs := pcm1794a.o + snd-soc-pcm5102a-objs := pcm5102a.o + snd-soc-rt5631-objs := rt5631.o + snd-soc-rt5640-objs := rt5640.o +@@ -264,6 +265,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o ++obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o + obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o + obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o +diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c +new file mode 100644 +index 0000000..b4eaa44 +--- /dev/null ++++ b/sound/soc/codecs/pcm1794a.c +@@ -0,0 +1,62 @@ ++/* ++ * Driver for the PCM1794A codec ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver pcm1794a_dai = { ++ .name = "pcm1794a-hifi", ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_pcm1794a; ++ ++static int pcm1794a_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm1794a, ++ &pcm1794a_dai, 1); ++} ++ ++static int pcm1794a_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver pcm1794a_codec_driver = { ++ .probe = pcm1794a_probe, ++ .remove = pcm1794a_remove, ++ .driver = { ++ .name = "pcm1794a-codec", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(pcm1794a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From 0418e9bd3eab8e21b5d69ed0b7899dd5a80263f1 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:41:23 +0100 +Subject: [PATCH 41/77] 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 + additional mclk_div divider, it is now possible to control the behaviour. + This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It + should allow lower jitter and better signal quality. The behavior has to be + controlled by the sound card driver, because some sample frequency share the + same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only + difference is the MCLK divider. + +This also added support for 32bit data. + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 1e403f6..d4efa85 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, + blen = 0x1; + break; + case 24: ++ case 32: + blen = 0x2; + break; + default: +@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { + }; + + #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ +- SNDRV_PCM_FMTBIT_S24_LE) ++ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + +From 82c2f5a297701240bf5a77611d2d93c041497246 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:42:08 +0100 +Subject: [PATCH 42/77] ASoC: BCM:Add support for HiFiBerry Digi. Driver is + based on the patched WM8804 driver. + +Signed-off-by: Daniel Matuschek + +Add a parameter to turn off SPDIF output if no audio is playing + +This patch adds the paramater auto_shutdown_output to the kernel module. +Default behaviour of the module is the same, but when auto_shutdown_output +is set to 1, the SPDIF oputput will shutdown if no stream is playing. + +bugfix for 32kHz sample rate, was missing + +HiFiBerry Digi: set SPDIF status bits for sample rate + +The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. +While this is optional, some DACs and receivers do not accept this signal. This patch +adds the sample rate bits in the SPDIF status block. +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_digi.c | 201 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 210 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_digi.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index cb7c0c2..2e26e12 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + help + Say Y or M if you want to add support for HifiBerry DAC. + ++config SND_BCM2708_SOC_HIFIBERRY_DIGI ++ tristate "Support for HifiBerry Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index ccc9809..826df7d 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,7 +10,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +new file mode 100644 +index 0000000..92e9e46 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -0,0 +1,201 @@ ++/* ++ * ASoC Driver for HifiBerry Digi ++ * ++ * Author: Daniel Matuschek ++ * based on the HifiBerry DAC driver by Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8804.h" ++ ++static short int auto_shutdown_output = 0; ++module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++ ++static int samplerate=44100; ++ ++static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_digi_startup(struct snd_pcm_substream *substream) { ++ /* turn on digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { ++ /* turn off output */ ++ if (auto_shutdown_output) { ++ /* turn off output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ int sysclk = 27000000; /* This is fixed on this board */ ++ ++ long mclk_freq=0; ++ int mclk_div=1; ++ int sampling_freq=1; ++ ++ int ret; ++ ++ samplerate = params_rate(params); ++ ++ if (samplerate<=96000) { ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq=0x03; ++ break; ++ case 44100: ++ sampling_freq=0x00; ++ break; ++ case 48000: ++ sampling_freq=0x02; ++ break; ++ case 88200: ++ sampling_freq=0x08; ++ break; ++ case 96000: ++ sampling_freq=0x0a; ++ break; ++ case 176400: ++ sampling_freq=0x0c; ++ break; ++ case 192000: ++ sampling_freq=0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { ++ .hw_params = snd_rpi_hifiberry_digi_hw_params, ++ .startup = snd_rpi_hifiberry_digi_startup, ++ .shutdown = snd_rpi_hifiberry_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { ++{ ++ .name = "HifiBerry Digi", ++ .stream_name = "HifiBerry Digi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_hifiberry_digi_ops, ++ .init = snd_rpi_hifiberry_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_digi = { ++ .name = "snd_rpi_hifiberry_digi", ++ .dai_link = snd_rpi_hifiberry_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), ++}; ++ ++static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_digi.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_digi_driver = { ++ .driver = { ++ .name = "snd-hifiberry-digi", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_digi_probe, ++ .remove = snd_rpi_hifiberry_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); ++MODULE_LICENSE("GPL v2"); + +From df14e52cd5e411324c58e28ec158f503d4905dbb Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:26:08 +0100 +Subject: [PATCH 43/77] BCM2708: Added support for HiFiBerry Digi board Board + initalization by I2C + +Signed-off-by: Daniel Matuschek +--- + arch/arm/mach-bcm2708/bcm2708.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index be27073..2a33663 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,21 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++static struct platform_device snd_hifiberry_digi_device = { ++ .name = "snd-hifiberry-digi", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8804", 0x3b) ++ }, ++}; ++ ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", +@@ -839,6 +854,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_digi_device); ++ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); + +From d8de9644604c68b7148b023608d70d8ac3bf466f Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:36:35 +0100 +Subject: [PATCH 44/77] ASoC: wm8804: Set idle_bias_off to false Idle bias has + been change to remove warning on driver startup + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index d4efa85..f3f26a2 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -544,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { + }; + + static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { +- .idle_bias_off = true, ++ .idle_bias_off = false, + + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + +From 40f01186460630fa704c88adbefbc347e5e402e4 Mon Sep 17 00:00:00 2001 +From: Gordon Garrity +Date: Sat, 8 Mar 2014 16:56:57 +0000 +Subject: [PATCH 45/77] Add IQaudIO Sound Card support for Raspberry Pi + +Set a limit of 0dB on Digital Volume Control + +The main volume control in the PCM512x DAC has a range up to ++24dB. This is dangerously loud and can potentially cause massive +clipping in the output stages. Therefore this sets a sensible +limit of 0dB for this control. +--- + arch/arm/mach-bcm2708/bcm2708.c | 21 ++++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio-dac.c | 117 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 147 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio-dac.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 2a33663..957504e 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -681,6 +681,22 @@ static struct platform_device snd_pcm1794a_codec_device = { + }; + #endif + ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++static struct platform_device snd_rpi_iqaudio_dac_device = { ++ .name = "snd-rpi-iqaudio-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++// Use the actual device name rather than generic driver name ++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4c) ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -864,6 +880,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm1794a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 2e26e12..f6f8ec1 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -39,3 +39,10 @@ config SND_BCM2708_SOC_RPI_DAC + select SND_SOC_PCM1794A + help + Say Y or M if you want to add support for RPi-DAC. ++ ++config SND_BCM2708_SOC_IQAUDIO_DAC ++ tristate "Support for IQaudIO-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ help ++ Say Y or M if you want to add support for IQaudIO-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 826df7d..d597fb0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,7 +12,9 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +new file mode 100644 +index 0000000..aff7377 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -0,0 +1,117 @@ ++/* ++ * ASoC Driver for IQaudIO DAC ++ * ++ * Author: Florian Meier ++ * Copyright 2013 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ ret = snd_soc_limit_volume(codec, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; ++// NOT USED struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { ++ .hw_params = snd_rpi_iqaudio_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { ++{ ++ .name = "IQaudIO DAC", ++ .stream_name = "IQaudIO DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_iqaudio_dac_ops, ++ .init = snd_rpi_iqaudio_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_dac = { ++ .name = "IQaudIODAC", ++ .dai_link = snd_rpi_iqaudio_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), ++}; ++ ++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); ++} ++ ++static const struct of_device_id iqaudio_of_match[] = { ++ { .compatible = "iqaudio,iqaudio-dac", }, ++ {}, ++}; ++ ++static struct platform_driver snd_rpi_iqaudio_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-iqaudio-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = iqaudio_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_dac_probe, ++ .remove = snd_rpi_iqaudio_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); ++MODULE_LICENSE("GPL v2"); + +From 5d1014e6dfa91f7f4b07851eefaa0a8bc544fda8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 18 Jun 2014 13:42:01 +0100 +Subject: [PATCH 46/77] vmstat: Workaround for issue where dirty page count + goes negative + +See: +https://github.com/raspberrypi/linux/issues/617 +http://www.spinics.net/lists/linux-mm/msg72236.html +--- + include/linux/vmstat.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h +index 82e7db7..f87d16d 100644 +--- a/include/linux/vmstat.h ++++ b/include/linux/vmstat.h +@@ -241,7 +241,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) + static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) + { + atomic_long_dec(&zone->vm_stat[item]); ++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&zone->vm_stat[item]) < 0)) ++ atomic_long_set(&zone->vm_stat[item], 0); + atomic_long_dec(&vm_stat[item]); ++ if (item == NR_FILE_DIRTY && unlikely(atomic_long_read(&vm_stat[item]) < 0)) ++ atomic_long_set(&vm_stat[item], 0); + } + + static inline void __inc_zone_page_state(struct page *page, + +From 462ac627ee409f190f5519727c80942afafd0d6d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 14 Jul 2014 22:02:09 +0100 +Subject: [PATCH 47/77] hid: Reduce default mouse polling interval to 60Hz + +Reduces overhead when using X +--- + drivers/hid/usbhid/hid-core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index bfbe1be..a738b25 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -49,7 +49,7 @@ + * Module parameters. + */ + +-static unsigned int hid_mousepoll_interval; ++static unsigned int hid_mousepoll_interval = ~0; + module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); + MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); + +@@ -1090,8 +1090,12 @@ static int usbhid_start(struct hid_device *hid) + } + + /* Change the polling interval of mice. */ +- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) +- interval = hid_mousepoll_interval; ++ if (hid->collection->usage == HID_GD_MOUSE) { ++ if (hid_mousepoll_interval == ~0 && interval < 16) ++ interval = 16; ++ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) ++ interval = hid_mousepoll_interval; ++ } + + ret = -ENOMEM; + if (usb_endpoint_dir_in(endpoint)) { + +From 6a68d9854eed6f1c5741aff8466cb5877deecd54 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 10:06:56 +0200 +Subject: [PATCH 48/77] 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. +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++ + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_dacplus.c | 119 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 147 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dacplus.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 957504e..90459b8 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++static struct platform_device snd_rpi_hifiberry_dacplus_device = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4d) ++ }, ++}; ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + static struct platform_device snd_hifiberry_digi_device = { + .name = "snd-hifiberry-digi", +@@ -870,6 +884,11 @@ void __init bcm2708_init(void) + bcm_register_device_dt(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + bcm_register_device_dt(&snd_hifiberry_digi_device); + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index f6f8ec1..8b45ac5 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -26,6 +26,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + help + Say Y or M if you want to add support for HifiBerry DAC. + ++config SND_BCM2708_SOC_HIFIBERRY_DACPLUS ++ tristate "Support for HifiBerry DAC+" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x ++ help ++ Say Y or M if you want to add support for HifiBerry DAC+. ++ + config SND_BCM2708_SOC_HIFIBERRY_DIGI + tristate "Support for HifiBerry Digi" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index d597fb0..c02e3a2 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -10,11 +10,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +new file mode 100644 +index 0000000..c63387b +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -0,0 +1,119 @@ ++/* ++ * ASoC Driver for HiFiBerry DAC+ ++ * ++ * Author: Daniel Matuschek ++ * Copyright 2014 ++ * based on code by Florian Meier ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/pcm512x.h" ++ ++static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++static int snd_rpi_hifiberry_dacplus_startup(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_dacplus_shutdown(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { ++ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, ++ .startup = snd_rpi_hifiberry_dacplus_startup, ++ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { ++{ ++ .name = "HiFiBerry DAC+", ++ .stream_name = "HiFiBerry DAC+ HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dacplus_ops, ++ .init = snd_rpi_hifiberry_dacplus_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dacplus = { ++ .name = "snd_rpi_hifiberry_dacplus", ++ .dai_link = snd_rpi_hifiberry_dacplus_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), ++}; ++ ++static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { ++ .driver = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_dacplus_probe, ++ .remove = snd_rpi_hifiberry_dacplus_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dacplus_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); ++MODULE_LICENSE("GPL v2"); + +From 1ca3777a5f3e17847136937e1bab1717281c73ca Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 11:09:58 +0200 +Subject: [PATCH 49/77] 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. + +TAS5713: return error if initialisation fails + +Existing TAS5713 driver logs errors during initialisation, but does not return +an error code. Therefore even if initialisation fails, the driver will still be +loaded, but won't work. This patch fixes this. I2C communication error will now +reported correctly by a non-zero return code. + +HiFiBerry Amp: fix device-tree problems + +Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 +++ + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_amp.c | 127 ++++++++++++++ + sound/soc/codecs/Kconfig | 4 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/tas5713.h | 210 +++++++++++++++++++++++ + 8 files changed, 740 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_amp.c + create mode 100644 sound/soc/codecs/tas5713.c + create mode 100644 sound/soc/codecs/tas5713.h + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 90459b8..785cf1a 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -681,6 +681,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { + + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++static struct platform_device snd_hifiberry_amp_device = { ++ .name = "snd-hifiberry-amp", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("tas5713", 0x1b) ++ }, ++}; ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", +@@ -894,6 +908,11 @@ void __init bcm2708_init(void) + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_amp_device); ++ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); ++#endif ++ + #if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8b45ac5..bdcf12f 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -40,6 +40,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. + ++config SND_BCM2708_SOC_HIFIBERRY_AMP ++ tristate "Support for the HifiBerry Amp" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_TAS5713 ++ help ++ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index c02e3a2..17ea2b0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o ++snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +new file mode 100644 +index 0000000..5903915 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_amp.c +@@ -0,0 +1,127 @@ ++/* ++ * ASoC Driver for HifiBerry AMP ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_hifiberry_amp_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ // ToDo: init of the dsp-registers. ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_amp_hw_params( struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params ) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { ++ .hw_params = snd_rpi_hifiberry_amp_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { ++ { ++ .name = "HifiBerry AMP", ++ .stream_name = "HifiBerry AMP HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tas5713-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tas5713.1-001b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_amp_ops, ++ .init = snd_rpi_hifiberry_amp_init, ++ }, ++}; ++ ++ ++static struct snd_soc_card snd_rpi_hifiberry_amp = { ++ .name = "snd_rpi_hifiberry_amp", ++ .dai_link = snd_rpi_hifiberry_amp_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), ++}; ++ ++static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-amp", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); ++ ++ ++static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_amp.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); ++ ++ if (ret != 0) { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); ++} ++ ++ ++static struct platform_driver snd_rpi_hifiberry_amp_driver = { ++ .driver = { ++ .name = "snd-hifiberry-amp", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_amp_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_amp_probe, ++ .remove = snd_rpi_hifiberry_amp_remove, ++}; ++ ++ ++module_platform_driver(snd_rpi_hifiberry_amp_driver); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index dc3df1a..8a9f07c 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -109,6 +109,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER ++ select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4 if I2C +@@ -623,6 +624,9 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C + ++config SND_SOC_TAS5713 ++ tristate ++ + config SND_SOC_TLV320AIC23 + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index c1f6ba6..8ebf7f1 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -109,6 +109,7 @@ snd-soc-sta529-objs := sta529.o + snd-soc-stac9766-objs := stac9766.o + snd-soc-tas5086-objs := tas5086.o + snd-soc-tfa9879-objs := tfa9879.o ++snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -293,6 +294,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o + obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o + obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o ++obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +new file mode 100644 +index 0000000..9b27138 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.c +@@ -0,0 +1,369 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "tas5713.h" ++ ++ ++static struct i2c_client *i2c; ++ ++struct tas5713_priv { ++ struct regmap *regmap; ++ int mclk_div; ++ struct snd_soc_codec *codec; ++}; ++ ++static struct tas5713_priv *priv_data; ++ ++ ++ ++ ++/* ++ * _ _ ___ _ ___ _ _ ++ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ ++ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< ++ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ ++ * ++ */ ++ ++static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); ++ ++ ++static const struct snd_kcontrol_new tas5713_snd_controls[] = { ++ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), ++ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) ++}; ++ ++ ++ ++ ++/* ++ * __ __ _ _ ___ _ ++ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ ++ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| ++ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ u16 blen = 0x00; ++ ++ struct snd_soc_codec *codec; ++ codec = dai->codec; ++ priv_data->codec = dai->codec; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ blen = 0x03; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ blen = 0x1; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ blen = 0x04; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ blen = 0x05; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported word length: %u\n", ++ params_format(params)); ++ return -EINVAL; ++ } ++ ++ // set word length ++ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); ++ ++ return 0; ++} ++ ++ ++static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ unsigned int val = 0; ++ ++ struct tas5713_priv *tas5713; ++ struct snd_soc_codec *codec = dai->codec; ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ if (mute) { ++ val = TAS5713_SOFT_MUTE_ALL; ++ } ++ ++ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); ++} ++ ++ ++static const struct snd_soc_dai_ops tas5713_dai_ops = { ++ .hw_params = tas5713_hw_params, ++ .mute_stream = tas5713_mute_stream, ++}; ++ ++ ++static struct snd_soc_dai_driver tas5713_dai = { ++ .name = "tas5713-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), ++ }, ++ .ops = &tas5713_dai_ops, ++}; ++ ++ ++ ++ ++/* ++ * ___ _ ___ _ ++ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ ++ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| ++ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_remove(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ return 0; ++} ++ ++ ++static int tas5713_probe(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ int i, ret; ++ ++ i2c = container_of(codec->dev, struct i2c_client, dev); ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Trim oscillator ++ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); ++ if (ret < 0) return ret; ++ msleep(1000); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Clock mode: 44/48kHz, MCLK=64xfs ++ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); ++ if (ret < 0) return ret; ++ ++ // I2S 24bit ++ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); ++ if (ret < 0) return ret; ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); ++ if (ret < 0) return ret; ++ ++ // Set volume to 0db ++ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); ++ if (ret < 0) return ret; ++ ++ // Now start programming the default initialization sequence ++ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { ++ ret = i2c_master_send(i2c, ++ tas5713_init_sequence[i].data, ++ tas5713_init_sequence[i].size); ++ if (ret < 0) { ++ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); ++ } ++ } ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { ++ .probe = tas5713_probe, ++ .remove = tas5713_remove, ++ .controls = tas5713_snd_controls, ++ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++}; ++ ++ ++ ++ ++/* ++ * ___ ___ ___ ___ _ ++ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ ++ * | | / / (__ | |) | '_| \ V / -_) '_| ++ * |___/___\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static const struct reg_default tas5713_reg_defaults[] = { ++ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB ++ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB ++ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB ++ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB ++}; ++ ++ ++static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case TAS5713_DEVICE_ID: ++ case TAS5713_ERROR_STATUS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++ ++static const struct of_device_id tas5713_of_match[] = { ++ { .compatible = "ti,tas5713", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, tas5713_of_match); ++ ++ ++static struct regmap_config tas5713_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .max_register = TAS5713_MAX_REGISTER, ++ .volatile_reg = tas5713_reg_volatile, ++ ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = tas5713_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), ++}; ++ ++ ++static int tas5713_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ int ret; ++ ++ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); ++ if (!priv_data) ++ return -ENOMEM; ++ ++ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); ++ if (IS_ERR(priv_data->regmap)) { ++ ret = PTR_ERR(priv_data->regmap); ++ return ret; ++ } ++ ++ i2c_set_clientdata(i2c, priv_data); ++ ++ ret = snd_soc_register_codec(&i2c->dev, ++ &soc_codec_dev_tas5713, &tas5713_dai, 1); ++ ++ return ret; ++} ++ ++ ++static int tas5713_i2c_remove(struct i2c_client *i2c) ++{ ++ snd_soc_unregister_codec(&i2c->dev); ++ i2c_set_clientdata(i2c, NULL); ++ ++ kfree(priv_data); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id tas5713_i2c_id[] = { ++ { "tas5713", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); ++ ++ ++static struct i2c_driver tas5713_i2c_driver = { ++ .driver = { ++ .name = "tas5713", ++ .owner = THIS_MODULE, ++ .of_match_table = tas5713_of_match, ++ }, ++ .probe = tas5713_i2c_probe, ++ .remove = tas5713_i2c_remove, ++ .id_table = tas5713_i2c_id ++}; ++ ++ ++static int __init tas5713_modinit(void) ++{ ++ int ret = 0; ++ ++ ret = i2c_add_driver(&tas5713_i2c_driver); ++ if (ret) { ++ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", ++ ret); ++ } ++ ++ return ret; ++} ++module_init(tas5713_modinit); ++ ++ ++static void __exit tas5713_exit(void) ++{ ++ i2c_del_driver(&tas5713_i2c_driver); ++} ++module_exit(tas5713_exit); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for TAS5713"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +new file mode 100644 +index 0000000..8f019e0 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.h +@@ -0,0 +1,210 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++#ifndef _TAS5713_H ++#define _TAS5713_H ++ ++ ++// TAS5713 I2C-bus register addresses ++ ++#define TAS5713_CLOCK_CTRL 0x00 ++#define TAS5713_DEVICE_ID 0x01 ++#define TAS5713_ERROR_STATUS 0x02 ++#define TAS5713_SYSTEM_CTRL1 0x03 ++#define TAS5713_SERIAL_DATA_INTERFACE 0x04 ++#define TAS5713_SYSTEM_CTRL2 0x05 ++#define TAS5713_SOFT_MUTE 0x06 ++#define TAS5713_VOL_MASTER 0x07 ++#define TAS5713_VOL_CH1 0x08 ++#define TAS5713_VOL_CH2 0x09 ++#define TAS5713_VOL_HEADPHONE 0x0A ++#define TAS5713_VOL_CONFIG 0x0E ++#define TAS5713_MODULATION_LIMIT 0x10 ++#define TAS5713_IC_DLY_CH1 0x11 ++#define TAS5713_IC_DLY_CH2 0x12 ++#define TAS5713_IC_DLY_CH3 0x13 ++#define TAS5713_IC_DLY_CH4 0x14 ++ ++#define TAS5713_START_STOP_PERIOD 0x1A ++#define TAS5713_OSC_TRIM 0x1B ++#define TAS5713_BKND_ERR 0x1C ++ ++#define TAS5713_INPUT_MUX 0x20 ++#define TAS5713_SRC_SELECT_CH4 0x21 ++#define TAS5713_PWM_MUX 0x25 ++ ++#define TAS5713_CH1_BQ0 0x29 ++#define TAS5713_CH1_BQ1 0x2A ++#define TAS5713_CH1_BQ2 0x2B ++#define TAS5713_CH1_BQ3 0x2C ++#define TAS5713_CH1_BQ4 0x2D ++#define TAS5713_CH1_BQ5 0x2E ++#define TAS5713_CH1_BQ6 0x2F ++#define TAS5713_CH1_BQ7 0x58 ++#define TAS5713_CH1_BQ8 0x59 ++ ++#define TAS5713_CH2_BQ0 0x30 ++#define TAS5713_CH2_BQ1 0x31 ++#define TAS5713_CH2_BQ2 0x32 ++#define TAS5713_CH2_BQ3 0x33 ++#define TAS5713_CH2_BQ4 0x34 ++#define TAS5713_CH2_BQ5 0x35 ++#define TAS5713_CH2_BQ6 0x36 ++#define TAS5713_CH2_BQ7 0x5C ++#define TAS5713_CH2_BQ8 0x5D ++ ++#define TAS5713_CH4_BQ0 0x5A ++#define TAS5713_CH4_BQ1 0x5B ++#define TAS5713_CH3_BQ0 0x5E ++#define TAS5713_CH3_BQ1 0x5F ++ ++#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B ++#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C ++#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E ++#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F ++#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 ++#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 ++#define TAS5713_DRC_CTRL 0x46 ++ ++#define TAS5713_BANK_SW_CTRL 0x50 ++#define TAS5713_CH1_OUTPUT_MIXER 0x51 ++#define TAS5713_CH2_OUTPUT_MIXER 0x52 ++#define TAS5713_CH1_INPUT_MIXER 0x53 ++#define TAS5713_CH2_INPUT_MIXER 0x54 ++#define TAS5713_OUTPUT_POST_SCALE 0x56 ++#define TAS5713_OUTPUT_PRESCALE 0x57 ++ ++#define TAS5713_IDF_POST_SCALE 0x62 ++ ++#define TAS5713_CH1_INLINE_MIXER 0x70 ++#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 ++#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 ++#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 ++#define TAS5713_CH2_INLINE_MIXER 0x74 ++#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 ++#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 ++#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 ++ ++#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 ++#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 ++ ++#define TAS5713_REGISTER_COUNT 0x46 ++#define TAS5713_MAX_REGISTER 0xF9 ++ ++ ++// Bitmasks for registers ++#define TAS5713_SOFT_MUTE_ALL 0x07 ++ ++ ++ ++struct tas5713_init_command { ++ const int size; ++ const char *const data; ++}; ++ ++static const struct tas5713_init_command tas5713_init_sequence[] = { ++ ++ // Trim oscillator ++ { .size = 2, .data = "\x1B\x00" }, ++ // System control register 1 (0x03): block DC ++ { .size = 2, .data = "\x03\x80" }, ++ // Mute everything ++ { .size = 2, .data = "\x05\x40" }, ++ // Modulation limit register (0x10): 97.7% ++ { .size = 2, .data = "\x10\x02" }, ++ // Interchannel delay registers ++ // (0x11, 0x12, 0x13, and 0x14): BD mode ++ { .size = 2, .data = "\x11\xB8" }, ++ { .size = 2, .data = "\x12\x60" }, ++ { .size = 2, .data = "\x13\xA0" }, ++ { .size = 2, .data = "\x14\x48" }, ++ // PWM shutdown group register (0x19): no shutdown ++ { .size = 2, .data = "\x19\x00" }, ++ // Input multiplexer register (0x20): BD mode ++ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, ++ // PWM output mux register (0x25) ++ // Channel 1 --> OUTA, channel 1 neg --> OUTB ++ // Channel 2 --> OUTC, channel 2 neg --> OUTD ++ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, ++ // DRC control (0x46): DRC off ++ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, ++ // BKND_ERR register (0x1C): 299ms reset period ++ { .size = 2, .data = "\x1C\x07" }, ++ // Mute channel 3 ++ { .size = 2, .data = "\x0A\xFF" }, ++ // Volume configuration register (0x0E): volume slew 512 steps ++ { .size = 2, .data = "\x0E\x90" }, ++ // Clock control register (0x00): 44/48kHz, MCLK=64xfs ++ { .size = 2, .data = "\x00\x60" }, ++ // Bank switch and eq control (0x50): no bank switching ++ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, ++ // Volume registers (0x07, 0x08, 0x09, 0x0A) ++ { .size = 2, .data = "\x07\x20" }, ++ { .size = 2, .data = "\x08\x30" }, ++ { .size = 2, .data = "\x09\x30" }, ++ { .size = 2, .data = "\x0A\xFF" }, ++ // 0x72, 0x73, 0x76, 0x77 input mixer: ++ // no intermix between channels ++ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, ++ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: ++ // no inline DRC inmix ++ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, ++ // 0x56, 0x57 Output scale ++ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, ++ // 0x3B, 0x3c ++ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ // 0x51, 0x52: output mixer ++ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ // PEQ defaults ++ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++}; ++ ++ ++#endif /* _TAS5713_H */ + +From 06c9b132b1340b495048f8814be13fe71b5cd77e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Apr 2015 19:14:18 +0100 +Subject: [PATCH 50/77] bcm2708: Allow option card devices to be configured via + DT + +If the kernel is built with Device Tree support, and if a DT blob +is provided for the kernel at boot time, then the platform devices +for option cards are not created. This avoids both the need to +blacklist unwanted devices, and the need to update the board +support code with each new device. +--- + sound/soc/bcm/bcm2835-i2s.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 03fa1cb..c816526 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -861,6 +861,7 @@ static const struct of_device_id bcm2835_i2s_of_match[] = { + { .compatible = "brcm,bcm2835-i2s", }, + {}, + }; ++MODULE_DEVICE_TABLE(of, bcm2835_i2s_of_match); + + static struct platform_driver bcm2835_i2s_driver = { + .probe = bcm2835_i2s_probe, + +From a9fff3c9005e6658977bd5e7df92114e70e1f813 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 13 Apr 2015 18:45:39 +0100 +Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards + +--- + arch/arm/mach-bcm2709/bcm2709.c | 143 ++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/hifiberry_dac.c | 22 ++++++ + sound/soc/bcm/hifiberry_dacplus.c | 22 ++++++ + sound/soc/bcm/hifiberry_digi.c | 22 ++++++ + sound/soc/bcm/iqaudio-dac.c | 16 +++++ + sound/soc/codecs/pcm5102a.c | 7 ++ + 6 files changed, 232 insertions(+) + +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 03e208b..2ae79d9 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -636,6 +636,115 @@ static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", + }; + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++static struct resource bcm2708_i2s_resources[] = { ++ { ++ .start = I2S_BASE, ++ .end = I2S_BASE + 0x20, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = PCM_CLOCK_BASE, ++ .end = PCM_CLOCK_BASE + 0x02, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device bcm2708_i2s_device = { ++ .name = "bcm2708-i2s", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), ++ .resource = bcm2708_i2s_resources, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++static struct platform_device snd_hifiberry_dac_device = { ++ .name = "snd-hifiberry-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm5102a_codec_device = { ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++static struct platform_device snd_rpi_hifiberry_dacplus_device = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4d) ++ }, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++static struct platform_device snd_hifiberry_digi_device = { ++ .name = "snd-hifiberry-digi", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8804", 0x3b) ++ }, ++}; ++ ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++static struct platform_device snd_hifiberry_amp_device = { ++ .name = "snd-hifiberry-amp", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("tas5713", 0x1b) ++ }, ++}; ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++static struct platform_device snd_rpi_dac_device = { ++ .name = "snd-rpi-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_pcm1794a_codec_device = { ++ .name = "pcm1794a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++static struct platform_device snd_rpi_iqaudio_dac_device = { ++ .name = "snd-rpi-iqaudio-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++// Use the actual device name rather than generic driver name ++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4c) ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -800,6 +909,40 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2835_thermal_device); + ++#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) ++ bcm_register_device_dt(&bcm2708_i2s_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_dac_device); ++ bcm_register_device_dt(&snd_pcm5102a_codec_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) ++ bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_digi_device); ++ i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) ++ bcm_register_device_dt(&snd_hifiberry_amp_device); ++ i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_dac_device); ++ bcm_register_device_dt(&snd_pcm1794a_codec_device); ++#endif ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++ bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); ++ i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); ++#endif ++ + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; +diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c +index 4b70b45..3ab0f47 100644 +--- a/sound/soc/bcm/hifiberry_dac.c ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -72,6 +72,21 @@ static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +@@ -84,10 +99,17 @@ static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); + } + ++static const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_dac_driver = { + .driver = { + .name = "snd-hifiberry-dac", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dac_of_match, + }, + .probe = snd_rpi_hifiberry_dac_probe, + .remove = snd_rpi_hifiberry_dac_remove, +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +index c63387b..11e4f39 100644 +--- a/sound/soc/bcm/hifiberry_dacplus.c ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -90,6 +90,21 @@ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dacplus_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); + if (ret) + dev_err(&pdev->dev, +@@ -103,10 +118,17 @@ static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); + } + ++static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dacplus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { + .driver = { + .name = "snd-rpi-hifiberry-dacplus", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, + }, + .probe = snd_rpi_hifiberry_dacplus_probe, + .remove = snd_rpi_hifiberry_dacplus_remove, +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +index 92e9e46..80732b8 100644 +--- a/sound/soc/bcm/hifiberry_digi.c ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -173,6 +173,21 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_hifiberry_digi.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); +@@ -185,10 +200,17 @@ static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) + return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); + } + ++static const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); ++ + static struct platform_driver snd_rpi_hifiberry_digi_driver = { + .driver = { + .name = "snd-hifiberry-digi", + .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_digi_of_match, + }, + .probe = snd_rpi_hifiberry_digi_probe, + .remove = snd_rpi_hifiberry_digi_remove, +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +index aff7377..a38e874 100644 +--- a/sound/soc/bcm/iqaudio-dac.c ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -82,6 +82,21 @@ static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) + int ret = 0; + + snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); + if (ret) + dev_err(&pdev->dev, +@@ -99,6 +114,7 @@ static const struct of_device_id iqaudio_of_match[] = { + { .compatible = "iqaudio,iqaudio-dac", }, + {}, + }; ++MODULE_DEVICE_TABLE(of, iqaudio_of_match); + + static struct platform_driver snd_rpi_iqaudio_dac_driver = { + .driver = { +diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c +index 126f1e9..7c6598e 100644 +--- a/sound/soc/codecs/pcm5102a.c ++++ b/sound/soc/codecs/pcm5102a.c +@@ -47,12 +47,19 @@ static int pcm5102a_remove(struct platform_device *pdev) + return 0; + } + ++static const struct of_device_id pcm5102a_of_match[] = { ++ { .compatible = "ti,pcm5102a", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcm5102a_of_match); ++ + static struct platform_driver pcm5102a_codec_driver = { + .probe = pcm5102a_probe, + .remove = pcm5102a_remove, + .driver = { + .name = "pcm5102a-codec", + .owner = THIS_MODULE, ++ .of_match_table = pcm5102a_of_match, + }, + }; + + +From 9518bd237c4fb516a0ec78f7ec81e5784f8425e0 Mon Sep 17 00:00:00 2001 +From: Timo Kokkonen +Date: Wed, 29 Oct 2014 23:30:30 -0700 +Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used + from pps-gpio module (LinuxPPS). Enable PPS modules in default config for + RPi. + +--- + arch/arm/mach-bcm2708/bcm2708.c | 27 +++++++++++++++++++++++++++ + arch/arm/mach-bcm2709/bcm2709.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 785cf1a..e42f5a5 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -92,6 +93,7 @@ static unsigned reboot_part = 0; + static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; ++static int pps_gpio_pin = -1; + + static unsigned use_dt = 0; + +@@ -325,6 +327,19 @@ static struct platform_device w1_device = { + }; + #endif + ++static struct pps_gpio_platform_data pps_gpio_info = { ++ .assert_falling_edge = false, ++ .capture_clear = false, ++ .gpio_pin = -1, ++ .gpio_label = "PPS", ++}; ++ ++static struct platform_device pps_gpio_device = { ++ .name = "pps-gpio", ++ .id = PLATFORM_DEVID_NONE, ++ .dev.platform_data = &pps_gpio_info, ++}; ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -860,6 +875,16 @@ void __init bcm2708_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++ ++#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) ++ if (!use_dt && (pps_gpio_pin >= 0)) { ++ pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); ++ pps_gpio_info.gpio_pin = pps_gpio_pin; ++ pps_gpio_device.id = pps_gpio_pin; ++ bcm_register_device(&pps_gpio_device); ++ } ++#endif ++ + #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; +@@ -1116,3 +1141,5 @@ module_param(w1_gpio_pin, uint, 0644); + module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); ++module_param(pps_gpio_pin, int, 0644); ++MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); +diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c +index 2ae79d9..95223ff 100644 +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -94,6 +95,7 @@ static unsigned reboot_part = 0; + static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; ++static int pps_gpio_pin = -1; + + static unsigned use_dt = 0; + +@@ -335,6 +337,19 @@ static struct platform_device w1_device = { + }; + #endif + ++static struct pps_gpio_platform_data pps_gpio_info = { ++ .assert_falling_edge = false, ++ .capture_clear = false, ++ .gpio_pin = -1, ++ .gpio_label = "PPS", ++}; ++ ++static struct platform_device pps_gpio_device = { ++ .name = "pps-gpio", ++ .id = PLATFORM_DEVID_NONE, ++ .dev.platform_data = &pps_gpio_info, ++}; ++ + static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_fb_device = { +@@ -880,6 +895,16 @@ void __init bcm2709_init(void) + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); + #endif ++ ++#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) ++ if (!use_dt && (pps_gpio_pin >= 0)) { ++ pr_info("bcm2709: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); ++ pps_gpio_info.gpio_pin = pps_gpio_pin; ++ pps_gpio_device.id = pps_gpio_pin; ++ bcm_register_device(&pps_gpio_device); ++ } ++#endif ++ + #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; +@@ -1284,3 +1309,5 @@ module_param(w1_gpio_pin, uint, 0644); + module_param(w1_gpio_pullup, uint, 0644); + module_param(vc_i2c_override, bool, 0644); + MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); ++module_param(pps_gpio_pin, int, 0644); ++MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); + +From 6831eded602a01774036cb24d3195dbbd51f9135 Mon Sep 17 00:00:00 2001 +From: Ryan Coe +Date: Sat, 31 Jan 2015 18:25:49 -0700 +Subject: [PATCH 53/77] Update ds1307 driver for device-tree support + +Signed-off-by: Ryan Coe +--- + drivers/rtc/rtc-ds1307.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 4ffabb3..c6789a7 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1242,6 +1242,14 @@ static int ds1307_remove(struct i2c_client *client) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id ds1307_of_match[] = { ++ { .compatible = "maxim,ds1307" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ds1307_of_match); ++#endif ++ + static struct i2c_driver ds1307_driver = { + .driver = { + .name = "rtc-ds1307", + +From 47ca2482bc03a888435d35139cd2f5989354ee1b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 6 Feb 2015 13:50:57 +0000 +Subject: [PATCH 54/77] BCM270x_DT: Add pwr_led, and the required "input" + trigger + +The "input" trigger makes the associated GPIO an input. This is to support +the Raspberry Pi PWR LED, which is driven by external hardware in normal use. + +N.B. pwr_led is not available on Model A or B boards. +--- + drivers/leds/trigger/Kconfig | 7 ++++ + drivers/leds/trigger/Makefile | 1 + + drivers/leds/trigger/ledtrig-input.c | 65 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 73 insertions(+) + create mode 100644 drivers/leds/trigger/ledtrig-input.c + diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..640756b 100644 --- a/drivers/leds/trigger/Kconfig @@ -124668,10 +127463,10 @@ index 0000000..2ca2b98 +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); -From be825a324f0b4e90f3fc396b0ed17442c5cb771d Mon Sep 17 00:00:00 2001 +From 38c278bba1388423ba1508d0712babb717685530 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Jun 2014 17:19:27 +0100 -Subject: [PATCH 072/216] bcm2709: Simplify and strip down IRQ handler +Subject: [PATCH 55/77] bcm2709: Simplify and strip down IRQ handler --- arch/arm/include/asm/entry-macro-multi.S | 2 + @@ -124890,737 +127685,10 @@ index d08591b..08d184c 100644 +1: get_irqnr_and_base r0, r2, r6, lr + .endm -From 219ae1b83de018ba2a3e3d909c0cbfce14579c14 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Tue, 3 Feb 2015 07:15:19 +0100 -Subject: [PATCH 073/216] HiFiBerry Amp: fix device-tree problems - -Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. ---- - sound/soc/bcm/hifiberry_amp.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -index 1e87ee06..5903915 100644 ---- a/sound/soc/bcm/hifiberry_amp.c -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -65,6 +65,12 @@ static struct snd_soc_card snd_rpi_hifiberry_amp = { - .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), - }; - -+static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-amp", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -+ - - static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) - { -@@ -72,6 +78,20 @@ static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) - - snd_rpi_hifiberry_amp.dev = &pdev->dev; - -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ - ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); - - if (ret != 0) { -@@ -92,6 +112,7 @@ static struct platform_driver snd_rpi_hifiberry_amp_driver = { - .driver = { - .name = "snd-hifiberry-amp", - .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_amp_of_match, - }, - .probe = snd_rpi_hifiberry_amp_probe, - .remove = snd_rpi_hifiberry_amp_remove, - -From 81042a79740e7b0c61fcbfa97e76c3d97c40b630 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 3 Feb 2015 11:41:38 +0000 -Subject: [PATCH 074/216] BCM270x_DT: Add i2c0_baudrate and i2c1_baudrate - parameters - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 3 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index b409c2c..7f84473 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -103,6 +103,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 1ecd1a1..a39562f 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -97,6 +97,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 46f4908..75c222f 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -103,6 +103,8 @@ - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; - i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; - - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - -From 4ff8b4c54db8215c8daa7a1d70c623b642143f16 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 4 Feb 2015 10:02:24 +0000 -Subject: [PATCH 075/216] pinctrl-bcm2835: bcm2835_gpio_direction_output must - set the value - ---- - drivers/pinctrl/pinctrl-bcm2835.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index 9d1149e..d9c727b 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -355,7 +355,14 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) - static int bcm2835_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) - { -- return pinctrl_gpio_direction_output(chip->base + offset); -+ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev); -+ int ret; -+ -+ ret = pinctrl_gpio_direction_output(chip->base + offset); -+ if (ret >= 0) -+ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset); -+ -+ return ret; - } - - static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) - -From 1184251f953b0cd578ee44fa36d67f7f9091e6a5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 4 Feb 2015 12:59:36 +0000 -Subject: [PATCH 076/216] w1-gpio: Sort out the pullup/parasitic power tangle - ---- - arch/arm/boot/dts/w1-gpio-overlay.dts | 4 +++- - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 6 +++-- - drivers/w1/masters/w1-gpio.c | 36 ++++++++++++++++++---------- - include/linux/w1-gpio.h | 1 + - 4 files changed, 32 insertions(+), 15 deletions(-) - -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -index b2c5ee2..29a3b48 100644 ---- a/arch/arm/boot/dts/w1-gpio-overlay.dts -+++ b/arch/arm/boot/dts/w1-gpio-overlay.dts -@@ -1,4 +1,4 @@ --// Definitions for lirc-rpi module -+// Definitions for w1-gpio module (without external pullup) - /dts-v1/; - /plugin/; - -@@ -14,6 +14,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&w1_pins>; - gpios = <&gpio 4 0>; -+ rpi,parasitic-power = <0>; - status = "okay"; - }; - }; -@@ -33,5 +34,6 @@ - __overrides__ { - gpiopin = <&w1>,"gpios:4", - <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; - }; - }; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -index b3e97c2..66a98f6 100644 ---- a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -+++ b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -@@ -1,4 +1,4 @@ --// Definitions for lirc-rpi module -+// Definitions for w1-gpio module (with external pullup) - /dts-v1/; - /plugin/; - -@@ -14,6 +14,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&w1_pins>; - gpios = <&gpio 4 0>, <&gpio 5 1>; -+ rpi,parasitic-power = <0>; - status = "okay"; - }; - }; -@@ -33,7 +34,8 @@ - __overrides__ { - gpiopin = <&w1>,"gpios:4", - <&w1_pins>,"brcm,pins:0"; -- pullup = <&w1>,"gpios:16", -+ extpullup = <&w1>,"gpios:16", - <&w1_pins>,"brcm,pins:4"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; - }; - }; -diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c -index 3ad15cc..e34d418 100644 ---- a/drivers/w1/masters/w1-gpio.c -+++ b/drivers/w1/masters/w1-gpio.c -@@ -23,10 +23,14 @@ - #include "../w1.h" - #include "../w1_int.h" - --static int w1_gpio_pullup = -1; --static int w1_gpio_pullup_orig = -1; -+static int w1_gpio_pullup = 0; -+static int w1_gpio_pullup_orig = 0; - module_param_named(pullup, w1_gpio_pullup, int, 0); --MODULE_PARM_DESC(pullup, "GPIO pin pullup number"); -+MODULE_PARM_DESC(pullup, "Enable parasitic power (power on data) mode"); -+static int w1_gpio_pullup_pin = -1; -+static int w1_gpio_pullup_pin_orig = -1; -+module_param_named(extpullup, w1_gpio_pullup_pin, int, 0); -+MODULE_PARM_DESC(extpullup, "GPIO external pullup pin number"); - static int w1_gpio_pin = -1; - static int w1_gpio_pin_orig = -1; - module_param_named(gpiopin, w1_gpio_pin, int, 0); -@@ -99,6 +103,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; - int gpio; -+ u32 value; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) -@@ -107,6 +112,9 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - if (of_get_property(np, "linux,open-drain", NULL)) - pdata->is_open_drain = 1; - -+ if (of_property_read_u32(np, "rpi,parasitic-power", &value) == 0) -+ pdata->parasitic_power = (value != 0); -+ - gpio = of_get_gpio(np, 0); - if (gpio < 0) { - if (gpio != -EPROBE_DEFER) -@@ -122,7 +130,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) - if (gpio == -EPROBE_DEFER) - return gpio; - /* ignore other errors as the pullup gpio is optional */ -- pdata->ext_pullup_enable_pin = gpio; -+ pdata->ext_pullup_enable_pin = (gpio >= 0) ? gpio : -1; - - pdev->dev.platform_data = pdata; - -@@ -158,17 +166,20 @@ static int w1_gpio_probe(struct platform_device *pdev) - } - - w1_gpio_pin_orig = pdata->pin; -- w1_gpio_pullup_orig = pdata->ext_pullup_enable_pin; -+ w1_gpio_pullup_pin_orig = pdata->ext_pullup_enable_pin; -+ w1_gpio_pullup_orig = pdata->parasitic_power; - - if(gpio_is_valid(w1_gpio_pin)) { - pdata->pin = w1_gpio_pin; - pdata->ext_pullup_enable_pin = -1; -+ pdata->parasitic_power = -1; - } -- if(gpio_is_valid(w1_gpio_pullup)) { -- pdata->ext_pullup_enable_pin = w1_gpio_pullup; -+ pdata->parasitic_power |= w1_gpio_pullup; -+ if(gpio_is_valid(w1_gpio_pullup_pin)) { -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin; - } - -- dev_info(&pdev->dev, "gpio pin %d, gpio pullup pin %d\n", pdata->pin, pdata->ext_pullup_enable_pin); -+ dev_info(&pdev->dev, "gpio pin %d, external pullup pin %d, parasitic power %d\n", pdata->pin, pdata->ext_pullup_enable_pin, pdata->parasitic_power); - - err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); - if (err) { -@@ -199,10 +210,10 @@ static int w1_gpio_probe(struct platform_device *pdev) - master->set_pullup = w1_gpio_set_pullup; - } - -- if (gpio_is_valid(w1_gpio_pullup)) { -+ if (pdata->parasitic_power) { - if (pdata->is_open_drain) -- printk(KERN_ERR "w1-gpio 'pullup' option " -- "doesn't work with open drain GPIO\n"); -+ printk(KERN_ERR "w1-gpio 'pullup'(parasitic power) " -+ "option doesn't work with open drain GPIO\n"); - else - master->bitbang_pullup = w1_gpio_bitbang_pullup; - } -@@ -238,7 +249,8 @@ static int w1_gpio_remove(struct platform_device *pdev) - w1_remove_master_device(master); - - pdata->pin = w1_gpio_pin_orig; -- pdata->ext_pullup_enable_pin = w1_gpio_pullup_orig; -+ pdata->ext_pullup_enable_pin = w1_gpio_pullup_pin_orig; -+ pdata->parasitic_power = w1_gpio_pullup_orig; - - return 0; - } -diff --git a/include/linux/w1-gpio.h b/include/linux/w1-gpio.h -index d58594a..feae942 100644 ---- a/include/linux/w1-gpio.h -+++ b/include/linux/w1-gpio.h -@@ -18,6 +18,7 @@ - struct w1_gpio_platform_data { - unsigned int pin; - unsigned int is_open_drain:1; -+ unsigned int parasitic_power:1; - void (*enable_external_pullup)(int enable); - unsigned int ext_pullup_enable_pin; - unsigned int pullup_duration; - -From a0d0e3ba49f5daa0ece5234cdf688fb490ee15a7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 5 Feb 2015 16:01:44 +0000 -Subject: [PATCH 077/216] i2c_bcm2708: Fix clock reference counting - ---- - drivers/i2c/busses/i2c-bcm2708.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 526129b..fda59ba 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -337,11 +337,17 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - return PTR_ERR(clk); - } - -+ err = clk_prepare_enable(clk); -+ if (err) { -+ dev_err(&pdev->dev, "could not enable clk: %d\n", err); -+ goto out_clk_put; -+ } -+ - bcm2708_i2c_init_pinmode(pdev->id); - - bi = kzalloc(sizeof(*bi), GFP_KERNEL); - if (!bi) -- goto out_clk_put; -+ goto out_clk_disable; - - platform_set_drvdata(pdev, bi); - -@@ -412,6 +418,8 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - iounmap(bi->base); - out_free_bi: - kfree(bi); -+out_clk_disable: -+ clk_disable_unprepare(clk); - out_clk_put: - clk_put(clk); - return err; -@@ -426,7 +434,7 @@ static int bcm2708_i2c_remove(struct platform_device *pdev) - i2c_del_adapter(&bi->adapter); - free_irq(bi->irq, bi); - iounmap(bi->base); -- clk_disable(bi->clk); -+ clk_disable_unprepare(bi->clk); - clk_put(bi->clk); - kfree(bi); - - -From dffb6179317e46f3f2d60c62b6b4c6c1008990ef Mon Sep 17 00:00:00 2001 -From: Byron Bradley -Date: Fri, 6 Feb 2015 14:19:41 +0000 -Subject: [PATCH 078/216] Add device-tree overlay for pcf2127 - -Signed-off-by: Byron Bradley ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pcf2127-rtc-overlay.dts | 22 ++++++++++++++++++++++ - 2 files changed, 23 insertions(+) - create mode 100644 arch/arm/boot/dts/pcf2127-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 7755a84..6cb743a 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -20,6 +20,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -new file mode 100644 -index 0000000..01fc81d ---- /dev/null -+++ b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF2127 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; - -From 6547e99ab9f5be7bc839f36becfc18e6dd879d0d Mon Sep 17 00:00:00 2001 -From: android -Date: Mon, 25 Aug 2014 13:18:21 +0100 -Subject: [PATCH 079/216] BCM2708_VCIO : Add automatic creation of device node - ---- - arch/arm/mach-bcm2708/vcio.c | 12 +++++++++++- - arch/arm/mach-bcm2709/vcio.c | 12 +++++++++++- - 2 files changed, 22 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 5e43e85..700bff4 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -61,7 +61,7 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de -- -+static struct class *vcio_class = NULL; - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -421,6 +421,13 @@ static int bcm_vcio_probe(struct platform_device *pdev) - "Failed registering the character device %d\n", ret); - return ret; - } -+ vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ return ret ; -+ } -+ device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); - } - return ret; - } -@@ -462,6 +469,9 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -+ device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -index 5e43e85..700bff4 100644 ---- a/arch/arm/mach-bcm2709/vcio.c -+++ b/arch/arm/mach-bcm2709/vcio.c -@@ -61,7 +61,7 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de -- -+static struct class *vcio_class = NULL; - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -421,6 +421,13 @@ static int bcm_vcio_probe(struct platform_device *pdev) - "Failed registering the character device %d\n", ret); - return ret; - } -+ vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ return ret ; -+ } -+ device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); - } - return ret; - } -@@ -462,6 +469,9 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -+ device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - - -From 05b37dedc10f2da009b868c101623c742eda1c3f Mon Sep 17 00:00:00 2001 -From: jeanleflambeur -Date: Sun, 1 Feb 2015 12:35:38 +0100 -Subject: [PATCH 080/216] Fix grabbing lock from atomic context in i2c driver - -2 main changes: -- check for timeouts in the bcm2708_bsc_setup function as indicated by this comment: - /* poll for transfer start bit (should only take 1-20 polls) */ - This implies that the setup function can now fail so account for this everywhere it's called -- Removed the clk_get_rate call from inside the setup function as it locks a mutex and that's not ok since we call it from under a spin lock. - -removed dead code and update comment - -fixed typo in comment ---- - drivers/i2c/busses/i2c-bcm2708.c | 90 +++++++++++++++++++++++++++++----------- - 1 file changed, 65 insertions(+), 25 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index fda59ba..81e9374 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -68,6 +68,7 @@ - #define BSC_S_TA 0x00000001 - - #define I2C_TIMEOUT_MS 150 -+#define I2C_WAIT_LOOP_COUNT 40 - - #define DRV_NAME "bcm2708_i2c" - -@@ -86,6 +87,7 @@ struct bcm2708_i2c { - void __iomem *base; - int irq; - struct clk *clk; -+ u32 cdiv; - - struct completion done; - -@@ -109,10 +111,10 @@ static void bcm2708_i2c_init_pinmode(int id) - int pin; - u32 *gpio = ioremap(GPIO_BASE, SZ_16K); - -- BUG_ON(id != 0 && id != 1); -+ BUG_ON(id != 0 && id != 1); - /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ - for (pin = id*2+0; pin <= id*2+1; pin++) { --printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); -+ printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); - INP_GPIO(pin); /* set mode to GPIO input first */ - SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ - } -@@ -151,16 +153,16 @@ static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) - bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); - } - --static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) -+static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi) - { -- unsigned long bus_hz; - u32 cdiv, s; - u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; -+ int wait_loops = I2C_WAIT_LOOP_COUNT; - -- bus_hz = clk_get_rate(bi->clk); -- cdiv = bus_hz / baudrate; -- if (cdiv > 0xffff) -- cdiv = 0xffff; -+ /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked. -+ * Use the value that we cached in the probe. -+ */ -+ cdiv = bi->cdiv; - - if (bi->msg->flags & I2C_M_RD) - c |= BSC_C_INTR | BSC_C_READ; -@@ -177,17 +179,25 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) - - Both messages to same slave address - - Write message can fit inside FIFO (16 bytes or less) */ - if ( (bi->nmsgs > 1) && -- !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -- (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { -+ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && -+ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { - /* Fill FIFO with entire write message (16 byte FIFO) */ -- while (bi->pos < bi->msg->len) -+ while (bi->pos < bi->msg->len) { - bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); -+ } - /* Start write transfer (no interrupts, don't clear FIFO) */ - bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); -+ - /* poll for transfer start bit (should only take 1-20 polls) */ - do { - s = bcm2708_rd(bi, BSC_S); -- } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE))); -+ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0); -+ -+ /* did we time out or some error occured? */ -+ if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) { -+ return -1; -+ } -+ - /* Send next read message before the write transfer finishes. */ - bi->nmsgs--; - bi->msg++; -@@ -197,6 +207,8 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) - } - } - bcm2708_wr(bi, BSC_C, c); -+ -+ return 0; - } - - static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) -@@ -204,13 +216,15 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - struct bcm2708_i2c *bi = dev_id; - bool handled = true; - u32 s; -+ int ret; - - spin_lock(&bi->lock); - - /* we may see camera interrupts on the "other" I2C channel -- Just return if we've not sent anything */ -- if (!bi->nmsgs || !bi->msg ) -+ Just return if we've not sent anything */ -+ if (!bi->nmsgs || !bi->msg) { - goto early_exit; -+ } - - s = bcm2708_rd(bi, BSC_S); - -@@ -218,13 +232,16 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - bcm2708_bsc_reset(bi); - bi->error = true; - -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; - /* wake up our bh */ - complete(&bi->done); - } else if (s & BSC_S_DONE) { - bi->nmsgs--; - -- if (bi->msg->flags & I2C_M_RD) -+ if (bi->msg->flags & I2C_M_RD) { - bcm2708_bsc_fifo_drain(bi); -+ } - - bcm2708_bsc_reset(bi); - -@@ -232,8 +249,19 @@ static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) - /* advance to next message */ - bi->msg++; - bi->pos = 0; -- bcm2708_bsc_setup(bi); -+ ret = bcm2708_bsc_setup(bi); -+ if (ret < 0) { -+ bcm2708_bsc_reset(bi); -+ bi->error = true; -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; -+ /* wake up our bh */ -+ complete(&bi->done); -+ goto early_exit; -+ } - } else { -+ bi->msg = 0; /* to inform the that all work is done */ -+ bi->nmsgs = 0; - /* wake up our bh */ - complete(&bi->done); - } -@@ -266,22 +294,33 @@ static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, - bi->nmsgs = num; - bi->error = false; - -- bcm2708_bsc_setup(bi); -+ ret = bcm2708_bsc_setup(bi); - -- /* unlockig _after_ the setup to avoid races with the interrupt routine */ - spin_unlock_irqrestore(&bi->lock, flags); - -- ret = wait_for_completion_timeout(&bi->done, -- msecs_to_jiffies(I2C_TIMEOUT_MS)); -+ /* check the result of the setup */ -+ if (ret < 0) -+ { -+ dev_err(&adap->dev, "transfer setup timed out\n"); -+ goto error_timeout; -+ } -+ -+ ret = wait_for_completion_timeout(&bi->done, msecs_to_jiffies(I2C_TIMEOUT_MS)); - if (ret == 0) { - dev_err(&adap->dev, "transfer timed out\n"); -- spin_lock_irqsave(&bi->lock, flags); -- bcm2708_bsc_reset(bi); -- spin_unlock_irqrestore(&bi->lock, flags); -- return -ETIMEDOUT; -+ goto error_timeout; - } - -- return bi->error ? -EIO : num; -+ ret = bi->error ? -EIO : num; -+ return ret; -+ -+error_timeout: -+ spin_lock_irqsave(&bi->lock, flags); -+ bcm2708_bsc_reset(bi); -+ bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */ -+ bi->nmsgs = 0; -+ spin_unlock_irqrestore(&bi->lock, flags); -+ return -ETIMEDOUT; - } - - static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) -@@ -406,6 +445,7 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - cdiv = 0xffff; - baudrate = bus_hz / cdiv; - } -+ bi->cdiv = cdiv; - - dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", - pdev->id, (unsigned long)regs->start, irq, baudrate); - -From 2e3d8378c9031150eda4fd030b14d6c4ea762786 Mon Sep 17 00:00:00 2001 +From a69146643bae1215ab2860b9646f0f380bd3c50f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Feb 2015 11:17:53 +0000 -Subject: [PATCH 081/216] Fix LED "input" trigger implementation for 3.19 +Subject: [PATCH 56/77] Fix LED "input" trigger implementation for 3.19 --- drivers/leds/leds-gpio.c | 10 +++++++++- @@ -125629,7 +127697,7 @@ Subject: [PATCH 081/216] Fix LED "input" trigger implementation for 3.19 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index d26af0a..9e49c72 100644 +index 15eb3f8..3cfbd6a 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -41,6 +41,13 @@ static void gpio_led_work(struct work_struct *work) @@ -125693,13 +127761,13 @@ index 2ca2b98..07d1219 100644 static struct led_trigger input_led_trigger = { diff --git a/include/linux/leds.h b/include/linux/leds.h -index f70f84f..f3fcaa1 100644 +index 9a2b000..60accc5 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -48,6 +48,9 @@ struct led_classdev { +@@ -47,6 +47,9 @@ struct led_classdev { + #define SET_BRIGHTNESS_ASYNC (1 << 21) #define SET_BRIGHTNESS_SYNC (1 << 22) #define LED_DEV_CAP_FLASH (1 << 23) - #define LED_DEV_CAP_SYNC_STROBE (1 << 24) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT (1 << 30) +#define SET_GPIO_OUTPUT (1 << 31) @@ -125707,65 +127775,67 @@ index f70f84f..f3fcaa1 100644 /* Set LED brightness level */ /* Must not sleep, use a workqueue if needed */ -From 9bdca5da4acd1e4893a10183c0202b2b1293b9cd Mon Sep 17 00:00:00 2001 -From: Rainer Herbers -Date: Sun, 15 Feb 2015 13:44:14 +0100 -Subject: [PATCH 082/216] Create bmp085_i2c-sensor-overlay.dts and update - Makefile +From d8f6c527b14c125e58173e8bd0e7c6c59bab4919 Mon Sep 17 00:00:00 2001 +From: notro +Date: Thu, 10 Jul 2014 13:59:47 +0200 +Subject: [PATCH 57/77] pinctrl-bcm2835: Set base to 0 give expected gpio + numbering + +Signed-off-by: Noralf Tronnes +--- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 8d908e3..7a1900d 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -382,7 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = { + .get = bcm2835_gpio_get, + .set = bcm2835_gpio_set, + .to_irq = bcm2835_gpio_to_irq, +- .base = -1, ++ .base = 0, + .ngpio = BCM2835_NUM_GPIOS, + .can_sleep = false, + }; + +From bf8c97c74733237b219a22da649cb6cb7029615d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 4 Feb 2015 10:02:24 +0000 +Subject: [PATCH 58/77] pinctrl-bcm2835: bcm2835_gpio_direction_output must set + the value --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts | 23 +++++++++++++++++++++++ - 2 files changed, 24 insertions(+) - create mode 100644 arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 6cb743a..7946143 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 7a1900d..62f85aa 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -355,7 +355,14 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) + static int bcm2835_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) + { +- return pinctrl_gpio_direction_output(chip->base + offset); ++ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev); ++ int ret; ++ ++ ret = pinctrl_gpio_direction_output(chip->base + offset); ++ if (ret >= 0) ++ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset); ++ ++ return ret; + } -+dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -diff --git a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -new file mode 100644 -index 0000000..b830bf2 ---- /dev/null -+++ b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -@@ -0,0 +1,23 @@ -+// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; + static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -From 92765161f74e60edf1eb2c752f2cd3ea9d531d14 Mon Sep 17 00:00:00 2001 +From 1262602778ac5adbe798e7ace41b22262a578fcf Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 083/216] pinctrl-bcm2835: Fix interrupt handling for GPIOs - 28-31 and 46-53 +Subject: [PATCH 59/77] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 + and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has four interrupt lines - one each for the three IRQ groups and one common. Rather @@ -125781,13 +127851,13 @@ This bug has only just been observed because GPIOs above 27 can only be accessed on an old Raspberry Pi with the optional P5 header fitted, where the pins are often used for I2S instead. --- - drivers/pinctrl/pinctrl-bcm2835.c | 51 ++++++++++++++++++++++++++++++--------- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 51 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index d9c727b..ae68710 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 62f85aa..c7cf266 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 @@ -125842,9 +127912,9 @@ index d9c727b..ae68710 100644 events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; -@@ -420,7 +420,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) - if (type & IRQ_TYPE_LEVEL_MASK) - bcm2835_gpio_set_bit(pc, GPEDS0, gpio); +@@ -412,7 +412,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) + + generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } - return events ? IRQ_HANDLED : IRQ_NONE; + @@ -125874,7 +127944,7 @@ index d9c727b..ae68710 100644 } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, -@@ -992,8 +1015,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1000,8 +1023,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; @@ -125883,7 +127953,7 @@ index d9c727b..ae68710 100644 /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); -@@ -1008,10 +1029,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1016,10 +1037,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); @@ -125901,7 +127971,7 @@ index d9c727b..ae68710 100644 len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); -@@ -1069,6 +1095,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { +@@ -1077,6 +1103,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { .remove = bcm2835_pinctrl_remove, .driver = { .name = MODULE_NAME, @@ -125910,11 +127980,11 @@ index d9c727b..ae68710 100644 }, }; -From d1f5e57c873c1acf3be524693888af970a08f4fb Mon Sep 17 00:00:00 2001 +From fd7e740e1c83bd550444192a8beff54ea5291c50 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 084/216] pinctrl-bcm2835: Only request the interrupts listed - in the DTB +Subject: [PATCH 60/77] pinctrl-bcm2835: Only request the interrupts listed in + the DTB Although the GPIO controller can generate three interrupts (four counting the common one), the device tree files currently only specify two. In the @@ -125923,14 +127993,14 @@ registering 0), which has the effect of making it impossible to generate interrupts for GPIOs 46-53 which, since they share pins with the SD card interface, is unlikely to be a problem. --- - drivers/pinctrl/pinctrl-bcm2835.c | 2 ++ + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c -index ae68710..87b7a4a 100644 ---- a/drivers/pinctrl/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/pinctrl-bcm2835.c -@@ -1036,6 +1036,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index c7cf266..986779a 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -1044,6 +1044,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int len; char *name; pc->irq[i] = irq_of_parse_and_map(np, i); @@ -125940,1282 +128010,16 @@ index ae68710..87b7a4a 100644 pc->irq_data[i].irqgroup = i; -From a10a9f8313c8fff626c82bf63608f3f00188c5db Mon Sep 17 00:00:00 2001 -From: Dave Martin -Date: Fri, 27 Feb 2015 15:51:37 +0000 -Subject: [PATCH 085/216] serial/amba-pl011: Activate TX IRQ passively - -The current PL011 driver transmits a dummy character when the UART -is opened, to assert the TX IRQ for the first time -(see pl011_startup()). The UART is put in loopback mode temporarily, -so the receiver presumably shouldn't see anything. - -However... - -At least some platforms containing a PL011 send characters down the -wire even when loopback mode is enabled. This means that a -spurious NUL character may be seen at the receiver when the PL011 is -opened through the TTY layer. - -The current code also temporarily sets the baud rate to maximum and -the character width to the minimum, to that the dummy TX completes -as quickly as possible. If this is seen by the receiver it will -result in a framing error and can knock the receiver out of sync -- -turning subsequent output into garbage until synchronisation -is reestablished. (Particularly problematic during boot with systemd.) - -To avoid spurious transmissions, this patch removes assumptions about -whether the TX IRQ will fire until at least one TX IRQ has been seen. - -Instead, the UART will unmask the TX IRQ and then slow-start via -polling and timer-based soft IRQs initially. If the TTY layer writes -enough data to fill the FIFO to the interrupt threshold in one go, -the TX IRQ should assert, at which point the driver changes to -fully interrupt-driven TX. - -In this way, the TX IRQ is activated as a side-effect instead of -being done deliberately. - -This should also mean that the driver works on the SBSA Generic -UART[1] (a cut-down PL011) without invasive changes. The Generic -UART lacks some features needed for the dummy TX approach to work -(FIFO disabling and loopback). - -[1] Server Base System Architecture (ARM-DEN-0029-v2.3) - http://infocenter.arm.com/ - (click-thru required :/) - -Signed-off-by: Dave Martin ---- - drivers/tty/serial/amba-pl011.c | 165 ++++++++++++++++++++++++++++------------ - 1 file changed, 115 insertions(+), 50 deletions(-) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 16ca535..c243729 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include - - #define UART_NR 14 - -@@ -156,7 +157,9 @@ struct uart_amba_port { - unsigned int lcrh_tx; /* vendor-specific */ - unsigned int lcrh_rx; /* vendor-specific */ - unsigned int old_cr; /* state during shutdown */ -+ struct delayed_work tx_softirq_work; - bool autorts; -+ unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */ - char type[12]; - #ifdef CONFIG_DMA_ENGINE - /* DMA stuff */ -@@ -440,8 +443,9 @@ static void pl011_dma_remove(struct uart_amba_port *uap) - dma_release_channel(uap->dmarx.chan); - } - --/* Forward declare this for the refill routine */ -+/* Forward declare these for the refill routine */ - static int pl011_dma_tx_refill(struct uart_amba_port *uap); -+static void pl011_start_tx_pio(struct uart_amba_port *uap); - - /* - * The current DMA TX buffer has been sent. -@@ -479,14 +483,13 @@ static void pl011_dma_tx_callback(void *data) - return; - } - -- if (pl011_dma_tx_refill(uap) <= 0) { -+ if (pl011_dma_tx_refill(uap) <= 0) - /* - * We didn't queue a DMA buffer for some reason, but we - * have data pending to be sent. Re-enable the TX IRQ. - */ -- uap->im |= UART011_TXIM; -- writew(uap->im, uap->port.membase + UART011_IMSC); -- } -+ pl011_start_tx_pio(uap); -+ - spin_unlock_irqrestore(&uap->port.lock, flags); - } - -@@ -664,12 +667,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap) - if (!uap->dmatx.queued) { - if (pl011_dma_tx_refill(uap) > 0) { - uap->im &= ~UART011_TXIM; -- ret = true; -- } else { -- uap->im |= UART011_TXIM; -+ writew(uap->im, uap->port.membase + -+ UART011_IMSC); -+ } else - ret = false; -- } -- writew(uap->im, uap->port.membase + UART011_IMSC); - } else if (!(uap->dmacr & UART011_TXDMAE)) { - uap->dmacr |= UART011_TXDMAE; - writew(uap->dmacr, -@@ -1208,15 +1209,24 @@ static void pl011_stop_tx(struct uart_port *port) - pl011_dma_tx_stop(uap); - } - -+static bool pl011_tx_chars(struct uart_amba_port *uap); -+ -+/* Start TX with programmed I/O only (no DMA) */ -+static void pl011_start_tx_pio(struct uart_amba_port *uap) -+{ -+ uap->im |= UART011_TXIM; -+ writew(uap->im, uap->port.membase + UART011_IMSC); -+ if (!uap->tx_irq_seen) -+ pl011_tx_chars(uap); -+} -+ - static void pl011_start_tx(struct uart_port *port) - { - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); - -- if (!pl011_dma_tx_start(uap)) { -- uap->im |= UART011_TXIM; -- writew(uap->im, uap->port.membase + UART011_IMSC); -- } -+ if (!pl011_dma_tx_start(uap)) -+ pl011_start_tx_pio(uap); - } - - static void pl011_stop_rx(struct uart_port *port) -@@ -1274,40 +1284,87 @@ __acquires(&uap->port.lock) - spin_lock(&uap->port.lock); - } - --static void pl011_tx_chars(struct uart_amba_port *uap) -+/* -+ * Transmit a character -+ * There must be at least one free entry in the TX FIFO to accept the char. -+ * -+ * Returns true if the FIFO might have space in it afterwards; -+ * returns false if the FIFO definitely became full. -+ */ -+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c) -+{ -+ writew(c, uap->port.membase + UART01x_DR); -+ uap->port.icount.tx++; -+ -+ if (likely(uap->tx_irq_seen > 1)) -+ return true; -+ -+ return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF); -+} -+ -+static bool pl011_tx_chars(struct uart_amba_port *uap) - { - struct circ_buf *xmit = &uap->port.state->xmit; - int count; - -+ if (unlikely(uap->tx_irq_seen < 2)) -+ /* -+ * Initial FIFO fill level unknown: we must check TXFF -+ * after each write, so just try to fill up the FIFO. -+ */ -+ count = uap->fifosize; -+ else /* tx_irq_seen >= 2 */ -+ /* -+ * FIFO initially at least half-empty, so we can simply -+ * write half the FIFO without polling TXFF. -+ -+ * Note: the *first* TX IRQ can still race with -+ * pl011_start_tx_pio(), which can result in the FIFO -+ * being fuller than expected in that case. -+ */ -+ count = uap->fifosize >> 1; -+ -+ /* -+ * If the FIFO is full we're guaranteed a TX IRQ at some later point, -+ * and can't transmit immediately in any case: -+ */ -+ if (unlikely(uap->tx_irq_seen < 2 && -+ readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)) -+ return false; -+ - if (uap->port.x_char) { -- writew(uap->port.x_char, uap->port.membase + UART01x_DR); -- uap->port.icount.tx++; -+ pl011_tx_char(uap, uap->port.x_char); - uap->port.x_char = 0; -- return; -+ --count; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl011_stop_tx(&uap->port); -- return; -+ goto done; - } - - /* If we are using DMA mode, try to send some characters. */ - if (pl011_dma_tx_irq(uap)) -- return; -+ goto done; - -- count = uap->fifosize >> 1; -- do { -- writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); -+ while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) { - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -- uap->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; -- } while (--count > 0); -+ } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uap->port); - -- if (uart_circ_empty(xmit)) -+ if (uart_circ_empty(xmit)) { - pl011_stop_tx(&uap->port); -+ goto done; -+ } -+ -+ if (unlikely(!uap->tx_irq_seen)) -+ schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout); -+ -+done: -+ return false; - } - - static void pl011_modem_status(struct uart_amba_port *uap) -@@ -1334,6 +1391,28 @@ static void pl011_modem_status(struct uart_amba_port *uap) - wake_up_interruptible(&uap->port.state->port.delta_msr_wait); - } - -+static void pl011_tx_softirq(struct work_struct *work) -+{ -+ struct delayed_work *dwork = to_delayed_work(work); -+ struct uart_amba_port *uap = -+ container_of(dwork, struct uart_amba_port, tx_softirq_work); -+ -+ spin_lock(&uap->port.lock); -+ while (pl011_tx_chars(uap)) ; -+ spin_unlock(&uap->port.lock); -+} -+ -+static void pl011_tx_irq_seen(struct uart_amba_port *uap) -+{ -+ if (likely(uap->tx_irq_seen > 1)) -+ return; -+ -+ uap->tx_irq_seen++; -+ if (uap->tx_irq_seen < 2) -+ /* first TX IRQ */ -+ cancel_delayed_work(&uap->tx_softirq_work); -+} -+ - static irqreturn_t pl011_int(int irq, void *dev_id) - { - struct uart_amba_port *uap = dev_id; -@@ -1372,8 +1451,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id) - if (status & (UART011_DSRMIS|UART011_DCDMIS| - UART011_CTSMIS|UART011_RIMIS)) - pl011_modem_status(uap); -- if (status & UART011_TXIS) -+ if (status & UART011_TXIS) { -+ pl011_tx_irq_seen(uap); - pl011_tx_chars(uap); -+ } - - if (pass_counter-- == 0) - break; -@@ -1577,7 +1658,7 @@ static int pl011_startup(struct uart_port *port) - { - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); -- unsigned int cr, lcr_h, fbrd, ibrd; -+ unsigned int cr; - int retval; - - retval = pl011_hwinit(port); -@@ -1595,29 +1676,10 @@ static int pl011_startup(struct uart_port *port) - - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); - -- /* -- * Provoke TX FIFO interrupt into asserting. Taking care to preserve -- * baud rate and data format specified by FBRD, IBRD and LCRH as the -- * UART may already be in use as a console. -- */ -- spin_lock_irq(&uap->port.lock); -- -- fbrd = readw(uap->port.membase + UART011_FBRD); -- ibrd = readw(uap->port.membase + UART011_IBRD); -- lcr_h = readw(uap->port.membase + uap->lcrh_rx); -- -- cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; -- writew(cr, uap->port.membase + UART011_CR); -- writew(0, uap->port.membase + UART011_FBRD); -- writew(1, uap->port.membase + UART011_IBRD); -- pl011_write_lcr_h(uap, 0); -- writew(0, uap->port.membase + UART01x_DR); -- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) -- barrier(); -+ /* Assume that TX IRQ doesn't work until we see one: */ -+ uap->tx_irq_seen = 0; - -- writew(fbrd, uap->port.membase + UART011_FBRD); -- writew(ibrd, uap->port.membase + UART011_IBRD); -- pl011_write_lcr_h(uap, lcr_h); -+ spin_lock_irq(&uap->port.lock); - - /* restore RTS and DTR */ - cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); -@@ -1672,6 +1734,8 @@ static void pl011_shutdown(struct uart_port *port) - container_of(port, struct uart_amba_port, port); - unsigned int cr; - -+ cancel_delayed_work_sync(&uap->tx_softirq_work); -+ - /* - * disable all interrupts - */ -@@ -2218,6 +2282,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) - uap->port.ops = &amba_pl011_pops; - uap->port.flags = UPF_BOOT_AUTOCONF; - uap->port.line = i; -+ INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq); - pl011_dma_probe(&dev->dev, uap); - - /* Ensure interrupts from this UART are masked and cleared */ - -From 75d9fae636d84117aa46cf0c2dcc556d02d67aca Mon Sep 17 00:00:00 2001 -From: Dave Martin -Date: Wed, 1 Apr 2015 14:08:31 +0100 -Subject: [PATCH 086/216] serial/amba-pl011: Refactor and simplify TX FIFO - handling - -Commit 734745c serial/amba-pl011: Activate TX IRQ passively -adds some complexity and overhead in the form of a softirq -mechanism for transmitting in the absence of interrupts. - -This patch simplifies the code flow to reduce the reliance on -subtle behaviour and avoid fragility under future maintenance. - -To this end, the TX softirq mechanism is removed and instead -pl011_start_tx() will now simply stuff the FIFO until full -(guaranteeing future TX IRQs), or until there are no more chars -to write (in which case we don't care whether an IRQ happens). - -Signed-off-by: Dave Martin -Signed-off-by: Jakub Kicinski ---- - drivers/tty/serial/amba-pl011.c | 119 +++++++++------------------------------- - 1 file changed, 26 insertions(+), 93 deletions(-) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index c243729..e32f4d7 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -58,7 +58,6 @@ - #include - #include - #include --#include - - #define UART_NR 14 - -@@ -157,9 +156,7 @@ struct uart_amba_port { - unsigned int lcrh_tx; /* vendor-specific */ - unsigned int lcrh_rx; /* vendor-specific */ - unsigned int old_cr; /* state during shutdown */ -- struct delayed_work tx_softirq_work; - bool autorts; -- unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */ - char type[12]; - #ifdef CONFIG_DMA_ENGINE - /* DMA stuff */ -@@ -1209,15 +1206,14 @@ static void pl011_stop_tx(struct uart_port *port) - pl011_dma_tx_stop(uap); - } - --static bool pl011_tx_chars(struct uart_amba_port *uap); -+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq); - - /* Start TX with programmed I/O only (no DMA) */ - static void pl011_start_tx_pio(struct uart_amba_port *uap) - { - uap->im |= UART011_TXIM; - writew(uap->im, uap->port.membase + UART011_IMSC); -- if (!uap->tx_irq_seen) -- pl011_tx_chars(uap); -+ pl011_tx_chars(uap, false); - } - - static void pl011_start_tx(struct uart_port *port) -@@ -1284,87 +1280,54 @@ __acquires(&uap->port.lock) - spin_lock(&uap->port.lock); - } - --/* -- * Transmit a character -- * There must be at least one free entry in the TX FIFO to accept the char. -- * -- * Returns true if the FIFO might have space in it afterwards; -- * returns false if the FIFO definitely became full. -- */ --static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c) -+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, -+ bool from_irq) - { -+ if (unlikely(!from_irq) && -+ readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) -+ return false; /* unable to transmit character */ -+ - writew(c, uap->port.membase + UART01x_DR); - uap->port.icount.tx++; - -- if (likely(uap->tx_irq_seen > 1)) -- return true; -- -- return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF); -+ return true; - } - --static bool pl011_tx_chars(struct uart_amba_port *uap) -+static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) - { - struct circ_buf *xmit = &uap->port.state->xmit; -- int count; -- -- if (unlikely(uap->tx_irq_seen < 2)) -- /* -- * Initial FIFO fill level unknown: we must check TXFF -- * after each write, so just try to fill up the FIFO. -- */ -- count = uap->fifosize; -- else /* tx_irq_seen >= 2 */ -- /* -- * FIFO initially at least half-empty, so we can simply -- * write half the FIFO without polling TXFF. -- -- * Note: the *first* TX IRQ can still race with -- * pl011_start_tx_pio(), which can result in the FIFO -- * being fuller than expected in that case. -- */ -- count = uap->fifosize >> 1; -- -- /* -- * If the FIFO is full we're guaranteed a TX IRQ at some later point, -- * and can't transmit immediately in any case: -- */ -- if (unlikely(uap->tx_irq_seen < 2 && -- readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)) -- return false; -+ int count = uap->fifosize >> 1; - - if (uap->port.x_char) { -- pl011_tx_char(uap, uap->port.x_char); -+ if (!pl011_tx_char(uap, uap->port.x_char, from_irq)) -+ return; - uap->port.x_char = 0; - --count; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl011_stop_tx(&uap->port); -- goto done; -+ return; - } - - /* If we are using DMA mode, try to send some characters. */ - if (pl011_dma_tx_irq(uap)) -- goto done; -+ return; - -- while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) { -- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -- if (uart_circ_empty(xmit)) -+ do { -+ if (likely(from_irq) && count-- == 0) - break; -- } -+ -+ if (!pl011_tx_char(uap, xmit->buf[xmit->tail], from_irq)) -+ break; -+ -+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); -+ } while (!uart_circ_empty(xmit)); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uap->port); - -- if (uart_circ_empty(xmit)) { -+ if (uart_circ_empty(xmit)) - pl011_stop_tx(&uap->port); -- goto done; -- } -- -- if (unlikely(!uap->tx_irq_seen)) -- schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout); -- --done: -- return false; - } - - static void pl011_modem_status(struct uart_amba_port *uap) -@@ -1391,28 +1354,6 @@ static void pl011_modem_status(struct uart_amba_port *uap) - wake_up_interruptible(&uap->port.state->port.delta_msr_wait); - } - --static void pl011_tx_softirq(struct work_struct *work) --{ -- struct delayed_work *dwork = to_delayed_work(work); -- struct uart_amba_port *uap = -- container_of(dwork, struct uart_amba_port, tx_softirq_work); -- -- spin_lock(&uap->port.lock); -- while (pl011_tx_chars(uap)) ; -- spin_unlock(&uap->port.lock); --} -- --static void pl011_tx_irq_seen(struct uart_amba_port *uap) --{ -- if (likely(uap->tx_irq_seen > 1)) -- return; -- -- uap->tx_irq_seen++; -- if (uap->tx_irq_seen < 2) -- /* first TX IRQ */ -- cancel_delayed_work(&uap->tx_softirq_work); --} -- - static irqreturn_t pl011_int(int irq, void *dev_id) - { - struct uart_amba_port *uap = dev_id; -@@ -1451,10 +1392,8 @@ static irqreturn_t pl011_int(int irq, void *dev_id) - if (status & (UART011_DSRMIS|UART011_DCDMIS| - UART011_CTSMIS|UART011_RIMIS)) - pl011_modem_status(uap); -- if (status & UART011_TXIS) { -- pl011_tx_irq_seen(uap); -- pl011_tx_chars(uap); -- } -+ if (status & UART011_TXIS) -+ pl011_tx_chars(uap, true); - - if (pass_counter-- == 0) - break; -@@ -1676,9 +1615,6 @@ static int pl011_startup(struct uart_port *port) - - writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); - -- /* Assume that TX IRQ doesn't work until we see one: */ -- uap->tx_irq_seen = 0; -- - spin_lock_irq(&uap->port.lock); - - /* restore RTS and DTR */ -@@ -1734,8 +1670,6 @@ static void pl011_shutdown(struct uart_port *port) - container_of(port, struct uart_amba_port, port); - unsigned int cr; - -- cancel_delayed_work_sync(&uap->tx_softirq_work); -- - /* - * disable all interrupts - */ -@@ -2282,7 +2216,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) - uap->port.ops = &amba_pl011_pops; - uap->port.flags = UPF_BOOT_AUTOCONF; - uap->port.line = i; -- INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq); - pl011_dma_probe(&dev->dev, uap); - - /* Ensure interrupts from this UART are masked and cleared */ - -From 29cd864c0ec9d9d593e569ee5d4fcb463d36cb35 Mon Sep 17 00:00:00 2001 -From: Jon Burgess -Date: Tue, 17 Feb 2015 13:22:17 +0000 -Subject: [PATCH 087/216] Create generic i2c-rtc overlay for supporting ds1307, - ds3231, pcf2127 and pcf8523. - -Signed-off-by: Jon Burgess ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/i2c-rtc-overlay.dts | 43 +++++++++++++++++++++++++++++++++++ - 2 files changed, 44 insertions(+) - create mode 100644 arch/arm/boot/dts/i2c-rtc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 7946143..6753fcb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -14,6 +14,7 @@ endif - - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -diff --git a/arch/arm/boot/dts/i2c-rtc-overlay.dts b/arch/arm/boot/dts/i2c-rtc-overlay.dts -new file mode 100644 -index 0000000..5d5abb1 ---- /dev/null -+++ b/arch/arm/boot/dts/i2c-rtc-overlay.dts -@@ -0,0 +1,43 @@ -+// Definitions for several I2C based Real Time Clocks -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ ds3231: ds3231@68 { -+ compatible = "maxim,ds3231"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf2127: pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ pcf8523: pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ __overrides__ { -+ ds1307 = <&ds1307>,"status"; -+ ds3231 = <&ds3231>,"status"; -+ pcf2127 = <&pcf2127>,"status"; -+ pcf8523 = <&pcf8523>,"status"; -+ }; -+}; - -From 600d5e0e89ecc723b7ffb29209b058d0275502e2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:24:05 +0100 -Subject: [PATCH 088/216] dts: overlay: add support for rpi-display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for rpi-display by Watterott. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-display-overlay.dts | 81 +++++++++++++++++++++++++++++++ - 2 files changed, 82 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-display-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 6753fcb..de47748 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -25,6 +25,7 @@ dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -new file mode 100644 -index 0000000..0578810 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-display-overlay.dts -@@ -0,0 +1,81 @@ -+/* -+ * Device Tree overlay for rpi-display by Watterott -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ rpi_display_pins: rpi_display_pins { -+ brcm,pins = <18 23 24 25>; -+ brcm,function = <1 1 1 0>; /* out out out in */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rpidisplay: rpi-display@0{ -+ compatible = "ilitek,ili9341"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rpi_display_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ reset-gpios = <&gpio 23 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ rpidisplay_ts: rpi-display-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <25 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 25 0>; -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&rpidisplay>,"spi-max-frequency:0"; -+ rotate = <&rpidisplay>,"rotate:0"; -+ fps = <&rpidisplay>,"fps:0"; -+ debug = <&rpidisplay>,"debug:0"; -+ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From 525949ace298ff41d93fc2025ac768654e745642 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:36:27 +0100 -Subject: [PATCH 089/216] dts: overlay: add support for HY28A display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for HY28A display by HAOYU Electronics. -Default values are set to match Texy's display shield. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hy28a-overlay.dts | 87 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 88 insertions(+) - create mode 100644 arch/arm/boot/dts/hy28a-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index de47748..8d7e535 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -19,6 +19,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hy28a-overlay.dts b/arch/arm/boot/dts/hy28a-overlay.dts -new file mode 100644 -index 0000000..3cd3083 ---- /dev/null -+++ b/arch/arm/boot/dts/hy28a-overlay.dts -@@ -0,0 +1,87 @@ -+/* -+ * Device Tree overlay for HY28A display -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28a_pins: hy28a_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28a: hy28a@0{ -+ compatible = "ilitek,ili9320"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28a_pins>; -+ -+ spi-max-frequency = <32000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ hy28a_ts: hy28a-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28a>,"spi-max-frequency:0"; -+ rotate = <&hy28a>,"rotate:0"; -+ fps = <&hy28a>,"fps:0"; -+ debug = <&hy28a>,"debug:0"; -+ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28a>,"reset-gpios:4", -+ <&hy28a_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28a>,"led-gpios:4", -+ <&hy28a_pins>, "brcm,pins:2"; -+ }; -+}; - -From 131c6ba7b078b8536755c8cae2e31c09053b5804 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:38:00 +0100 -Subject: [PATCH 090/216] dts: overlay: add support for HY28B display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for HY28B display by HAOYU Electronics. -Default values are set to match Texy's display shield. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/hy28b-overlay.dts | 142 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 143 insertions(+) - create mode 100644 arch/arm/boot/dts/hy28b-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 8d7e535..ec26431b1 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -20,6 +20,7 @@ dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -diff --git a/arch/arm/boot/dts/hy28b-overlay.dts b/arch/arm/boot/dts/hy28b-overlay.dts -new file mode 100644 -index 0000000..f774c4a ---- /dev/null -+++ b/arch/arm/boot/dts/hy28b-overlay.dts -@@ -0,0 +1,142 @@ -+/* -+ * Device Tree overlay for HY28b display shield by Texy -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28b_pins: hy28b_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28b: hy28b@0{ -+ compatible = "ilitek,ili9325"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28b_pins>; -+ -+ spi-max-frequency = <48000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ -+ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -+ -+ init = <0x10000e7 0x0010 -+ 0x1000000 0x0001 -+ 0x1000001 0x0100 -+ 0x1000002 0x0700 -+ 0x1000003 0x1030 -+ 0x1000004 0x0000 -+ 0x1000008 0x0207 -+ 0x1000009 0x0000 -+ 0x100000a 0x0000 -+ 0x100000c 0x0001 -+ 0x100000d 0x0000 -+ 0x100000f 0x0000 -+ 0x1000010 0x0000 -+ 0x1000011 0x0007 -+ 0x1000012 0x0000 -+ 0x1000013 0x0000 -+ 0x2000032 -+ 0x1000010 0x1590 -+ 0x1000011 0x0227 -+ 0x2000032 -+ 0x1000012 0x009c -+ 0x2000032 -+ 0x1000013 0x1900 -+ 0x1000029 0x0023 -+ 0x100002b 0x000e -+ 0x2000032 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000032 -+ 0x1000050 0x0000 -+ 0x1000051 0x00ef -+ 0x1000052 0x0000 -+ 0x1000053 0x013f -+ 0x1000060 0xa700 -+ 0x1000061 0x0001 -+ 0x100006a 0x0000 -+ 0x1000080 0x0000 -+ 0x1000081 0x0000 -+ 0x1000082 0x0000 -+ 0x1000083 0x0000 -+ 0x1000084 0x0000 -+ 0x1000085 0x0000 -+ 0x1000090 0x0010 -+ 0x1000092 0x0000 -+ 0x1000093 0x0003 -+ 0x1000095 0x0110 -+ 0x1000097 0x0000 -+ 0x1000098 0x0000 -+ 0x1000007 0x0133 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000064>; -+ debug = <0>; -+ }; -+ -+ hy28b_ts: hy28b-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28b>,"spi-max-frequency:0"; -+ rotate = <&hy28b>,"rotate:0"; -+ fps = <&hy28b>,"fps:0"; -+ debug = <&hy28b>,"debug:0"; -+ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28b>,"reset-gpios:4", -+ <&hy28b_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28b>,"led-gpios:4", -+ <&hy28b_pins>, "brcm,pins:2"; -+ }; -+}; - -From 33ce6c6c093580873f0f54b8633f44479d31786b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 26 Feb 2015 21:38:47 +0100 -Subject: [PATCH 091/216] dts: overlay: add support for PiScreen display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for PiScreen display by OzzMaker.com - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/piscreen-overlay.dts | 94 ++++++++++++++++++++++++++++++++++ - 2 files changed, 95 insertions(+) - create mode 100644 arch/arm/boot/dts/piscreen-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ec26431b1..107448d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -26,6 +26,7 @@ dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -new file mode 100644 -index 0000000..8cd6a95 ---- /dev/null -+++ b/arch/arm/boot/dts/piscreen-overlay.dts -@@ -0,0 +1,94 @@ -+/* -+ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ piscreen_pins: piscreen_pins { -+ brcm,pins = <17 25 24 22>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ piscreen: piscreen@0{ -+ compatible = "ilitek,ili9486"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&piscreen_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ regwidth = <16>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 22 1>; -+ debug = <0>; -+ -+ init = <0x10000b0 0x00 -+ 0x1000011 -+ 0x20000ff -+ 0x100003a 0x55 -+ 0x1000036 0x28 -+ 0x10000c2 0x44 -+ 0x10000c5 0x00 0x00 0x00 0x00 -+ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -+ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x1000011 -+ 0x1000029>; -+ }; -+ -+ piscreen-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&piscreen>,"spi-max-frequency:0"; -+ rotate = <&piscreen>,"rotate:0"; -+ fps = <&piscreen>,"fps:0"; -+ debug = <&piscreen>,"debug:0"; -+ }; -+}; - -From 5ef8657c77133ceed5a8ddf80fed6d3002ac9dca Mon Sep 17 00:00:00 2001 +From c24fbfc7a5bc3c7cb35f51d0a40ad25b98a8a422 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 092/216] enc28j60: Add device tree compatible string and an +Subject: [PATCH 61/77] enc28j60: Add device tree compatible string and an overlay --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/enc28j60-overlay.dts | 29 +++++++++++++++++++++++++++++ drivers/net/ethernet/microchip/enc28j60.c | 11 +++++++++++ - 3 files changed, 41 insertions(+) - create mode 100755 arch/arm/boot/dts/enc28j60-overlay.dts + 1 file changed, 11 insertions(+) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 107448d..81afe85 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -14,6 +14,7 @@ endif - - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -diff --git a/arch/arm/boot/dts/enc28j60-overlay.dts b/arch/arm/boot/dts/enc28j60-overlay.dts -new file mode 100755 -index 0000000..aa9b645 ---- /dev/null -+++ b/arch/arm/boot/dts/enc28j60-overlay.dts -@@ -0,0 +1,29 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index b1b5f66..c6b6e1a 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c @@ -127243,1131 +128047,10 @@ index b1b5f66..c6b6e1a 100644 .probe = enc28j60_probe, .remove = enc28j60_remove, -From 04e8bf899200ef72d464ce9ee362d4377fbd7d87 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 27 Feb 2015 18:17:25 +0100 -Subject: [PATCH 093/216] dts: overlay: add support for Adafruit PiTFT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add DT overlay for the Adafruit PiTFT 2.8" resistive touch screen - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/pitft28-resistive-overlay.dts | 115 ++++++++++++++++++++++++ - 2 files changed, 116 insertions(+) - create mode 100644 arch/arm/boot/dts/pitft28-resistive-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 81afe85..07c6eeb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -28,6 +28,7 @@ dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -diff --git a/arch/arm/boot/dts/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -new file mode 100644 -index 0000000..d506eae ---- /dev/null -+++ b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -@@ -0,0 +1,115 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "ilitek,ili9340"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; - -From 917597bfd056d8d37b02a21e7ea4e56023a3e630 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 2 Mar 2015 09:37:02 +0000 -Subject: [PATCH 094/216] enable compiling spi-bcm2835 and add overlay to allow - us to load the driver - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/spi-bcm2835-overlay.dts | 18 ++++++++++++++++++ - 2 files changed, 19 insertions(+) - create mode 100644 arch/arm/boot/dts/spi-bcm2835-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 07c6eeb..e83179f 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -33,6 +33,7 @@ dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -new file mode 100644 -index 0000000..fc1e39b ---- /dev/null -+++ b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2835-spi"; -+ }; -+ }; -+}; - -From 58f834d50fb0e6eb0f1a8c48bdb3551866addc62 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:39:30 +0100 -Subject: [PATCH 095/216] dts: overlay: add support for MZ61581 display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for MZ61581 display by Tontec. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/mz61581-overlay.dts | 109 ++++++++++++++++++++++++++++++++++ - 2 files changed, 110 insertions(+) - create mode 100644 arch/arm/boot/dts/mz61581-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e83179f..f99eccf 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -25,6 +25,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -diff --git a/arch/arm/boot/dts/mz61581-overlay.dts b/arch/arm/boot/dts/mz61581-overlay.dts -new file mode 100644 -index 0000000..c06fe12 ---- /dev/null -+++ b/arch/arm/boot/dts/mz61581-overlay.dts -@@ -0,0 +1,109 @@ -+/* -+ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ mz61581_pins: mz61581_pins { -+ brcm,pins = <4 15 18 25>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mz61581: mz61581@0{ -+ compatible = "samsung,s6d02a1"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mz61581_pins>; -+ -+ spi-max-frequency = <128000000>; -+ spi-cpol; -+ spi-cpha; -+ -+ width = <320>; -+ height = <480>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ -+ reset-gpios = <&gpio 15 0>; -+ dc-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 0>; -+ -+ init = <0x10000b0 00 -+ 0x1000011 -+ 0x20000ff -+ 0x10000b3 0x02 0x00 0x00 0x00 -+ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -+ 0x10000c1 0x08 0x16 0x08 0x08 -+ 0x10000c4 0x11 0x07 0x03 0x03 -+ 0x10000c6 0x00 -+ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -+ 0x1000035 0x00 -+ 0x1000036 0xa0 -+ 0x100003a 0x55 -+ 0x1000044 0x00 0x01 -+ 0x10000d0 0x07 0x07 0x1d 0x03 -+ 0x10000d1 0x03 0x30 0x10 -+ 0x10000d2 0x03 0x14 0x04 -+ 0x1000029 -+ 0x100002c>; -+ -+ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -+ debug = <3>; -+ }; -+ -+ mz61581_ts: mz61581_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <4 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 4 0>; -+ -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&mz61581>, "spi-max-frequency:0"; -+ rotate = <&mz61581>, "rotate:0"; -+ fps = <&mz61581>, "fps:0"; -+ debug = <&mz61581>, "debug:0"; -+ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From 080c66dfc13694a3c6123d6732d6255361e49733 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:40:07 +0100 -Subject: [PATCH 096/216] dts: overlay: piscreen: set speed to 24MHz -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some of the displays can't handle the 32MHz speed. -Lower the default speed to 24MHz. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/piscreen-overlay.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -index 8cd6a95..b7fd7ea 100644 ---- a/arch/arm/boot/dts/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/piscreen-overlay.dts -@@ -47,7 +47,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&piscreen_pins>; - -- spi-max-frequency = <32000000>; -+ spi-max-frequency = <24000000>; - rotate = <270>; - bgr; - fps = <30>; - -From c34aef0866b8605b64dd7b7c1bf4c1db77933089 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 7 Mar 2015 20:40:43 +0100 -Subject: [PATCH 097/216] dts: overlay: rpi-display: pullup irq gpio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -An early version of rpi-display needs the touch controller irq -to be pulled up. This is the version with 9-bit SPI as default. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/rpi-display-overlay.dts | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -index 0578810..a8fa974 100644 ---- a/arch/arm/boot/dts/rpi-display-overlay.dts -+++ b/arch/arm/boot/dts/rpi-display-overlay.dts -@@ -30,6 +30,7 @@ - rpi_display_pins: rpi_display_pins { - brcm,pins = <18 23 24 25>; - brcm,function = <1 1 1 0>; /* out out out in */ -+ brcm,pull = <0 0 0 2>; /* - - - up */ - }; - }; - }; - -From 7268b2f16833d36f6568add569f15325b398497b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 14:48:30 +0100 -Subject: [PATCH 098/216] BCM270x_DT: add bcm2835-dma entry -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree entry for bcm2835-dma. -The entry doesn't contain any resources since they are handled -by the arch/arm/mach-bcm270x/dma.c driver. -In non-DT mode, don't add the device in the board file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708.dtsi | 5 +++++ - arch/arm/boot/dts/bcm2709.dtsi | 5 +++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 4 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 0713a1ed..846f148 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -17,6 +17,11 @@ - #size-cells = <1>; - ranges = <0x7e000000 0x20000000 0x01000000>; - -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ - intc: interrupt-controller { - compatible = "brcm,bcm2708-armctrl-ic"; - reg = <0x7e00b200 0x200>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index 34d2226..d468363 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -17,6 +17,11 @@ - #size-cells = <1>; - ranges = <0x7e000000 0x3f000000 0x01000000>; - -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ - intc: interrupt-controller { - compatible = "brcm,bcm2708-armctrl-ic"; - reg = <0x7e00b200 0x200>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c8aea5b..6a08e95 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -857,7 +857,7 @@ void __init bcm2708_init(void) - bcm2708_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); -- bcm_register_device(&bcm2708_dmaengine_device); -+ bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 259d552..3c1c1dc 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -879,7 +879,7 @@ void __init bcm2709_init(void) - bcm2709_dt_init(); - - bcm_register_device(&bcm2708_dmaman_device); -- bcm_register_device(&bcm2708_dmaengine_device); -+ bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - -From ccc2b25ac7ffe4252a482901541a1894c86bb4c3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 14:50:19 +0100 -Subject: [PATCH 099/216] bcm270x: add mmc-bcm2835 clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add clock for the mmc-bcm2835.0 device. -Will be used in non-DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6a08e95..b5f22e2 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -233,6 +233,7 @@ void __init bcm2708_init_clocks(void) - bcm2708_register_clkdev(clk, "dev:f1"); - - clk = bcm2708_clk_register("sdhost_clk", 250000000); -+ bcm2708_register_clkdev(clk, "mmc-bcm2835.0"); - bcm2708_register_clkdev(clk, "bcm2708_spi.0"); - bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); - bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 3c1c1dc..e10667d 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -243,6 +243,7 @@ void __init bcm2709_init_clocks(void) - bcm2709_register_clkdev(clk, "dev:f1"); - - clk = bcm2709_clk_register("sdhost_clk", 250000000); -+ bcm2709_register_clkdev(clk, "mmc-bcm2835.0"); - bcm2709_register_clkdev(clk, "bcm2708_spi.0"); - bcm2709_register_clkdev(clk, "bcm2708_i2c.0"); - bcm2709_register_clkdev(clk, "bcm2708_i2c.1"); - -From 7520bcefca288277ace88e3df254045eee89c189 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 24 Mar 2015 15:12:35 +0100 -Subject: [PATCH 100/216] BCM270x_DT: add bcm2835-mmc entry -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree entry for bcm2835-mmc. -In non-DT mode, don't add the device in the board file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 +++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 +++++ - arch/arm/boot/dts/bcm2708.dtsi | 19 +++++++++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 +++++ - arch/arm/boot/dts/bcm2709.dtsi | 19 +++++++++++++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 7 files changed, 55 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 7f84473..f25563a 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index a39562f..17b4b8c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 846f148..42edda5 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -41,6 +41,17 @@ - #interrupt-cells = <2>; - }; - -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -96,6 +107,14 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ - clk_i2c: i2c { - compatible = "fixed-clock"; - reg = <1>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 75c222f..c73249b 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -44,6 +44,11 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index d468363..bd6605d 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -41,6 +41,17 @@ - #interrupt-cells = <2>; - }; - -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -97,6 +108,14 @@ - #address-cells = <1>; - #size-cells = <0>; - -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ - clk_i2c: i2c { - compatible = "fixed-clock"; - reg = <1>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index b5f22e2..16ba248 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -885,7 +885,7 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 -- bcm_register_device(&bcm2835_emmc_device); -+ bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2708_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index e10667d..dcad008 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -909,7 +909,7 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 -- bcm_register_device(&bcm2835_emmc_device); -+ bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2709_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - -From 7504524f3f951bf8c40c5decf231ea6538d1380b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 27 Mar 2015 11:45:44 +0000 -Subject: [PATCH 101/216] BCM270x_DT: Refactor bcm2708.dtsi and bcm2709.dtsi - -Extract the common elements, creating bcm2708_common.dtsi ---- - arch/arm/boot/dts/bcm2708.dtsi | 118 +-------------------------------- - arch/arm/boot/dts/bcm2708_common.dtsi | 120 ++++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709.dtsi | 118 +-------------------------------- - 3 files changed, 124 insertions(+), 232 deletions(-) - create mode 100644 arch/arm/boot/dts/bcm2708_common.dtsi - -diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi -index 42edda5..0d47427 100644 ---- a/arch/arm/boot/dts/bcm2708.dtsi -+++ b/arch/arm/boot/dts/bcm2708.dtsi -@@ -1,133 +1,19 @@ --/include/ "skeleton.dtsi" -+/include/ "bcm2708_common.dtsi" - - / { - compatible = "brcm,bcm2708"; - model = "BCM2708"; - -- interrupt-parent = <&intc>; -- - chosen { - /* No padding required - the boot loader can do that. */ - bootargs = ""; - }; - -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -+ soc { - ranges = <0x7e000000 0x20000000 0x01000000>; - -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- #dma-cells = <1>; -- }; -- -- intc: interrupt-controller { -- compatible = "brcm,bcm2708-armctrl-ic"; -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- gpio: gpio { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&clk_mmc>; -- dmas = <&dma 11>, -- <&dma 11>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2708-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -- -- //dmas = <&dma 2>, -- // <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&clk_spi>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- - arm-pmu { - compatible = "arm,arm1176-pmu"; - }; - }; -- -- clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_mmc: clock@0 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "mmc"; -- clock-frequency = <250000000>; -- }; -- -- clk_i2c: i2c { -- compatible = "fixed-clock"; -- reg = <1>; -- #clock-cells = <0>; -- clock-frequency = <250000000>; -- }; -- -- clk_spi: clock@2 { -- compatible = "fixed-clock"; -- reg = <2>; -- #clock-cells = <0>; -- clock-output-names = "spi"; -- clock-frequency = <250000000>; -- }; -- }; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -new file mode 100644 -index 0000000..ff70c58 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,120 @@ -+/include/ "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&intc>; -+ -+ soc: soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ dma: dma@7e007000 { -+ compatible = "brcm,bcm2835-dma"; -+ #dma-cells = <1>; -+ }; -+ -+ intc: interrupt-controller { -+ compatible = "brcm,bcm2708-armctrl-ic"; -+ reg = <0x7e00b200 0x200>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio: gpio { -+ compatible = "brcm,bcm2835-gpio"; -+ reg = <0x7e200000 0xb4>; -+ interrupts = <2 17>, <2 18>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; -+ reg = <0x7e300000 0x100>; -+ interrupts = <2 30>; -+ clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ i2s: i2s@7e203000 { -+ compatible = "brcm,bcm2708-i2s"; -+ reg = <0x7e203000 0x20>, -+ <0x7e101098 0x02>; -+ -+ //dmas = <&dma 2>, -+ // <&dma 3>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ -+ spi0: spi@7e204000 { -+ compatible = "brcm,bcm2708-spi"; -+ reg = <0x7e204000 0x1000>; -+ interrupts = <2 22>; -+ clocks = <&clk_spi>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@7e205000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e205000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ i2c1: i2c@7e804000 { -+ compatible = "brcm,bcm2708-i2c"; -+ reg = <0x7e804000 0x1000>; -+ interrupts = <2 21>; -+ clocks = <&clk_i2c>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ leds: leds { -+ compatible = "gpio-leds"; -+ }; -+ }; -+ -+ clocks { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_mmc: clock@0 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "mmc"; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_i2c: i2c { -+ compatible = "fixed-clock"; -+ reg = <1>; -+ #clock-cells = <0>; -+ clock-frequency = <250000000>; -+ }; -+ -+ clk_spi: clock@2 { -+ compatible = "fixed-clock"; -+ reg = <2>; -+ #clock-cells = <0>; -+ clock-output-names = "spi"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2709.dtsi b/arch/arm/boot/dts/bcm2709.dtsi -index bd6605d..5e0b935 100644 ---- a/arch/arm/boot/dts/bcm2709.dtsi -+++ b/arch/arm/boot/dts/bcm2709.dtsi -@@ -1,137 +1,23 @@ --/include/ "skeleton.dtsi" -+/include/ "bcm2708_common.dtsi" - - / { - compatible = "brcm,bcm2709"; - model = "BCM2709"; - -- interrupt-parent = <&intc>; -- - chosen { - /* No padding required - the boot loader can do that. */ - bootargs = ""; - }; - -- soc: soc { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <1>; -+ soc { - ranges = <0x7e000000 0x3f000000 0x01000000>; - -- dma: dma@7e007000 { -- compatible = "brcm,bcm2835-dma"; -- #dma-cells = <1>; -- }; -- -- intc: interrupt-controller { -- compatible = "brcm,bcm2708-armctrl-ic"; -- reg = <0x7e00b200 0x200>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- gpio: gpio { -- compatible = "brcm,bcm2835-gpio"; -- reg = <0x7e200000 0xb4>; -- interrupts = <2 17>, <2 18>; -- -- gpio-controller; -- #gpio-cells = <2>; -- -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- mmc: mmc@7e300000 { -- compatible = "brcm,bcm2835-mmc"; -- reg = <0x7e300000 0x100>; -- interrupts = <2 30>; -- clocks = <&clk_mmc>; -- dmas = <&dma 11>, -- <&dma 11>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- i2s: i2s@7e203000 { -- compatible = "brcm,bcm2708-i2s"; -- reg = <0x7e203000 0x20>, -- <0x7e101098 0x02>; -- -- //dmas = <&dma 2>, -- // <&dma 3>; -- dma-names = "tx", "rx"; -- status = "disabled"; -- }; -- -- spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -- reg = <0x7e204000 0x1000>; -- interrupts = <2 22>; -- clocks = <&clk_spi>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c0: i2c@7e205000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e205000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- i2c1: i2c@7e804000 { -- compatible = "brcm,bcm2708-i2c"; -- reg = <0x7e804000 0x1000>; -- interrupts = <2 21>; -- clocks = <&clk_i2c>; -- #address-cells = <1>; -- #size-cells = <0>; -- status = "disabled"; -- }; -- -- leds: leds { -- compatible = "gpio-leds"; -- }; -- - arm-pmu { - compatible = "arm,cortex-a7-pmu"; - interrupts = <3 9>; - }; - }; - -- clocks { -- compatible = "simple-bus"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_mmc: clock@0 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "mmc"; -- clock-frequency = <250000000>; -- }; -- -- clk_i2c: i2c { -- compatible = "fixed-clock"; -- reg = <1>; -- #clock-cells = <0>; -- clock-frequency = <250000000>; -- }; -- -- clk_spi: clock@2 { -- compatible = "fixed-clock"; -- reg = <2>; -- #clock-cells = <0>; -- clock-output-names = "spi"; -- clock-frequency = <250000000>; -- }; -- }; -- - timer { - compatible = "arm,armv7-timer"; - clock-frequency = <19200000>; - -From 5d44aea95dbfd69851ffeb426ccf419f5894e70e Mon Sep 17 00:00:00 2001 +From 331cdec0de30933d5e7839f0e3def9b98d3fa968 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 102/216] Add driver for rpi-proto +Subject: [PATCH 62/77] 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 @@ -128380,74 +128063,14 @@ Playback tested with devicetree enabled. Signed-off-by: Waldemar Brodkorb --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-proto-overlay.dts | 39 ++++++++ - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-proto.c | 153 ++++++++++++++++++++++++++++++++ - 5 files changed, 202 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-proto-overlay.dts + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-proto.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 162 insertions(+) create mode 100644 sound/soc/bcm/rpi-proto.c -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index f99eccf..daf51d2 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -24,6 +24,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb -diff --git a/arch/arm/boot/dts/rpi-proto-overlay.dts b/arch/arm/boot/dts/rpi-proto-overlay.dts -new file mode 100644 -index 0000000..2029930 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-proto-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for Rpi-Proto -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-proto"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8731@1a { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8731"; -+ reg = <0x1a>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 40d27c1..003ae28 100644 +index bdcf12f..fc151ea 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -54,6 +54,13 @@ config SND_BCM2708_SOC_RPI_DAC @@ -128456,14 +128079,14 @@ index 40d27c1..003ae28 100644 +config SND_BCM2708_SOC_RPI_PROTO + tristate "Support for Rpi-PROTO" -+ depends on SND_BCM2708_SOC_I2S ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8731 + help + Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). + config SND_BCM2708_SOC_IQAUDIO_DAC tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile index 17ea2b0..883241b 100644 --- a/sound/soc/bcm/Makefile @@ -128642,71 +128265,16 @@ index 0000000..c6e45a0 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From b1c2c58f341642e8bcc337b592f19d5543ae51ad Mon Sep 17 00:00:00 2001 +From 2079392f1bde4f50d8c1ad65c2f7b52a6ff34848 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Thu, 2 Apr 2015 12:22:55 +0100 -Subject: [PATCH 103/216] Add Device Tree support for RPi-DAC. +Subject: [PATCH 63/77] Add Device Tree support for RPi-DAC. --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/rpi-dac-overlay.dts | 34 ++++++++++++++++++++++++++++++++++ - sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ - sound/soc/codecs/pcm1794a.c | 7 +++++++ - 4 files changed, 63 insertions(+) - create mode 100644 arch/arm/boot/dts/rpi-dac-overlay.dts + sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ + sound/soc/codecs/pcm1794a.c | 7 +++++++ + 2 files changed, 28 insertions(+) -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index daf51d2..980b78e0 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -24,6 +24,7 @@ dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb -diff --git a/arch/arm/boot/dts/rpi-dac-overlay.dts b/arch/arm/boot/dts/rpi-dac-overlay.dts -new file mode 100644 -index 0000000..7fc6ac9 ---- /dev/null -+++ b/arch/arm/boot/dts/rpi-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for RPi DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm1794a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm1794a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c index 6d6e0ba..d5fac1b 100644 --- a/sound/soc/bcm/rpi-dac.c @@ -128775,24 +128343,24 @@ index b4eaa44..afe1b41 100644 }; -From c3bd8511bef07e4a3ebf9e78fc1ed0889aaf1d62 Mon Sep 17 00:00:00 2001 +From 4725644a3f7c09811486c1324f9653e79ecbdcb7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 104/216] config: Add default configs +Subject: [PATCH 64/77] config: Add default configs --- - arch/arm/configs/bcm2709_defconfig | 1191 ++++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1186 +++++++++++++++++++++++++++++++++++ - 2 files changed, 2377 insertions(+) + arch/arm/configs/bcm2709_defconfig | 1204 ++++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1199 +++++++++++++++++++++++++++++++++++ + 2 files changed, 2403 insertions(+) create mode 100644 arch/arm/configs/bcm2709_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000..7cec5f8 +index 0000000..a3067bf --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1191 @@ +@@ -0,0 +1,1204 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +CONFIG_LOCALVERSION="-v7" @@ -129315,7 +128883,8 @@ index 0000000..7cec5f8 +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m -+# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m @@ -129350,6 +128919,7 @@ index 0000000..7cec5f8 +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y @@ -129392,6 +128962,7 @@ index 0000000..7cec5f8 +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m ++CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y @@ -129564,6 +129135,7 @@ index 0000000..7cec5f8 +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -129751,6 +129323,7 @@ index 0000000..7cec5f8 +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m @@ -129846,9 +129419,16 @@ index 0000000..7cec5f8 +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=y ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_DHT11=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y @@ -129910,6 +129490,7 @@ index 0000000..7cec5f8 +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m @@ -129986,10 +129567,10 @@ index 0000000..7cec5f8 +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 0000000..e77173b +index 0000000..6a41231 --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1186 @@ +@@ -0,0 +1,1199 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +# CONFIG_LOCALVERSION_AUTO is not set @@ -130505,7 +130086,8 @@ index 0000000..e77173b +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m -+# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m @@ -130540,6 +130122,7 @@ index 0000000..e77173b +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y @@ -130582,6 +130165,7 @@ index 0000000..e77173b +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m ++CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y @@ -130754,6 +130338,7 @@ index 0000000..e77173b +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -130941,6 +130526,7 @@ index 0000000..e77173b +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m @@ -131036,9 +130622,16 @@ index 0000000..e77173b +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=y ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_DHT11=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y @@ -131100,6 +130693,7 @@ index 0000000..e77173b +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m @@ -131177,1110 +130771,10 @@ index 0000000..e77173b +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 196c354f9d8f85f9e56bd2ce11113883f98bccaa Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Mon, 2 Mar 2015 16:34:37 +0100 -Subject: [PATCH 105/216] bcm2708: fix uart1 parameters - -System clock is 250MHz, but the device uses a non-standard -oversampling rate (8 instead of 16) hence the clock rate -has to be multiplied by 16/8 = 2. Currently the clock -rate seems to be divided by 2. - -Also correct the .type and .flags. - -Signed-off-by: Jakub Kicinski ---- - arch/arm/mach-bcm2708/bcm2708.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 16ba248..b848e4a 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -312,11 +312,12 @@ static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { - { - .mapbase = UART1_BASE + 0x40, - .irq = IRQ_AUX, -- .uartclk = 125000000, -+ .uartclk = 500000000, - .regshift = 2, - .iotype = UPIO_MEM, -- .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_8250, -+ .flags = UPF_SHARE_IRQ | UPF_FIXED_TYPE | UPF_FIXED_PORT | -+ UPF_IOREMAP | UPF_SKIP_TEST, -+ .type = PORT_16550, - }, - {}, - }; - -From 8243fc28ee2c92452173c695fdb7990e3758fdc3 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 20 Mar 2015 15:26:11 +0100 -Subject: [PATCH 106/216] spi: bcm2835: fix all checkpath --strict messages - -The following errors/warnings issued by checkpatch.pl --strict have been fixed: -drivers/spi/spi-bcm2835.c:182: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:191: CHECK: braces {} should be used on all arms of this statement -drivers/spi/spi-bcm2835.c:234: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:256: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:271: CHECK: Alignment should match open parenthesis -drivers/spi/spi-bcm2835.c:346: CHECK: Alignment should match open parenthesis -total: 0 errors, 0 warnings, 6 checks, 403 lines checked - -In 2 locations the arguments had to get split/moved to the next line so that the -line width stays below 80 chars. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 419a782..779d3a8 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -179,7 +179,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - } - - static int bcm2835_spi_start_transfer(struct spi_device *spi, -- struct spi_transfer *tfr) -+ struct spi_transfer *tfr) - { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - unsigned long spi_hz, clk_hz, cdiv; -@@ -196,8 +196,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - - if (cdiv >= 65536) - cdiv = 0; /* 0 is the slowest we can go */ -- } else -+ } else { - cdiv = 0; /* 0 is the slowest we can go */ -+ } - - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; -@@ -231,7 +232,8 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - } - - static int bcm2835_spi_finish_transfer(struct spi_device *spi, -- struct spi_transfer *tfr, bool cs_change) -+ struct spi_transfer *tfr, -+ bool cs_change) - { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -@@ -253,7 +255,7 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, - } - - static int bcm2835_spi_transfer_one(struct spi_master *master, -- struct spi_message *mesg) -+ struct spi_message *mesg) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); - struct spi_transfer *tfr; -@@ -267,8 +269,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - if (err) - goto out; - -- timeout = wait_for_completion_timeout(&bs->done, -- msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS)); -+ timeout = wait_for_completion_timeout( -+ &bs->done, -+ msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) -+ ); - if (!timeout) { - err = -ETIMEDOUT; - goto out; -@@ -343,7 +347,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - clk_prepare_enable(bs->clk); - - err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, -- dev_name(&pdev->dev), master); -+ dev_name(&pdev->dev), master); - if (err) { - dev_err(&pdev->dev, "could not request IRQ: %d\n", err); - goto out_clk_disable; - -From 54e38f321ea8bb1990d6f496c0710532224a35ad Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 23 Mar 2015 15:11:53 +0100 -Subject: [PATCH 107/216] spi: bcm2835: fill/drain SPI-fifo as much as possible - during interrupt - -Implement the recommendation from the BCM2835 data-sheet -with regards to polling drivers to fill/drain the FIFO as much data as possible -also for the interrupt-driven case (which this driver is making use of). - -This means that for long transfers (>64bytes) we need one interrupt -every 64 bytes instead of every 12 bytes, as the FIFO is 16 words (not bytes) wide. - -Tested with mcp251x (can bus), fb_st7735 (TFT framebuffer device) -and enc28j60 (ethernet) drivers. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 78 +++++++++++------------------------------------ - 1 file changed, 17 insertions(+), 61 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 779d3a8..960dcce 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -91,25 +91,23 @@ static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val) - writel(val, bs->regs + reg); - } - --static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len) -+static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while (len--) { -+ while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { - byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); - if (bs->rx_buf) - *bs->rx_buf++ = byte; - } - } - --static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len) -+static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- if (len > bs->len) -- len = bs->len; -- -- while (len--) { -+ while ((bs->len) && -+ (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { - byte = bs->tx_buf ? *bs->tx_buf++ : 0; - bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); - bs->len--; -@@ -122,60 +120,24 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - struct bcm2835_spi *bs = spi_master_get_devdata(master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -- /* -- * RXR - RX needs Reading. This means 12 (or more) bytes have been -- * transmitted and hence 12 (or more) bytes have been received. -- * -- * The FIFO is 16-bytes deep. We check for this interrupt to keep the -- * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check -- * this before DONE (TX empty) just in case we delayed processing this -- * interrupt for some reason. -- * -- * We only check for this case if we have more bytes to TX; at the end -- * of the transfer, we ignore this pipelining optimization, and let -- * bcm2835_spi_finish_transfer() drain the RX FIFO. -- */ -- if (bs->len && (cs & BCM2835_SPI_CS_RXR)) { -- /* Read 12 bytes of data */ -- bcm2835_rd_fifo(bs, 12); -+ /* Read as many bytes as possible from FIFO */ -+ bcm2835_rd_fifo(bs); - -- /* Write up to 12 bytes */ -- bcm2835_wr_fifo(bs, 12); -+ if (bs->len) { /* there is more data to transmit */ -+ bcm2835_wr_fifo(bs); -+ } else { /* Transfer complete */ -+ /* Disable SPI interrupts */ -+ cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); - - /* -- * We must have written something to the TX FIFO due to the -- * bs->len check above, so cannot be DONE. Hence, return -- * early. Note that DONE could also be set if we serviced an -- * RXR interrupt really late. -+ * Wake up bcm2835_spi_transfer_one(), which will call -+ * bcm2835_spi_finish_transfer(), to drain the RX FIFO. - */ -- return IRQ_HANDLED; -+ complete(&bs->done); - } - -- /* -- * DONE - TX empty. This occurs when we first enable the transfer -- * since we do not pre-fill the TX FIFO. At any other time, given that -- * we refill the TX FIFO above based on RXR, and hence ignore DONE if -- * RXR is set, DONE really does mean end-of-transfer. -- */ -- if (cs & BCM2835_SPI_CS_DONE) { -- if (bs->len) { /* First interrupt in a transfer */ -- bcm2835_wr_fifo(bs, 16); -- } else { /* Transfer complete */ -- /* Disable SPI interrupts */ -- cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -- -- /* -- * Wake up bcm2835_spi_transfer_one(), which will call -- * bcm2835_spi_finish_transfer(), to drain the RX FIFO. -- */ -- complete(&bs->done); -- } -- -- return IRQ_HANDLED; -- } -- -- return IRQ_NONE; -+ return IRQ_HANDLED; - } - - static int bcm2835_spi_start_transfer(struct spi_device *spi, -@@ -238,12 +200,6 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -- /* Drain RX FIFO */ -- while (cs & BCM2835_SPI_CS_RXD) { -- bcm2835_rd_fifo(bs, 1); -- cs = bcm2835_rd(bs, BCM2835_SPI_CS); -- } -- - if (tfr->delay_usecs) - udelay(tfr->delay_usecs); - - -From 52469b2a3843dbd5aad2109a73e1b41371f83be3 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 19 Mar 2015 09:01:52 +0000 -Subject: [PATCH 108/216] spi: bcm2835: clock divider can be a multiple of 2 - -The official documentation is wrong in this respect. -Has been tested empirically for dividers 2-1024 - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 960dcce..8de1925 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -153,8 +153,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - if (spi_hz >= clk_hz / 2) { - cdiv = 2; /* clk_hz/2 is the fastest we can go */ - } else if (spi_hz) { -- /* CDIV must be a power of two */ -- cdiv = roundup_pow_of_two(DIV_ROUND_UP(clk_hz, spi_hz)); -+ /* CDIV must be a multiple of two */ -+ cdiv = DIV_ROUND_UP(clk_hz, spi_hz); -+ cdiv += (cdiv % 2); - - if (cdiv >= 65536) - cdiv = 0; /* 0 is the slowest we can go */ - -From b3622510de92a35d73778905be9ab4ad4235bd66 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 19 Mar 2015 09:01:53 +0000 -Subject: [PATCH 109/216] spi: bcm2835: enable support of 3-wire mode - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 8de1925..3f93718 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -67,7 +67,8 @@ - #define BCM2835_SPI_CS_CS_01 0x00000001 - - #define BCM2835_SPI_TIMEOUT_MS 30000 --#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS) -+#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ -+ | SPI_NO_CS | SPI_3WIRE) - - #define DRV_NAME "spi-bcm2835" - -@@ -163,6 +164,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - cdiv = 0; /* 0 is the slowest we can go */ - } - -+ if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) -+ cs |= BCM2835_SPI_CS_REN; -+ - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - -From c71501bcc7b07a82119e2f7b27309a62f90aa02a Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 26 Mar 2015 11:08:36 +0100 -Subject: [PATCH 110/216] spi: bcm2835: move to the transfer_one driver model - -This also allows for GPIO-CS to get used removing the limitation of -2/3 SPI devises on the SPI bus. - -Fixes: spi-cs-high with native CS with multiple devices on the spi-bus -resetting the chip selects to "normal" polarity after a finished -transfer. - -No other functionality/improvements added. - -Tested with the following 4 devices on the spi-bus: -* mcp2515 with native CS -* mcp2515 with gpio CS -* fb_st7735r with native CS - (plus spi-cs-high via transistor inverting polarity) -* enc28j60 with gpio-CS -Tested-by: Martin Sperl - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 212 +++++++++++++++++++++++++++------------------- - 1 file changed, 124 insertions(+), 88 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 3f93718..31d80eb0 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -3,6 +3,7 @@ - * - * Copyright (C) 2012 Chris Boot - * Copyright (C) 2013 Stephen Warren -+ * Copyright (C) 2015 Martin Sperl - * - * This driver is inspired by: - * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos -@@ -29,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -76,10 +78,10 @@ struct bcm2835_spi { - void __iomem *regs; - struct clk *clk; - int irq; -- struct completion done; - const u8 *tx_buf; - u8 *rx_buf; -- int len; -+ int tx_len; -+ int rx_len; - }; - - static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg) -@@ -96,10 +98,12 @@ static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { -+ while ((bs->rx_len) && -+ (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { - byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); - if (bs->rx_buf) - *bs->rx_buf++ = byte; -+ bs->rx_len--; - } - } - -@@ -107,47 +111,60 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) - { - u8 byte; - -- while ((bs->len) && -+ while ((bs->tx_len) && - (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { - byte = bs->tx_buf ? *bs->tx_buf++ : 0; - bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); -- bs->len--; -+ bs->tx_len--; - } - } - -+static void bcm2835_spi_reset_hw(struct spi_master *master) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -+ -+ /* Disable SPI interrupts and transfer */ -+ cs &= ~(BCM2835_SPI_CS_INTR | -+ BCM2835_SPI_CS_INTD | -+ BCM2835_SPI_CS_TA); -+ /* and reset RX/TX FIFOS */ -+ cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; -+ -+ /* and reset the SPI_HW */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+} -+ - static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - { - struct spi_master *master = dev_id; - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - - /* Read as many bytes as possible from FIFO */ - bcm2835_rd_fifo(bs); -- -- if (bs->len) { /* there is more data to transmit */ -- bcm2835_wr_fifo(bs); -- } else { /* Transfer complete */ -- /* Disable SPI interrupts */ -- cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -- -- /* -- * Wake up bcm2835_spi_transfer_one(), which will call -- * bcm2835_spi_finish_transfer(), to drain the RX FIFO. -- */ -- complete(&bs->done); -+ /* Write as many bytes as possible to FIFO */ -+ bcm2835_wr_fifo(bs); -+ -+ /* based on flags decide if we can finish the transfer */ -+ if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) { -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* wake up the framework */ -+ complete(&master->xfer_completion); - } - - return IRQ_HANDLED; - } - --static int bcm2835_spi_start_transfer(struct spi_device *spi, -- struct spi_transfer *tfr) -+static int bcm2835_spi_transfer_one(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr) - { -- struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, cdiv; -- u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - -+ /* set clock */ - spi_hz = tfr->speed_hz; - clk_hz = clk_get_rate(bs->clk); - -@@ -163,100 +180,118 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, - } else { - cdiv = 0; /* 0 is the slowest we can go */ - } -+ bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - -+ /* handle all the modes */ - if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) - cs |= BCM2835_SPI_CS_REN; -- - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; - -- if (!(spi->mode & SPI_NO_CS)) { -- if (spi->mode & SPI_CS_HIGH) { -- cs |= BCM2835_SPI_CS_CSPOL; -- cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; -- } -- -- cs |= spi->chip_select; -- } -+ /* for gpio_cs set dummy CS so that no HW-CS get changed -+ * we can not run this in bcm2835_spi_set_cs, as it does -+ * not get called for cs_gpio cases, so we need to do it here -+ */ -+ if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - -- reinit_completion(&bs->done); -+ /* set transmit buffers and length */ - bs->tx_buf = tfr->tx_buf; - bs->rx_buf = tfr->rx_buf; -- bs->len = tfr->len; -+ bs->tx_len = tfr->len; -+ bs->rx_len = tfr->len; - -- bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - /* - * Enable the HW block. This will immediately trigger a DONE (TX - * empty) interrupt, upon which we will fill the TX FIFO with the - * first TX bytes. Pre-filling the TX FIFO here to avoid the - * interrupt doesn't work:-( - */ -+ cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - -- return 0; -+ /* signal that we need to wait for completion */ -+ return 1; - } - --static int bcm2835_spi_finish_transfer(struct spi_device *spi, -- struct spi_transfer *tfr, -- bool cs_change) -+static void bcm2835_spi_handle_err(struct spi_master *master, -+ struct spi_message *msg) - { -- struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); -- u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -- -- if (tfr->delay_usecs) -- udelay(tfr->delay_usecs); -- -- if (cs_change) -- /* Clear TA flag */ -- bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA); -- -- return 0; -+ bcm2835_spi_reset_hw(master); - } - --static int bcm2835_spi_transfer_one(struct spi_master *master, -- struct spi_message *mesg) -+static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - { -+ /* -+ * we can assume that we are "native" as per spi_set_cs -+ * calling us ONLY when cs_gpio is not set -+ * we can also assume that we are CS < 3 as per bcm2835_spi_setup -+ * we would not get called because of error handling there. -+ * the level passed is the electrical level not enabled/disabled -+ * so it has to get translated back to enable/disable -+ * see spi_set_cs in spi.c for the implementation -+ */ -+ -+ struct spi_master *master = spi->master; - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- struct spi_transfer *tfr; -- struct spi_device *spi = mesg->spi; -- int err = 0; -- unsigned int timeout; -- bool cs_change; -- -- list_for_each_entry(tfr, &mesg->transfers, transfer_list) { -- err = bcm2835_spi_start_transfer(spi, tfr); -- if (err) -- goto out; -- -- timeout = wait_for_completion_timeout( -- &bs->done, -- msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) -- ); -- if (!timeout) { -- err = -ETIMEDOUT; -- goto out; -- } -+ u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); -+ bool enable; - -- cs_change = tfr->cs_change || -- list_is_last(&tfr->transfer_list, &mesg->transfers); -+ /* calculate the enable flag from the passed gpio_level */ -+ enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level; - -- err = bcm2835_spi_finish_transfer(spi, tfr, cs_change); -- if (err) -- goto out; -+ /* set flags for "reverse" polarity in the registers */ -+ if (spi->mode & SPI_CS_HIGH) { -+ /* set the correct CS-bits */ -+ cs |= BCM2835_SPI_CS_CSPOL; -+ cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; -+ } else { -+ /* clean the CS-bits */ -+ cs &= ~BCM2835_SPI_CS_CSPOL; -+ cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select); -+ } - -- mesg->actual_length += (tfr->len - bs->len); -+ /* select the correct chip_select depending on disabled/enabled */ -+ if (enable) { -+ /* set cs correctly */ -+ if (spi->mode & SPI_NO_CS) { -+ /* use the "undefined" chip-select */ -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; -+ } else { -+ /* set the chip select */ -+ cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01); -+ cs |= spi->chip_select; -+ } -+ } else { -+ /* disable CSPOL which puts HW-CS into deselected state */ -+ cs &= ~BCM2835_SPI_CS_CSPOL; -+ /* use the "undefined" chip-select as precaution */ -+ cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - } - --out: -- /* Clear FIFOs, and disable the HW block */ -- bcm2835_wr(bs, BCM2835_SPI_CS, -- BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); -- mesg->status = err; -- spi_finalize_current_message(master); -+ /* finally set the calculated flags in SPI_CS */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+} - -- return 0; -+static int bcm2835_spi_setup(struct spi_device *spi) -+{ -+ /* -+ * sanity checking the native-chipselects -+ */ -+ if (spi->mode & SPI_NO_CS) -+ return 0; -+ if (gpio_is_valid(spi->cs_gpio)) -+ return 0; -+ if (spi->chip_select < 3) -+ return 0; -+ -+ /* error in the case of native CS requested with CS-id > 2 */ -+ dev_err(&spi->dev, -+ "setup: only three native chip-selects are supported\n" -+ ); -+ return -EINVAL; - } - - static int bcm2835_spi_probe(struct platform_device *pdev) -@@ -277,13 +312,14 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - master->mode_bits = BCM2835_SPI_MODE_BITS; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->num_chipselect = 3; -- master->transfer_one_message = bcm2835_spi_transfer_one; -+ master->setup = bcm2835_spi_setup; -+ master->set_cs = bcm2835_spi_set_cs; -+ master->transfer_one = bcm2835_spi_transfer_one; -+ //master->handle_err = bcm2835_spi_handle_err; - master->dev.of_node = pdev->dev.of_node; - - bs = spi_master_get_devdata(master); - -- init_completion(&bs->done); -- - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(bs->regs)) { -@@ -314,7 +350,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) - goto out_clk_disable; - } - -- /* initialise the hardware */ -+ /* initialise the hardware with the default polarities */ - bcm2835_wr(bs, BCM2835_SPI_CS, - BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - - -From cf51ed163d8109aa02dfc267633ed4c0a4a81f08 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sun, 29 Mar 2015 16:03:23 +0200 -Subject: [PATCH 111/216] spi: bcm2835: fix code formatting issue - -Signed-off-by: Martin Sperl -Tested-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 31d80eb0..4aa80fd 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -289,8 +289,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) - - /* error in the case of native CS requested with CS-id > 2 */ - dev_err(&spi->dev, -- "setup: only three native chip-selects are supported\n" -- ); -+ "setup: only three native chip-selects are supported\n"); - return -EINVAL; - } - - -From 8f0e96a797cebd49ab5054b3c150386a5f840855 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sun, 29 Mar 2015 16:03:25 +0200 -Subject: [PATCH 112/216] spi: bcm2835: fill FIFO before enabling interrupts to - reduce interrupts/message - -To reduce the number of interrupts/message we fill the FIFO before -enabling interrupts - for short messages this reduces the interrupt count -from 2 to 1 interrupt. - -There have been rare cases where short (<200ns) chip-select switches with -native CS have been observed during such operation, this is why this -optimization is only enabled for GPIO-CS. - -Signed-off-by: Martin Sperl -Tested-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 4aa80fd..321dbe2 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -203,6 +203,22 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - bs->tx_len = tfr->len; - bs->rx_len = tfr->len; - -+ /* fill in fifo if we have gpio-cs -+ * note that there have been rare events where the native-CS -+ * flapped for <1us which may change the behaviour -+ * with gpio-cs this does not happen, so it is implemented -+ * only for this case -+ */ -+ if (gpio_is_valid(spi->cs_gpio)) { -+ /* enable HW block, but without interrupts enabled -+ * this would triggern an immediate interrupt -+ */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, -+ cs | BCM2835_SPI_CS_TA); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ } -+ - /* - * Enable the HW block. This will immediately trigger a DONE (TX - * empty) interrupt, upon which we will fill the TX FIFO with the - -From 31a827ccaeac10f8a5ac4ee4dc4fcdda68470eb7 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 6 Apr 2015 17:16:31 +0000 -Subject: [PATCH 113/216] spi: bcm2835: transform native-cs to gpio-cs on first - spi_setup - -Transforms the bcm-2835 native SPI-chip select to their gpio-cs equivalent. - -This allows for some support of some optimizations that are not -possible due to HW-gliches on the CS line - especially filling -the FIFO before enabling SPI interrupts (by writing to CS register) -while the transfer is already in progress (See commit: e3a2be3030e2) - -This patch also works arround some issues in bcm2835-pinctrl which does not -set the value when setting the GPIO as output - it just sets up output and -(typically) leaves the GPIO as low. When a fix for this is merged then this -gpio_set_value can get removed from bcm2835_spi_setup. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 49 ++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 44 insertions(+), 5 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 321dbe2..033b93f 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -291,8 +291,15 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - } - -+static int chip_match_name(struct gpio_chip *chip, void *data) -+{ -+ return !strcmp(chip->label, data); -+} -+ - static int bcm2835_spi_setup(struct spi_device *spi) - { -+ int err; -+ struct gpio_chip *chip; - /* - * sanity checking the native-chipselects - */ -@@ -300,13 +307,45 @@ static int bcm2835_spi_setup(struct spi_device *spi) - return 0; - if (gpio_is_valid(spi->cs_gpio)) - return 0; -- if (spi->chip_select < 3) -+ if (spi->chip_select > 1) { -+ /* error in the case of native CS requested with CS > 1 -+ * officially there is a CS2, but it is not documented -+ * which GPIO is connected with that... -+ */ -+ dev_err(&spi->dev, -+ "setup: only two native chip-selects are supported\n"); -+ return -EINVAL; -+ } -+ /* now translate native cs to GPIO */ -+ -+ /* get the gpio chip for the base */ -+ chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); -+ if (!chip) - return 0; - -- /* error in the case of native CS requested with CS-id > 2 */ -- dev_err(&spi->dev, -- "setup: only three native chip-selects are supported\n"); -- return -EINVAL; -+ /* and calculate the real CS */ -+ spi->cs_gpio = chip->base + 8 - spi->chip_select; -+ -+ /* and set up the "mode" and level */ -+ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -+ spi->chip_select, spi->cs_gpio); -+ -+ /* set up GPIO as output and pull to the correct level */ -+ err = gpio_direction_output(spi->cs_gpio, -+ (spi->mode & SPI_CS_HIGH) ? 0 : 1); -+ if (err) { -+ dev_err(&spi->dev, -+ "could not set CS%i gpio %i as output: %i", -+ spi->chip_select, spi->cs_gpio, err); -+ return err; -+ } -+ /* the implementation of pinctrl-bcm2835 currently does not -+ * set the GPIO value when using gpio_direction_output -+ * so we are setting it here explicitly -+ */ -+ gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1); -+ -+ return 0; - } - - static int bcm2835_spi_probe(struct platform_device *pdev) - -From 776aadc5da23cf97862d5eb535d8d9b8a038552f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 6 Apr 2015 17:16:30 +0000 -Subject: [PATCH 114/216] spi: bcm2835: enabling polling mode for transfers - shorter than 30us - -In cases of short transfer times the CPU is spending lots of time -in the interrupt handler and scheduler to reschedule the worker thread. - -Measurements show that we have times where it takes 29.32us to between -the last clock change and the time that the worker-thread is running again -returning from wait_for_completion_timeout(). - -During this time the interrupt-handler is running calling complete() -and then also the scheduler is rescheduling the worker thread. - -This time can vary depending on how much of the code is still in -CPU-caches, when there is a burst of spi transfers the subsequent delays -are in the order of 25us, so the value of 30us seems reasonable. - -With polling the whole transfer of 4 bytes at 10MHz finishes after 6.16us -(CS down to up) with the real transfer (clock running) taking 3.56us. -So the efficiency has much improved and is also freeing CPU cycles, -reducing interrupts and context switches. - -Because of the above 30us seems to be a reasonable limit for polling. - -Signed-off-by: Martin Sperl -Signed-off-by: Mark Brown ---- - drivers/spi/spi-bcm2835.c | 112 +++++++++++++++++++++++++++++++++++----------- - 1 file changed, 86 insertions(+), 26 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 033b93f..44ee1f3 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -68,7 +68,8 @@ - #define BCM2835_SPI_CS_CS_10 0x00000002 - #define BCM2835_SPI_CS_CS_01 0x00000001 - --#define BCM2835_SPI_TIMEOUT_MS 30000 -+#define BCM2835_SPI_POLLING_LIMIT_US 30 -+#define BCM2835_SPI_TIMEOUT_MS 30000 - #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ - | SPI_NO_CS | SPI_3WIRE) - -@@ -156,12 +157,86 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+static int bcm2835_spi_transfer_one_poll(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr, -+ u32 cs, -+ unsigned long xfer_time_us) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ unsigned long timeout = jiffies + -+ max(4 * xfer_time_us * HZ / 1000000, 2uL); -+ -+ /* enable HW block without interrupts */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); -+ -+ /* set timeout to 4x the expected time, or 2 jiffies */ -+ /* loop until finished the transfer */ -+ while (bs->rx_len) { -+ /* read from fifo as much as possible */ -+ bcm2835_rd_fifo(bs); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ /* if we still expect some data after the read, -+ * check for a possible timeout -+ */ -+ if (bs->rx_len && time_after(jiffies, timeout)) { -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* and return timeout */ -+ return -ETIMEDOUT; -+ } -+ } -+ -+ /* Transfer complete - reset SPI HW */ -+ bcm2835_spi_reset_hw(master); -+ /* and return without waiting for completion */ -+ return 0; -+} -+ -+static int bcm2835_spi_transfer_one_irq(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *tfr, -+ u32 cs) -+{ -+ struct bcm2835_spi *bs = spi_master_get_devdata(master); -+ -+ /* fill in fifo if we have gpio-cs -+ * note that there have been rare events where the native-CS -+ * flapped for <1us which may change the behaviour -+ * with gpio-cs this does not happen, so it is implemented -+ * only for this case -+ */ -+ if (gpio_is_valid(spi->cs_gpio)) { -+ /* enable HW block, but without interrupts enabled -+ * this would triggern an immediate interrupt -+ */ -+ bcm2835_wr(bs, BCM2835_SPI_CS, -+ cs | BCM2835_SPI_CS_TA); -+ /* fill in tx fifo as much as possible */ -+ bcm2835_wr_fifo(bs); -+ } -+ -+ /* -+ * Enable the HW block. This will immediately trigger a DONE (TX -+ * empty) interrupt, upon which we will fill the TX FIFO with the -+ * first TX bytes. Pre-filling the TX FIFO here to avoid the -+ * interrupt doesn't work:-( -+ */ -+ cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -+ bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+ -+ /* signal that we need to wait for completion */ -+ return 1; -+} -+ - static int bcm2835_spi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *tfr) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, cdiv; -+ unsigned long spi_used_hz, xfer_time_us; - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - - /* set clock */ -@@ -180,6 +255,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - } else { - cdiv = 0; /* 0 is the slowest we can go */ - } -+ spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); - bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - - /* handle all the modes */ -@@ -203,33 +279,17 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, - bs->tx_len = tfr->len; - bs->rx_len = tfr->len; - -- /* fill in fifo if we have gpio-cs -- * note that there have been rare events where the native-CS -- * flapped for <1us which may change the behaviour -- * with gpio-cs this does not happen, so it is implemented -- * only for this case -- */ -- if (gpio_is_valid(spi->cs_gpio)) { -- /* enable HW block, but without interrupts enabled -- * this would triggern an immediate interrupt -- */ -- bcm2835_wr(bs, BCM2835_SPI_CS, -- cs | BCM2835_SPI_CS_TA); -- /* fill in tx fifo as much as possible */ -- bcm2835_wr_fifo(bs); -- } -+ /* calculate the estimated time in us the transfer runs */ -+ xfer_time_us = tfr->len -+ * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ -+ * 1000000 / spi_used_hz; - -- /* -- * Enable the HW block. This will immediately trigger a DONE (TX -- * empty) interrupt, upon which we will fill the TX FIFO with the -- * first TX bytes. Pre-filling the TX FIFO here to avoid the -- * interrupt doesn't work:-( -- */ -- cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; -- bcm2835_wr(bs, BCM2835_SPI_CS, cs); -+ /* for short requests run polling*/ -+ if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) -+ return bcm2835_spi_transfer_one_poll(master, spi, tfr, -+ cs, xfer_time_us); - -- /* signal that we need to wait for completion */ -- return 1; -+ return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); - } - - static void bcm2835_spi_handle_err(struct spi_master *master, - -From 0a92a30733013eae878dc15c597dfa718f2865f5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Thu, 16 Apr 2015 21:18:47 +0100 -Subject: [PATCH 115/216] spi: bcm2835: change timeout of polling driver to 1s - -The way that the timeout code is written in the polling function -the timeout does also trigger when interrupted or rescheduled while -in the polling loop. - -This patch changes the timeout from effectively 20ms (=2 jiffies) to -1 second and removes the time that the transfer really takes out of -the computation, as - per design - this is <30us and the jiffie resolution -is 10ms so that does not make any difference what so ever. - -Signed-off-by: Martin Sperl ---- - drivers/spi/spi-bcm2835.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 44ee1f3..1a915e5 100644 ---- a/drivers/spi/spi-bcm2835.c -+++ b/drivers/spi/spi-bcm2835.c -@@ -164,13 +164,12 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, - unsigned long xfer_time_us) - { - struct bcm2835_spi *bs = spi_master_get_devdata(master); -- unsigned long timeout = jiffies + -- max(4 * xfer_time_us * HZ / 1000000, 2uL); -+ /* set timeout to 1 second of maximum polling */ -+ unsigned long timeout = jiffies + HZ; - - /* enable HW block without interrupts */ - bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); - -- /* set timeout to 4x the expected time, or 2 jiffies */ - /* loop until finished the transfer */ - while (bs->rx_len) { - /* read from fifo as much as possible */ - -From a53606a32ae4bdadc08985d0a67a6924c09633f1 Mon Sep 17 00:00:00 2001 +From 7de29243d1ac891a526c77e17129d6e2d547361d Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 116/216] smsx95xx: fix crimes against truesize +Subject: [PATCH 65/77] 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. @@ -132315,10 +130809,10 @@ index e29a323..aff63dc usbnet_skb_return(dev, ax_skb); } -From a6f41e34aeb0834ce943e48ee5f6655716dd53c4 Mon Sep 17 00:00:00 2001 +From 4772a6e4cc3921cb41515b7b0a91ad646d1491aa Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 117/216] smsc95xx: Disable turbo mode by default +Subject: [PATCH 66/77] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- @@ -132338,133 +130832,10 @@ index aff63dc..08a8a8c 100755 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From d8512fe40402051a7fb3ec7e7ad25f38d0abab65 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 18 Mar 2015 18:06:52 +0100 -Subject: [PATCH 118/216] HiFiBerry Digi: set SPDIF status bits for sample rate - -The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. -While this is optional, some DACs and receivers do not accept this signal. This patch -adds the sample rate bits in the SPDIF status block. ---- - sound/soc/bcm/hifiberry_digi.c | 28 ++++++++++++++++++++++++---- - 1 file changed, 24 insertions(+), 4 deletions(-) - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index a294a1b..80732b8 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -74,24 +74,41 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - - long mclk_freq=0; - int mclk_div=1; -+ int sampling_freq=1; - - int ret; - - samplerate = params_rate(params); - -+ if (samplerate<=96000) { -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ } -+ - switch (samplerate) { - case 32000: -+ sampling_freq=0x03; -+ break; - case 44100: -+ sampling_freq=0x00; -+ break; - case 48000: -+ sampling_freq=0x02; -+ break; - case 88200: -+ sampling_freq=0x08; -+ break; - case 96000: -- mclk_freq=samplerate*256; -- mclk_div=WM8804_MCLKDIV_256FS; -+ sampling_freq=0x0a; - break; - case 176400: -+ sampling_freq=0x0c; -+ break; - case 192000: -- mclk_freq=samplerate*128; -- mclk_div=WM8804_MCLKDIV_128FS; -+ sampling_freq=0x0e; - break; - default: - dev_err(codec->dev, -@@ -116,6 +133,9 @@ static int snd_rpi_hifiberry_digi_hw_params(struct snd_pcm_substream *substream, - /* Power on */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); - -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ - return snd_soc_dai_set_bclk_ratio(cpu_dai,64); - } - - -From 496a822ba4493536df3181be27d4b2d2906d4fde Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 18 Apr 2015 17:20:14 +0100 -Subject: [PATCH 119/216] bcm2708-dmaengine: Add debug options - ---- - drivers/dma/bcm2708-dmaengine.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 6150b8f..8182b16 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -56,6 +56,7 @@ - - #include "virt-dma.h" - -+static unsigned dma_debug; - - struct bcm2835_dmadev { - struct dma_device ddev; -@@ -600,7 +601,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( - } - - /* Common part */ -- control_block->info |= BCM2835_DMA_WAITS(SDHCI_BCM_DMA_WAITS); -+ u32 waits = SDHCI_BCM_DMA_WAITS; -+ if ((dma_debug >> 0) & 0x1f) -+ waits = (dma_debug >> 0) & 0x1f; -+ control_block->info |= BCM2835_DMA_WAITS(waits); - control_block->info |= BCM2835_DMA_WAIT_RESP; - - /* Enable */ -@@ -952,6 +956,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - } - - dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n"); -+ dev_info(&pdev->dev, "dma_debug:%x\n", dma_debug); - - return 0; - -@@ -982,6 +987,7 @@ static struct platform_driver bcm2835_dma_driver = { - - module_platform_driver(bcm2835_dma_driver); - -+module_param(dma_debug, uint, 0644); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); - -From 4dc3a781a0d5718153bc38b1f1294523d44b8f66 Mon Sep 17 00:00:00 2001 +From 9d1fbb7b2dbe16c506f54984c361a55d1b2603fb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Apr 2015 19:30:22 +0100 -Subject: [PATCH 120/216] Add blk_pos parameter to mmc multi_io_quirk callback +Subject: [PATCH 67/77] Add blk_pos parameter to mmc multi_io_quirk callback --- drivers/mmc/card/block.c | 1 + @@ -132475,7 +130846,7 @@ Subject: [PATCH 120/216] Add blk_pos parameter to mmc multi_io_quirk callback 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index ed2e71a..ce854a9 100644 +index 60f7141..1f15cb5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1413,6 +1413,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, @@ -132487,10 +130858,10 @@ index ed2e71a..ce854a9 100644 } diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c -index f84cfb0..fec8c12 100644 +index 9df2b68..8c0ee4a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c -@@ -1798,7 +1798,9 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc) +@@ -1749,7 +1749,9 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) } static int omap_hsmmc_multi_io_quirk(struct mmc_card *card, @@ -132502,7 +130873,7 @@ index f84cfb0..fec8c12 100644 /* This controller can't do multiblock reads due to hw bugs */ if (direction == MMC_DATA_READ) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c -index 6906a90..1fb7577 100644 +index 354f4f3..4f1ccf3 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -170,7 +170,9 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) @@ -132532,10 +130903,10 @@ index dba7e1c..0c87f4f 100644 struct tmio_mmc_host *host = mmc_priv(card->host); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index c3b84a2..c1c3868f 100644 +index b0258e8..d3cdad9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -146,7 +146,9 @@ struct mmc_host_ops { +@@ -140,7 +140,9 @@ struct mmc_host_ops { * I/O. Returns the number of supported blocks for the request. */ int (*multi_io_quirk)(struct mmc_card *card, @@ -132547,3870 +130918,10 @@ index c3b84a2..c1c3868f 100644 struct mmc_card; -From 12b12cf1a7a825c46dcefa06bdde683cac053189 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 121/216] Adding bcm2835-sdhost driver, and an overlay to - enable it - -BCM2835 has two SD card interfaces. This driver uses the other one. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/sdhost-overlay.dts | 73 ++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - drivers/mmc/host/Kconfig | 10 + - drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 1685 ++++++++++++++++++++++++++++++++++ - 7 files changed, 1772 insertions(+) - create mode 100644 arch/arm/boot/dts/sdhost-overlay.dts - create mode 100644 drivers/mmc/host/bcm2835-sdhost.c - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 980b78e0..9cb5a2d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -34,6 +34,7 @@ dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -new file mode 100644 -index 0000000..33db96e ---- /dev/null -+++ b/arch/arm/boot/dts/sdhost-overlay.dts -@@ -0,0 +1,73 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&soc>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ interrupts = <2 24>; -+ clocks = <&clk_sdhost>; -+ dmas = <&dma 13>, -+ <&dma 13>; -+ dma-names = "tx", "rx"; -+ brcm,delay-after-stop = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; -+ status = "okay"; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_sdhost: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ sdhost_pins: sdhost_pins { -+ brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&mmc>; -+ __overlay__ { -+ /* Find a way to disable the other driver */ -+ compatible = ""; -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/__overrides__"; -+ __overlay__ { -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+ }; -+ -+ __overrides__ { -+ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ force_pio = <&sdhost>,"brcm,force-pio?"; -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 7cec5f8..367a04a 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -956,6 +956,7 @@ CONFIG_MMC=y - CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SPI=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e77173b..db287f3 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -949,6 +949,7 @@ CONFIG_MMC=y - CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SPI=m -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 7c093a6..1666c6c 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER - - If unsure, say 2 here. - -+config MMC_BCM2835_SDHOST -+ tristate "Support for the SDHost controller on BCM2708/9" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ help -+ This selects the SDHost controller on BCM2835/6. -+ -+ If you have a controller with this interface, say Y or M here. -+ -+ If unsure, say N. -+ - config MMC_ARMMMCI - tristate "ARM AMBA Multimedia Card Interface support" - depends on ARM_AMBA -diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 9d41de9..8a7e43e 100644 ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o - obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o - obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o - obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o -+obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o - obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o - obj-$(CONFIG_MMC_WBSD) += wbsd.o - obj-$(CONFIG_MMC_AU1X) += au1xmmc.o -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -new file mode 100644 -index 0000000..0c311b5 ---- /dev/null -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,1685 @@ -+/* -+ * BCM2835 SD host driver. -+ * -+ * Author: Phil Elwell -+ * Copyright 2015 -+ * -+ * Based on -+ * mmc-bcm2835.c by Gellert Weisz -+ * which is, in turn, based on -+ * sdhci-bcm2708.c by Broadcom -+ * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko -+ * sdhci.c and sdhci-pci.c by Pierre Ossman -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#define SAFE_READ_THRESHOLD 4 -+#define SAFE_WRITE_THRESHOLD 4 -+#define ALLOW_DMA 1 -+#define ALLOW_CMD23 0 -+#define ALLOW_FAST 1 -+#define USE_BLOCK_IRQ 1 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "sdhost-bcm2835" -+ -+#define SDCMD 0x00 /* Command to SD card - 16 R/W */ -+#define SDARG 0x04 /* Argument to SD card - 32 R/W */ -+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ -+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ -+#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ -+#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ -+#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ -+#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ -+#define SDHSTS 0x20 /* SD host status - 11 R */ -+#define SDVDD 0x30 /* SD card power control - 1 R/W */ -+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ -+#define SDHCFG 0x38 /* Host configuration - 2 R/W */ -+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ -+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ -+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ -+ -+#define SDCMD_NEW_FLAG 0x8000 -+#define SDCMD_FAIL_FLAG 0x4000 -+#define SDCMD_BUSYWAIT 0x800 -+#define SDCMD_NO_RESPONSE 0x400 -+#define SDCMD_LONG_RESPONSE 0x200 -+#define SDCMD_WRITE_CMD 0x80 -+#define SDCMD_READ_CMD 0x40 -+#define SDCMD_CMD_MASK 0x3f -+ -+#define SDCDIV_MAX_CDIV 0x7ff -+ -+#define SDHSTS_BUSY_IRPT 0x400 -+#define SDHSTS_BLOCK_IRPT 0x200 -+#define SDHSTS_SDIO_IRPT 0x100 -+#define SDHSTS_REW_TIME_OUT 0x80 -+#define SDHSTS_CMD_TIME_OUT 0x40 -+#define SDHSTS_CRC16_ERROR 0x20 -+#define SDHSTS_CRC7_ERROR 0x10 -+#define SDHSTS_FIFO_ERROR 0x08 -+/* Reserved */ -+/* Reserved */ -+#define SDHSTS_DATA_FLAG 0x01 -+ -+#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) -+#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) -+/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ -+ -+#define SDHCFG_BUSY_IRPT_EN (1<<10) -+#define SDHCFG_BLOCK_IRPT_EN (1<<8) -+#define SDHCFG_SDIO_IRPT_EN (1<<5) -+#define SDHCFG_DATA_IRPT_EN (1<<4) -+#define SDHCFG_SLOW_CARD (1<<3) -+#define SDHCFG_WIDE_EXT_BUS (1<<2) -+#define SDHCFG_WIDE_INT_BUS (1<<1) -+#define SDHCFG_REL_CMD_LINE (1<<0) -+ -+#define SDEDM_FORCE_DATA_MODE (1<<19) -+#define SDEDM_CLOCK_PULSE (1<<20) -+#define SDEDM_BYPASS (1<<21) -+ -+#define SDEDM_WRITE_THRESHOLD_SHIFT 9 -+#define SDEDM_READ_THRESHOLD_SHIFT 14 -+#define SDEDM_THRESHOLD_MASK 0x1f -+ -+/* the inclusive limit in bytes under which PIO will be used instead of DMA */ -+#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER -+#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER -+#else -+#define PIO_DMA_BARRIER 0 -+#endif -+ -+#define MIN_FREQ 400000 -+#define TIMEOUT_VAL 0xE -+#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) -+ -+#ifndef BCM2708_PERI_BASE -+ #define BCM2708_PERI_BASE 0x20000000 -+#endif -+ -+/* FIXME: Needs IOMMU support */ -+#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) -+ -+ -+struct bcm2835_host { -+ spinlock_t lock; -+ -+ void __iomem *ioaddr; -+ u32 phys_addr; -+ -+ struct mmc_host *mmc; -+ -+ u32 timeout; -+ -+ int clock; /* Current clock speed */ -+ -+ bool slow_card; /* Force 11-bit divisor */ -+ -+ unsigned int max_clk; /* Max possible freq */ -+ unsigned int timeout_clk; /* Timeout freq (KHz) */ -+ -+ struct tasklet_struct finish_tasklet; /* Tasklet structures */ -+ -+ struct timer_list timer; /* Timer for timeouts */ -+ -+ struct sg_mapping_iter sg_miter; /* SG state for PIO */ -+ unsigned int blocks; /* remaining PIO blocks */ -+ -+ int irq; /* Device IRQ */ -+ -+ -+ /* cached registers */ -+ u32 hcfg; -+ u32 cdiv; -+ -+ struct mmc_request *mrq; /* Current request */ -+ struct mmc_command *cmd; /* Current command */ -+ struct mmc_data *data; /* Current data request */ -+ unsigned int data_complete:1; /* Data finished before cmd */ -+ -+ unsigned int flush_fifo:1; /* Drain the fifo when finishing */ -+ -+ unsigned int use_busy:1; /* Wait for busy interrupt */ -+ -+ u32 thread_isr; -+ -+ /*DMA part*/ -+ struct dma_chan *dma_chan_rx; /* DMA channel for reads */ -+ struct dma_chan *dma_chan_tx; /* DMA channel for writes */ -+ -+ bool allow_dma; -+ bool have_dma; -+ bool use_dma; -+ /*end of DMA part*/ -+ -+ int max_delay; /* maximum length of time spent waiting */ -+ struct timeval stop_time; /* when the last stop was issued */ -+ u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ -+}; -+ -+ -+static inline void bcm2835_sdhost_write(struct bcm2835_host *host, u32 val, int reg) -+{ -+ writel(val, host->ioaddr + reg); -+} -+ -+static inline u32 bcm2835_sdhost_read(struct bcm2835_host *host, int reg) -+{ -+ return readl(host->ioaddr + reg); -+} -+ -+static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg) -+{ -+ return readl_relaxed(host->ioaddr + reg); -+} -+ -+static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) -+{ -+ pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", -+ mmc_hostname(host->mmc)); -+ -+ pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", -+ bcm2835_sdhost_read(host, SDCMD)); -+ pr_info(DRIVER_NAME ": SDARG 0x%08x\n", -+ bcm2835_sdhost_read(host, SDARG)); -+ pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", -+ bcm2835_sdhost_read(host, SDTOUT)); -+ pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", -+ bcm2835_sdhost_read(host, SDCDIV)); -+ pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP0)); -+ pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP1)); -+ pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP2)); -+ pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", -+ bcm2835_sdhost_read(host, SDRSP3)); -+ pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHSTS)); -+ pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", -+ bcm2835_sdhost_read(host, SDVDD)); -+ pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", -+ bcm2835_sdhost_read(host, SDEDM)); -+ pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHCFG)); -+ pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHBCT)); -+ pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", -+ bcm2835_sdhost_read(host, SDHBLC)); -+ -+ pr_debug(DRIVER_NAME ": ===========================================\n"); -+} -+ -+ -+static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) -+{ -+ bcm2835_sdhost_write(host, on ? 1 : 0, SDVDD); -+} -+ -+ -+static void bcm2835_sdhost_reset(struct bcm2835_host *host) -+{ -+ u32 temp; -+ -+ pr_debug("bcm2835_sdhost_reset\n"); -+ -+ bcm2835_sdhost_set_power(host, false); -+ -+ bcm2835_sdhost_write(host, 0, SDCMD); -+ bcm2835_sdhost_write(host, 0, SDARG); -+ bcm2835_sdhost_write(host, 0xf00000, SDTOUT); -+ bcm2835_sdhost_write(host, 0, SDCDIV); -+ bcm2835_sdhost_write(host, 0x7f8, SDHSTS); /* Write 1s to clear */ -+ bcm2835_sdhost_write(host, 0, SDHCFG); -+ bcm2835_sdhost_write(host, 0, SDHBCT); -+ bcm2835_sdhost_write(host, 0, SDHBLC); -+ -+ /* Limit fifo usage due to silicon bug */ -+ temp = bcm2835_sdhost_read(host, SDEDM); -+ temp &= ~((SDEDM_THRESHOLD_MASK<clock = 0; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ mmiowb(); -+} -+ -+static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); -+ -+static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) -+{ -+ pr_debug("bcm2835_sdhost_init(%d)\n", soft); -+ -+ /* Set interrupt enables */ -+ host->hcfg = SDHCFG_BUSY_IRPT_EN; -+ -+ bcm2835_sdhost_reset(host); -+ -+ if (soft) { -+ /* force clock reconfiguration */ -+ host->clock = 0; -+ bcm2835_sdhost_set_ios(host->mmc, &host->mmc->ios); -+ } -+} -+ -+static bool bcm2835_sdhost_is_write_complete(struct bcm2835_host *host) -+{ -+ bool write_complete = ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1); -+ -+ if (!write_complete) { -+ /* Request an IRQ for the last block */ -+ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ if ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1) { -+ /* The write has now completed. Disable the interrupt -+ and clear the status flag */ -+ host->hcfg &= ~SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ bcm2835_sdhost_write(host, SDHSTS_BLOCK_IRPT, SDHSTS); -+ write_complete = true; -+ } -+ } -+ -+ return write_complete; -+} -+ -+static void bcm2835_sdhost_wait_write_complete(struct bcm2835_host *host) -+{ -+ int timediff; -+#ifdef DEBUG -+ static struct timeval start_time; -+ static int max_stall_time = 0; -+ static int total_stall_time = 0; -+ struct timeval before, after; -+ -+ do_gettimeofday(&before); -+ if (max_stall_time == 0) -+ start_time = before; -+#endif -+ -+ timediff = 0; -+ -+ while (1) { -+ u32 edm = bcm2835_sdhost_read(host, SDEDM); -+ if ((edm & 0xf) == 1) -+ break; -+ timediff++; -+ if (timediff > 5000000) { -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + -+ (after.tv_usec - before.tv_usec); -+ -+ pr_err(" wait_write_complete - still waiting after %dus\n", -+ timediff); -+#else -+ pr_err(" wait_write_complete - still waiting after %d retries\n", -+ timediff); -+#endif -+ bcm2835_sdhost_dumpregs(host); -+ host->data->error = -ETIMEDOUT; -+ return; -+ } -+ } -+ -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + (after.tv_usec - before.tv_usec); -+ -+ total_stall_time += timediff; -+ if (timediff > max_stall_time) -+ max_stall_time = timediff; -+ -+ if ((after.tv_sec - start_time.tv_sec) > 10) { -+ pr_debug(" wait_write_complete - max wait %dus, total %dus\n", -+ max_stall_time, total_stall_time); -+ start_time = after; -+ max_stall_time = 0; -+ total_stall_time = 0; -+ } -+#endif -+} -+ -+static void bcm2835_sdhost_finish_data(struct bcm2835_host *host); -+ -+static void bcm2835_sdhost_dma_complete(void *param) -+{ -+ struct bcm2835_host *host = param; -+ struct dma_chan *dma_chan; -+ unsigned long flags; -+ u32 dir_data; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (host->data) { -+ bool write_complete; -+ if (USE_BLOCK_IRQ) -+ write_complete = bcm2835_sdhost_is_write_complete(host); -+ else { -+ bcm2835_sdhost_wait_write_complete(host); -+ write_complete = true; -+ } -+ pr_debug("dma_complete() - write_complete=%d\n", -+ write_complete); -+ -+ if (write_complete || (host->data->flags & MMC_DATA_READ)) -+ { -+ if (write_complete) { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ } else { -+ dma_chan = host->dma_chan_rx; -+ dir_data = DMA_FROM_DEVICE; -+ } -+ -+ dma_unmap_sg(dma_chan->device->dev, -+ host->data->sg, host->data->sg_len, -+ dir_data); -+ -+ bcm2835_sdhost_finish_data(host); -+ } -+ } -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) -+{ -+ unsigned long flags; -+ size_t blksize, len; -+ u32 *buf; -+ -+ blksize = host->data->blksz; -+ -+ local_irq_save(flags); -+ -+ while (blksize) { -+ if (!sg_miter_next(&host->sg_miter)) -+ BUG(); -+ -+ len = min(host->sg_miter.length, blksize); -+ BUG_ON(len % 4); -+ -+ blksize -= len; -+ host->sg_miter.consumed = len; -+ -+ buf = (u32 *)host->sg_miter.addr; -+ -+ while (len) { -+ while (1) { -+ u32 hsts; -+ hsts = bcm2835_sdhost_read(host, SDHSTS); -+ if (hsts & SDHSTS_DATA_FLAG) -+ break; -+ -+ if (hsts & SDHSTS_ERROR_MASK) { -+ pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", -+ mmc_hostname(host->mmc), -+ hsts, -+ bcm2835_sdhost_read(host, SDHBCT), -+ blksize + len); -+ if (hsts & SDHSTS_REW_TIME_OUT) -+ host->data->error = -ETIMEDOUT; -+ else if (hsts & (SDHSTS_CRC16_ERROR || -+ SDHSTS_CRC7_ERROR)) -+ host->data->error = -EILSEQ; -+ else { -+ pr_err("%s: unexpected data error\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ } -+ } -+ } -+ -+ *(buf++) = bcm2835_sdhost_read(host, SDDATA); -+ len -= 4; -+ } -+ } -+ -+ sg_miter_stop(&host->sg_miter); -+ -+ local_irq_restore(flags); -+} -+ -+static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) -+{ -+ unsigned long flags; -+ size_t blksize, len; -+ u32 *buf; -+ -+ blksize = host->data->blksz; -+ -+ local_irq_save(flags); -+ -+ while (blksize) { -+ if (!sg_miter_next(&host->sg_miter)) -+ BUG(); -+ -+ len = min(host->sg_miter.length, blksize); -+ BUG_ON(len % 4); -+ -+ blksize -= len; -+ host->sg_miter.consumed = len; -+ -+ buf = host->sg_miter.addr; -+ -+ while (len) { -+ while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) -+ continue; -+ bcm2835_sdhost_write(host, *(buf++), SDDATA); -+ len -= 4; -+ } -+ } -+ -+ sg_miter_stop(&host->sg_miter); -+ -+ local_irq_restore(flags); -+} -+ -+ -+static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) -+{ -+ BUG_ON(!host->data); -+ -+ if (host->data->flags & MMC_DATA_READ) -+ bcm2835_sdhost_read_block_pio(host); -+ else -+ bcm2835_sdhost_write_block_pio(host); -+} -+ -+ -+static void bcm2835_sdhost_transfer_dma(struct bcm2835_host *host) -+{ -+ u32 len, dir_data, dir_slave; -+ struct dma_async_tx_descriptor *desc = NULL; -+ struct dma_chan *dma_chan; -+ -+ pr_debug("bcm2835_sdhost_transfer_dma()\n"); -+ -+ WARN_ON(!host->data); -+ -+ if (!host->data) -+ return; -+ -+ if (host->data->flags & MMC_DATA_READ) { -+ dma_chan = host->dma_chan_rx; -+ dir_data = DMA_FROM_DEVICE; -+ dir_slave = DMA_DEV_TO_MEM; -+ } else { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ dir_slave = DMA_MEM_TO_DEV; -+ } -+ -+ BUG_ON(!dma_chan->device); -+ BUG_ON(!dma_chan->device->dev); -+ BUG_ON(!host->data->sg); -+ -+ len = dma_map_sg(dma_chan->device->dev, host->data->sg, -+ host->data->sg_len, dir_data); -+ if (len > 0) { -+ desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg, -+ len, dir_slave, -+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -+ } else { -+ dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); -+ } -+ if (desc) { -+ desc->callback = bcm2835_sdhost_dma_complete; -+ desc->callback_param = host; -+ dmaengine_submit(desc); -+ dma_async_issue_pending(dma_chan); -+ } -+ -+} -+ -+ -+static void bcm2835_sdhost_set_transfer_irqs(struct bcm2835_host *host) -+{ -+ u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN | -+ SDHCFG_BUSY_IRPT_EN; -+ if (host->use_dma) -+ host->hcfg = (host->hcfg & ~all_irqs) | -+ SDHCFG_BUSY_IRPT_EN; -+ else -+ host->hcfg = (host->hcfg & ~all_irqs) | -+ SDHCFG_DATA_IRPT_EN | -+ SDHCFG_BUSY_IRPT_EN; -+ -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+} -+ -+ -+static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd) -+{ -+ struct mmc_data *data = cmd->data; -+ -+ WARN_ON(host->data); -+ -+ if (!data) -+ return; -+ -+ /* Sanity checks */ -+ BUG_ON(data->blksz * data->blocks > 524288); -+ BUG_ON(data->blksz > host->mmc->max_blk_size); -+ BUG_ON(data->blocks > 65535); -+ -+ host->data = data; -+ host->data_complete = 0; -+ host->flush_fifo = 0; -+ host->data->bytes_xfered = 0; -+ -+ if (!host->use_dma) { -+ int flags; -+ -+ flags = SG_MITER_ATOMIC; -+ if (data->flags & MMC_DATA_READ) -+ flags |= SG_MITER_TO_SG; -+ else -+ flags |= SG_MITER_FROM_SG; -+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); -+ host->blocks = data->blocks; -+ } -+ -+ host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; -+ -+ bcm2835_sdhost_set_transfer_irqs(host); -+ -+ bcm2835_sdhost_write(host, data->blksz, SDHBCT); -+ if (host->use_dma) -+ bcm2835_sdhost_write(host, data->blocks, SDHBLC); -+ -+ BUG_ON(!host->data); -+} -+ -+ -+void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd) -+{ -+ u32 sdcmd; -+ unsigned long timeout; -+ -+ WARN_ON(host->cmd); -+ -+ if (1) { -+ pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", -+ cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); -+ if (cmd->data) -+ pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", -+ (cmd->data->flags & MMC_DATA_READ) ? -+ "read" : "write", cmd->data->blocks, -+ cmd->data->blksz); -+ } -+ -+ /* Wait max 10 ms */ -+ timeout = 1000; -+ -+ while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { -+ if (timeout == 0) { -+ pr_err("%s: Previous command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ timeout--; -+ udelay(10); -+ } -+ -+ if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { -+ host->max_delay = (1000-timeout)/100; -+ pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); -+ } -+ -+ timeout = jiffies; -+#ifdef CONFIG_ARCH_BCM2835 -+ if (!cmd->data && cmd->busy_timeout > 9000) -+ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; -+ else -+#endif -+ timeout += 10 * HZ; -+ mod_timer(&host->timer, timeout); -+ -+ host->cmd = cmd; -+ -+ bcm2835_sdhost_prepare_data(host, cmd); -+ -+ bcm2835_sdhost_write(host, cmd->arg, SDARG); -+ -+ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { -+ pr_err("%s: Unsupported response type!\n", -+ mmc_hostname(host->mmc)); -+ cmd->error = -EINVAL; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ sdcmd = cmd->opcode & SDCMD_CMD_MASK; -+ -+ if (!(cmd->flags & MMC_RSP_PRESENT)) -+ sdcmd |= SDCMD_NO_RESPONSE; -+ else { -+ if (cmd->flags & MMC_RSP_136) -+ sdcmd |= SDCMD_LONG_RESPONSE; -+ if (cmd->flags & MMC_RSP_BUSY) { -+ sdcmd |= SDCMD_BUSYWAIT; -+ host->use_busy = 1; -+ } -+ } -+ -+ if (cmd->data) { -+ if (host->delay_after_stop) { -+ struct timeval now; -+ int time_since_stop; -+ do_gettimeofday(&now); -+ time_since_stop = (now.tv_sec - host->stop_time.tv_sec); -+ if (time_since_stop < 2) { -+ /* Possibly less than one second */ -+ time_since_stop = time_since_stop * 1000000 + -+ (now.tv_usec - host->stop_time.tv_usec); -+ if (time_since_stop < host->delay_after_stop) -+ udelay(host->delay_after_stop - -+ time_since_stop); -+ } -+ } -+ -+ if (cmd->data->flags & MMC_DATA_WRITE) -+ sdcmd |= SDCMD_WRITE_CMD; -+ if (cmd->data->flags & MMC_DATA_READ) -+ sdcmd |= SDCMD_READ_CMD; -+ } -+ -+ bcm2835_sdhost_write(host, sdcmd | SDCMD_NEW_FLAG, SDCMD); -+} -+ -+ -+static void bcm2835_sdhost_finish_command(struct bcm2835_host *host); -+static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host); -+ -+static void bcm2835_sdhost_finish_data(struct bcm2835_host *host) -+{ -+ struct mmc_data *data; -+ -+ data = host->data; -+ BUG_ON(!data); -+ -+ pr_debug("finish_data(error %d, stop %d, sbc %d)\n", -+ data->error, data->stop ? 1 : 0, -+ host->mrq->sbc ? 1 : 0); -+ -+ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ -+ if (data->error) { -+ data->bytes_xfered = 0; -+ } else -+ data->bytes_xfered = data->blksz * data->blocks; -+ -+ host->data_complete = 1; -+ -+ if (host->cmd) { -+ /* -+ * Data managed to finish before the -+ * command completed. Make sure we do -+ * things in the proper order. -+ */ -+ pr_debug("Finished early - HSTS %x\n", -+ bcm2835_sdhost_read(host, SDHSTS)); -+ } -+ else -+ bcm2835_sdhost_transfer_complete(host); -+} -+ -+ -+static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) -+{ -+ struct mmc_data *data; -+ -+ BUG_ON(host->cmd); -+ BUG_ON(!host->data); -+ BUG_ON(!host->data_complete); -+ -+ data = host->data; -+ host->data = NULL; -+ -+ pr_debug("transfer_complete(error %d, stop %d)\n", -+ data->error, data->stop ? 1 : 0); -+ -+ if (data->error) -+ /* -+ * The controller needs a reset of internal state machines -+ * upon error conditions. -+ */ -+ bcm2835_sdhost_reset(host); -+ -+ /* -+ * Need to send CMD12 if - -+ * a) open-ended multiblock transfer (no CMD23) -+ * b) error in multiblock transfer -+ */ -+ if (data->stop && -+ (data->error || -+ !host->mrq->sbc)) { -+ host->flush_fifo = 1; -+ bcm2835_sdhost_send_command(host, data->stop); -+ if (host->delay_after_stop) -+ do_gettimeofday(&host->stop_time); -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+ } else { -+ tasklet_schedule(&host->finish_tasklet); -+ } -+} -+ -+static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) -+{ -+ u32 sdcmd; -+ int timeout = 1000; -+#ifdef DEBUG -+ struct timeval before, after; -+ int timediff = 0; -+#endif -+ -+ pr_debug("finish_command(%x)\n", bcm2835_sdhost_read(host, SDCMD)); -+ -+ BUG_ON(!host->cmd || !host->mrq); -+ -+#ifdef DEBUG -+ do_gettimeofday(&before); -+#endif -+ for (sdcmd = bcm2835_sdhost_read(host, SDCMD); -+ (sdcmd & SDCMD_NEW_FLAG) && timeout; -+ timeout--) { -+ if (host->flush_fifo) { -+ while (bcm2835_sdhost_read(host, SDHSTS) & -+ SDHSTS_DATA_FLAG) -+ (void)bcm2835_sdhost_read(host, SDDATA); -+ } -+ udelay(10); -+ sdcmd = bcm2835_sdhost_read(host, SDCMD); -+ } -+#ifdef DEBUG -+ do_gettimeofday(&after); -+ timediff = (after.tv_sec - before.tv_sec)*1000000 + -+ (after.tv_usec - before.tv_usec); -+ -+ pr_debug(" finish_command - waited %dus\n", timediff); -+#endif -+ -+ if (timeout == 0) { -+ pr_err("%s: Command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ if (host->flush_fifo) { -+ for (timeout = 100; -+ (bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG) && timeout; -+ timeout--) { -+ (void)bcm2835_sdhost_read(host, SDDATA); -+ } -+ host->flush_fifo = 0; -+ if (timeout == 0) { -+ pr_err("%s: FIFO never drained.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ } -+ -+ /* Check for errors */ -+ if (sdcmd & SDCMD_FAIL_FLAG) -+ { -+ u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); -+ -+ pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", -+ mmc_hostname(host->mmc), sdcmd, sdhsts, -+ bcm2835_sdhost_read(host, SDEDM)); -+ -+ if (sdhsts & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else -+ { -+ pr_err("%s: unexpected command error\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; -+ } -+ tasklet_schedule(&host->finish_tasklet); -+ return; -+ } -+ -+ if (host->cmd->flags & MMC_RSP_PRESENT) { -+ if (host->cmd->flags & MMC_RSP_136) { -+ int i; -+ for (i = 0; i < 4; i++) -+ host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); -+ pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", -+ host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); -+ } else { -+ host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); -+ pr_debug("bcm2835_sdhost_finish_command: %08x\n", -+ host->cmd->resp[0]); -+ } -+ } -+ -+ host->cmd->error = 0; -+ -+ if (host->cmd == host->mrq->sbc) { -+ /* Finished CMD23, now send actual command. */ -+ host->cmd = NULL; -+ bcm2835_sdhost_send_command(host, host->mrq->cmd); -+ -+ if (host->cmd->data && host->use_dma) -+ /* DMA transfer starts now, PIO starts after irq */ -+ bcm2835_sdhost_transfer_dma(host); -+ -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+ } else if (host->cmd == host->mrq->stop) -+ /* Finished CMD12 */ -+ tasklet_schedule(&host->finish_tasklet); -+ else { -+ /* Processed actual command. */ -+ host->cmd = NULL; -+ if (!host->data) -+ tasklet_schedule(&host->finish_tasklet); -+ else if (host->data_complete) -+ bcm2835_sdhost_transfer_complete(host); -+ } -+} -+ -+static void bcm2835_sdhost_timeout_timer(unsigned long data) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ -+ host = (struct bcm2835_host *)data; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (host->mrq) { -+ pr_err("%s: Timeout waiting for hardware interrupt.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ -+ if (host->data) { -+ host->data->error = -ETIMEDOUT; -+ bcm2835_sdhost_finish_data(host); -+ } else { -+ if (host->cmd) -+ host->cmd->error = -ETIMEDOUT; -+ else -+ host->mrq->cmd->error = -ETIMEDOUT; -+ -+ pr_debug("timeout_timer tasklet_schedule\n"); -+ tasklet_schedule(&host->finish_tasklet); -+ } -+ } -+ -+ mmiowb(); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) -+{ -+ if (enable) -+ host->hcfg |= SDHCFG_SDIO_IRPT_EN; -+ else -+ host->hcfg &= ~SDHCFG_SDIO_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ mmiowb(); -+} -+ -+static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) -+{ -+ struct bcm2835_host *host = mmc_priv(mmc); -+ unsigned long flags; -+ -+ pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); -+ spin_lock_irqsave(&host->lock, flags); -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ if (!host->cmd) { -+ pr_err("%s: Got command busy interrupt 0x%08x even " -+ "though no command operation was in progress.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return 0; -+ } -+ -+ if (!host->use_busy) { -+ pr_err("%s: Got command busy interrupt 0x%08x even " -+ "though not expecting one.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return 0; -+ } -+ host->use_busy = 0; -+ -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | -+ SDHSTS_FIFO_ERROR)) -+ host->cmd->error = -EILSEQ; -+ -+ if (host->cmd->error) -+ tasklet_schedule(&host->finish_tasklet); -+ else -+ bcm2835_sdhost_finish_command(host); -+ -+ return handled; -+} -+ -+static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ /* There are no dedicated data/space available interrupt -+ status bits, so it is necessary to use the single shared -+ data/space available FIFO status bits. It is therefore not -+ an error to get here when there is no data transfer in -+ progress. */ -+ if (!host->data) -+ return 0; -+ -+ // XXX FIFO_ERROR -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && -+ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) -+ != MMC_BUS_TEST_R)) -+ host->cmd->error = -EILSEQ; -+ -+ /* Use the block interrupt for writes after the first block */ -+ if (!(host->data->flags & MMC_DATA_READ)) { -+ host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); -+ host->hcfg |= SDHCFG_BLOCK_IRPT_EN; -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ if (host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ bcm2835_sdhost_transfer_pio(host); -+ } else { -+ if (!host->data->error) { -+ bcm2835_sdhost_transfer_pio(host); -+ host->blocks--; -+ } -+ if ((host->blocks == 0) || host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ } -+ -+ return handled; -+} -+ -+static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) -+{ -+ struct dma_chan *dma_chan; -+ u32 dir_data; -+ const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | -+ SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); -+ -+ if (!host->data) { -+ pr_err("%s: Got block interrupt 0x%08x even " -+ "though no data operation was in progress.\n", -+ mmc_hostname(host->mmc), (unsigned)intmask); -+ bcm2835_sdhost_dumpregs(host); -+ return handled; -+ } -+ -+ if (intmask & SDHSTS_CMD_TIME_OUT) -+ host->cmd->error = -ETIMEDOUT; -+ else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && -+ ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) -+ != MMC_BUS_TEST_R)) -+ host->cmd->error = -EILSEQ; -+ -+ if (!host->use_dma) { -+ BUG_ON(!host->blocks); -+ host->blocks--; -+ if ((host->blocks == 0) || host->data->error) -+ bcm2835_sdhost_finish_data(host); -+ else -+ bcm2835_sdhost_transfer_pio(host); -+ } else if (host->data->flags & MMC_DATA_WRITE) { -+ dma_chan = host->dma_chan_tx; -+ dir_data = DMA_TO_DEVICE; -+ dma_unmap_sg(dma_chan->device->dev, -+ host->data->sg, host->data->sg_len, -+ dir_data); -+ -+ bcm2835_sdhost_finish_data(host); -+ } -+ -+ return handled; -+} -+ -+ -+static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) -+{ -+ irqreturn_t result = IRQ_NONE; -+ struct bcm2835_host *host = dev_id; -+ u32 unexpected = 0, early = 0; -+ int loops = 0; -+#ifndef CONFIG_ARCH_BCM2835 -+ int cardint = 0; -+#endif -+ spin_lock(&host->lock); -+ -+ for (loops = 0; loops < 1; loops++) { -+ u32 intmask, handled; -+ -+ intmask = bcm2835_sdhost_read(host, SDHSTS); -+ handled = intmask & (SDHSTS_BUSY_IRPT | -+ SDHSTS_BLOCK_IRPT | -+ SDHSTS_SDIO_IRPT | -+ SDHSTS_DATA_FLAG); -+ if ((handled == SDHSTS_DATA_FLAG) && // XXX -+ (loops == 0) && !host->data) { -+ pr_err("%s: sdhost_irq data interrupt 0x%08x even " -+ "though no data operation was in progress.\n", -+ mmc_hostname(host->mmc), -+ (unsigned)intmask); -+ -+ bcm2835_sdhost_dumpregs(host); -+ } -+ -+ if (loops) -+ early |= handled; -+ -+ if (!handled) -+ break; -+ -+ result = IRQ_HANDLED; -+ -+ /* Clear all interrupts and notifications */ -+ bcm2835_sdhost_write(host, intmask, SDHSTS); -+ -+ if (intmask & SDHSTS_BUSY_IRPT) -+ handled |= bcm2835_sdhost_busy_irq(host, intmask); -+ -+ /* There is no true data interrupt status bit, so it is -+ necessary to qualify the data flag with the interrupt -+ enable bit */ -+ if ((intmask & SDHSTS_DATA_FLAG) && -+ (host->hcfg & SDHCFG_DATA_IRPT_EN)) -+ handled |= bcm2835_sdhost_data_irq(host, intmask); -+ -+ if (intmask & SDHSTS_BLOCK_IRPT) -+ handled |= bcm2835_sdhost_block_irq(host, intmask); -+ -+ if (intmask & SDHSTS_SDIO_IRPT) { -+#ifndef CONFIG_ARCH_BCM2835 -+ cardint = 1; -+#else -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, false); -+ host->thread_isr |= SDHSTS_SDIO_IRPT; -+ result = IRQ_WAKE_THREAD; -+#endif -+ } -+ -+ unexpected |= (intmask & ~handled); -+ } -+ -+ mmiowb(); -+ -+ spin_unlock(&host->lock); -+ -+ if (early) -+ pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); -+ -+ if (unexpected) { -+ pr_err("%s: Unexpected interrupt 0x%08x.\n", -+ mmc_hostname(host->mmc), unexpected); -+ bcm2835_sdhost_dumpregs(host); -+ } -+ -+#ifndef CONFIG_ARCH_BCM2835 -+ if (cardint) -+ mmc_signal_sdio_irq(host->mmc); -+#endif -+ -+ return result; -+} -+ -+#ifdef CONFIG_ARCH_BCM2835 -+static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) -+{ -+ struct bcm2835_host *host = dev_id; -+ unsigned long flags; -+ u32 isr; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ isr = host->thread_isr; -+ host->thread_isr = 0; -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ if (isr & SDHSTS_SDIO_IRPT) { -+ sdio_run_irqs(host->mmc); -+ -+/* Is this necessary? Why re-enable an interrupt which is enabled? -+ spin_lock_irqsave(&host->lock, flags); -+ if (host->flags & SDHSTS_SDIO_IRPT_ENABLED) -+ bcm2835_sdhost_enable_sdio_irq_nolock(host, true); -+ spin_unlock_irqrestore(&host->lock, flags); -+*/ -+ } -+ -+ return isr ? IRQ_HANDLED : IRQ_NONE; -+} -+#endif -+ -+ -+ -+void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) -+{ -+ int div = 0; /* Initialized for compiler warning */ -+ -+ /* The SDCDIV register has 11 bits, and holds (div - 2). -+ But in data mode the max is 50MHz wihout a minimum, and only the -+ bottom 3 bits are used. Since the switch over is automatic (unless -+ we have marked the card as slow...), chosen values have to make -+ sense in both modes. -+ Ident mode must be 100-400KHz, so can range check the requested -+ clock. CMD15 must be used to return to data mode, so this can be -+ monitored. -+ -+ clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz -+ 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz -+ -+ 623->400KHz/27.8MHz -+ reset value (507)->491159/50MHz -+ -+ BUT, the 3-bit clock divisor in data mode is too small if the -+ core clock is higher than 250MHz, so instead use the SLOW_CARD -+ configuration bit to force the use of the ident clock divisor -+ at all times. -+ */ -+ -+ host->mmc->actual_clock = 0; -+ -+ if (clock < 100000) { -+ /* Can't stop the clock, but make it as slow as possible -+ * to show willing -+ */ -+ host->cdiv = SDCDIV_MAX_CDIV; -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ return; -+ } -+ -+ div = host->max_clk / clock; -+ if (div < 2) -+ div = 2; -+ if ((host->max_clk / div) > clock) -+ div++; -+ div -= 2; -+ -+ if (div > SDCDIV_MAX_CDIV) -+ div = SDCDIV_MAX_CDIV; -+ -+ host->mmc->actual_clock = host->max_clk / (div + 2); -+ -+ host->cdiv = div; -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ -+ pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", -+ clock, host->max_clk, host->cdiv, host->mmc->actual_clock); -+} -+ -+static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ -+ if (1) { -+ struct mmc_command *cmd = mrq->cmd; -+ const char *src = "cmd"; -+ BUG_ON(!cmd); -+ pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", -+ src, cmd->opcode, cmd->arg, cmd->flags); -+ if (cmd->data) -+ pr_debug("bcm2835_sdhost_request: %s %d*%d\n", -+ (cmd->data->flags & MMC_DATA_READ) ? -+ "read" : "write", cmd->data->blocks, -+ cmd->data->blksz); -+ } -+ -+ if (mrq->data && !is_power_of_2(mrq->data->blksz)) { -+ pr_err("%s: Unsupported block size (%d bytes)\n", -+ mmc_hostname(mmc), mrq->data->blksz); -+ mrq->cmd->error = -EINVAL; -+ mmc_request_done(mmc, mrq); -+ return; -+ } -+ -+ host = mmc_priv(mmc); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ WARN_ON(host->mrq != NULL); -+ -+ host->mrq = mrq; -+ -+ if (mrq->sbc) -+ bcm2835_sdhost_send_command(host, mrq->sbc); -+ else -+ bcm2835_sdhost_send_command(host, mrq->cmd); -+ -+ mmiowb(); -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ if (!mrq->sbc && mrq->cmd->data && host->use_dma) -+ /* DMA transfer starts now, PIO starts after irq */ -+ bcm2835_sdhost_transfer_dma(host); -+ -+ if (!host->use_busy) -+ bcm2835_sdhost_finish_command(host); -+} -+ -+ -+static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ -+ struct bcm2835_host *host = mmc_priv(mmc); -+ unsigned long flags; -+ -+ pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", -+ ios->clock, ios->power_mode, ios->bus_width, -+ ios->timing, ios->signal_voltage, ios->drv_type); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ if (!ios->clock || ios->clock != host->clock) { -+ bcm2835_sdhost_set_clock(host, ios->clock); -+ host->clock = ios->clock; -+ } -+ -+ /* set bus width */ -+ host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; -+ if (ios->bus_width == MMC_BUS_WIDTH_4) -+ host->hcfg |= SDHCFG_WIDE_EXT_BUS; -+ -+ host->hcfg |= SDHCFG_WIDE_INT_BUS; -+ -+ /* Disable clever clock switching, to cope with fast core clocks */ -+ host->hcfg |= SDHCFG_SLOW_CARD; -+ -+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG); -+ -+ mmiowb(); -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+static int bcm2835_sdhost_multi_io_quirk(struct mmc_card *card, -+ unsigned int direction, -+ u32 blk_pos, int blk_size) -+{ -+ /* There is a bug in the host controller hardware that makes -+ reading the final sector of the card as part of a multiple read -+ problematic. Detect that case and shorten the read accordingly. -+ */ -+ /* csd.capacity is in weird units - convert to sectors */ -+ u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9)); -+ -+ if ((direction == MMC_DATA_READ) && -+ ((blk_pos + blk_size) == card_sectors)) -+ blk_size--; -+ -+ return blk_size; -+} -+ -+ -+static struct mmc_host_ops bcm2835_sdhost_ops = { -+ .request = bcm2835_sdhost_request, -+ .set_ios = bcm2835_sdhost_set_ios, -+ .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, -+ .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, -+}; -+ -+ -+static void bcm2835_sdhost_tasklet_finish(unsigned long param) -+{ -+ struct bcm2835_host *host; -+ unsigned long flags; -+ struct mmc_request *mrq; -+ -+ host = (struct bcm2835_host *)param; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ /* -+ * If this tasklet gets rescheduled while running, it will -+ * be run again afterwards but without any active request. -+ */ -+ if (!host->mrq) { -+ spin_unlock_irqrestore(&host->lock, flags); -+ return; -+ } -+ -+ del_timer(&host->timer); -+ -+ mrq = host->mrq; -+ -+ /* -+ * The controller needs a reset of internal state machines -+ * upon error conditions. -+ */ -+ if (((mrq->cmd && mrq->cmd->error) || -+ (mrq->data && (mrq->data->error || -+ (mrq->data->stop && mrq->data->stop->error))))) { -+ -+ bcm2835_sdhost_reset(host); -+ } -+ -+ host->mrq = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ -+ mmiowb(); -+ -+ spin_unlock_irqrestore(&host->lock, flags); -+ mmc_request_done(host->mmc, mrq); -+} -+ -+ -+ -+int bcm2835_sdhost_add_host(struct bcm2835_host *host) -+{ -+ struct mmc_host *mmc; -+ struct dma_slave_config cfg; -+ int ret; -+ -+ mmc = host->mmc; -+ -+ bcm2835_sdhost_reset(host); -+ -+ mmc->f_max = host->max_clk; -+ mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; -+ -+ /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ -+ host->timeout_clk = mmc->f_max / 1000; -+#ifdef CONFIG_ARCH_BCM2835 -+ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; -+#endif -+ /* host controller capabilities */ -+ mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | -+ MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | -+ MMC_CAP_NEEDS_POLL | -+ (ALLOW_CMD23 * MMC_CAP_CMD23); -+ -+ spin_lock_init(&host->lock); -+ -+ if (host->allow_dma) { -+ if (!host->dma_chan_tx || !host->dma_chan_rx || -+ IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { -+ pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); -+ host->have_dma = false; -+ } else { -+ pr_info("DMA channels allocated for the SDHost driver"); -+ host->have_dma = true; -+ -+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ cfg.slave_id = 13; /* DREQ channel */ -+ -+ cfg.direction = DMA_MEM_TO_DEV; -+ cfg.src_addr = 0; -+ cfg.dst_addr = host->phys_addr + SDDATA; -+ ret = dmaengine_slave_config(host->dma_chan_tx, &cfg); -+ -+ cfg.direction = DMA_DEV_TO_MEM; -+ cfg.src_addr = host->phys_addr + SDDATA; -+ cfg.dst_addr = 0; -+ ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); -+ } -+ } else { -+ pr_info("Forcing PIO mode\n"); -+ host->have_dma = false; -+ } -+ -+ mmc->max_segs = 128; -+ mmc->max_req_size = 524288; -+ mmc->max_seg_size = mmc->max_req_size; -+ mmc->max_blk_size = 512; -+ mmc->max_blk_count = 65535; -+ -+ /* report supported voltage ranges */ -+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; -+ -+ tasklet_init(&host->finish_tasklet, -+ bcm2835_sdhost_tasklet_finish, (unsigned long)host); -+ -+ setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); -+ -+ bcm2835_sdhost_init(host, 0); -+#ifndef CONFIG_ARCH_BCM2835 -+ ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, -+ mmc_hostname(mmc), host); -+#else -+ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, -+ IRQF_SHARED, mmc_hostname(mmc), host); -+#endif -+ if (ret) { -+ pr_err("%s: Failed to request IRQ %d: %d\n", -+ mmc_hostname(mmc), host->irq, ret); -+ goto untasklet; -+ } -+ -+ mmiowb(); -+ mmc_add_host(mmc); -+ -+ pr_info("Load BCM2835 SDHost driver\n"); -+ if (host->delay_after_stop) -+ pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", -+ host->delay_after_stop); -+ -+ return 0; -+ -+untasklet: -+ tasklet_kill(&host->finish_tasklet); -+ -+ return ret; -+} -+ -+static int bcm2835_sdhost_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *node = dev->of_node; -+ struct clk *clk; -+ struct resource *iomem; -+ struct bcm2835_host *host; -+ struct mmc_host *mmc; -+ int ret; -+ -+ pr_debug("bcm2835_sdhost_probe\n"); -+ mmc = mmc_alloc_host(sizeof(*host), dev); -+ if (!mmc) -+ return -ENOMEM; -+ -+ mmc->ops = &bcm2835_sdhost_ops; -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ host->timeout = msecs_to_jiffies(1000); -+ spin_lock_init(&host->lock); -+ -+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ host->ioaddr = devm_ioremap_resource(dev, iomem); -+ if (IS_ERR(host->ioaddr)) { -+ ret = PTR_ERR(host->ioaddr); -+ goto err; -+ } -+ -+ host->phys_addr = iomem->start + BCM2835_VCMMU_SHIFT; -+ pr_debug(" - ioaddr %lx, iomem->start %lx, phys_addr %lx\n", -+ (unsigned long)host->ioaddr, -+ (unsigned long)iomem->start, -+ (unsigned long)host->phys_addr); -+ -+ host->allow_dma = ALLOW_DMA; -+ -+ if (node) { -+ /* Read any custom properties */ -+ of_property_read_u32(node, -+ "brcm,delay-after-stop", -+ &host->delay_after_stop); -+ host->allow_dma = ALLOW_DMA && -+ !of_property_read_bool(node, "brcm,force-pio"); -+ } -+ -+ if (host->allow_dma) { -+ if (node) { -+ host->dma_chan_tx = -+ dma_request_slave_channel(dev, "tx"); -+ host->dma_chan_rx = -+ dma_request_slave_channel(dev, "rx"); -+ } else { -+ dma_cap_mask_t mask; -+ -+ dma_cap_zero(mask); -+ /* we don't care about the channel, any would work */ -+ dma_cap_set(DMA_SLAVE, mask); -+ host->dma_chan_tx = -+ dma_request_channel(mask, NULL, NULL); -+ host->dma_chan_rx = -+ dma_request_channel(mask, NULL, NULL); -+ } -+ } -+ -+ clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "could not get clk\n"); -+ ret = PTR_ERR(clk); -+ goto err; -+ } -+ -+ host->max_clk = clk_get_rate(clk); -+ -+ host->irq = platform_get_irq(pdev, 0); -+ if (host->irq <= 0) { -+ dev_err(dev, "get IRQ failed\n"); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ pr_debug(" - max_clk %lx, irq %d\n", -+ (unsigned long)host->max_clk, -+ (int)host->irq); -+ -+ if (node) -+ mmc_of_parse(mmc); -+ else -+ mmc->caps |= MMC_CAP_4_BIT_DATA; -+ -+ ret = bcm2835_sdhost_add_host(host); -+ if (ret) -+ goto err; -+ -+ platform_set_drvdata(pdev, host); -+ -+ pr_debug("bcm2835_sdhost_probe -> OK\n"); -+ -+ return 0; -+ -+err: -+ pr_debug("bcm2835_sdhost_probe -> err %d\n", ret); -+ mmc_free_host(mmc); -+ -+ return ret; -+} -+ -+static int bcm2835_sdhost_remove(struct platform_device *pdev) -+{ -+ struct bcm2835_host *host = platform_get_drvdata(pdev); -+ -+ pr_debug("bcm2835_sdhost_remove\n"); -+ -+ mmc_remove_host(host->mmc); -+ -+ bcm2835_sdhost_set_power(host, false); -+ -+ free_irq(host->irq, host); -+ -+ del_timer_sync(&host->timer); -+ -+ tasklet_kill(&host->finish_tasklet); -+ -+ mmc_free_host(host->mmc); -+ platform_set_drvdata(pdev, NULL); -+ -+ pr_debug("bcm2835_sdhost_remove - OK\n"); -+ return 0; -+} -+ -+ -+static const struct of_device_id bcm2835_sdhost_match[] = { -+ { .compatible = "brcm,bcm2835-sdhost" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, bcm2835_sdhost_match); -+ -+ -+ -+static struct platform_driver bcm2835_sdhost_driver = { -+ .probe = bcm2835_sdhost_probe, -+ .remove = bcm2835_sdhost_remove, -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = bcm2835_sdhost_match, -+ }, -+}; -+module_platform_driver(bcm2835_sdhost_driver); -+ -+MODULE_ALIAS("platform:sdhost-bcm2835"); -+MODULE_DESCRIPTION("BCM2835 SDHost driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Phil Elwell"); - -From 4504d17456cfc2f8b8b987d8709adcf759c8ea2d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:24:30 +0200 -Subject: [PATCH 122/216] BCM270x: Add memory and irq resources to dmaengine - device and DT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Prepare for merging of the legacy DMA API arch driver dma.c -with bcm2708-dmaengine by adding memory and irq resources both -to platform file device and Device Tree node. -Don't use BCM_DMAMAN_DRIVER_NAME so we don't have to include mach/dma.h - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 16 +++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 65 +++++++++++++++++++++++++++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 65 +++++++++++++++++++++++++++++++++-- - 3 files changed, 142 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index ff70c58..065a424 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -10,7 +10,23 @@ - - dma: dma@7e007000 { - compatible = "brcm,bcm2835-dma"; -+ reg = <0x7e007000 0xf00>; -+ interrupts = <1 16>, -+ <1 17>, -+ <1 18>, -+ <1 19>, -+ <1 20>, -+ <1 21>, -+ <1 22>, -+ <1 23>, -+ <1 24>, -+ <1 25>, -+ <1 26>, -+ <1 27>, -+ <1 28>; -+ - #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x7f35>; - }; - - intc: interrupt-controller { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index b848e4a..703215d 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -55,7 +55,6 @@ - #include - - #include --#include - #include - #include - -@@ -257,15 +256,77 @@ static struct resource bcm2708_dmaman_resources[] = { - }; - - static struct platform_device bcm2708_dmaman_device = { -- .name = BCM_DMAMAN_DRIVER_NAME, -+ .name = "bcm2708_dma", - .id = 0, /* first bcm2708_dma */ - .resource = bcm2708_dmaman_resources, - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), - }; - -+static struct resource bcm2708_dmaengine_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_DMA0, -+ .end = IRQ_DMA0, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA1, -+ .end = IRQ_DMA1, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA2, -+ .end = IRQ_DMA2, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA3, -+ .end = IRQ_DMA3, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA4, -+ .end = IRQ_DMA4, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA5, -+ .end = IRQ_DMA5, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA6, -+ .end = IRQ_DMA6, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA7, -+ .end = IRQ_DMA7, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA8, -+ .end = IRQ_DMA8, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA9, -+ .end = IRQ_DMA9, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA10, -+ .end = IRQ_DMA10, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA11, -+ .end = IRQ_DMA11, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA12, -+ .end = IRQ_DMA12, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ - static struct platform_device bcm2708_dmaengine_device = { - .name = "bcm2708-dmaengine", - .id = -1, -+ .resource = bcm2708_dmaengine_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), - }; - - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index dcad008..97116c3 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -56,7 +56,6 @@ - #include - - #include --#include - #include - #include - -@@ -267,15 +266,77 @@ static struct resource bcm2708_dmaman_resources[] = { - }; - - static struct platform_device bcm2708_dmaman_device = { -- .name = BCM_DMAMAN_DRIVER_NAME, -+ .name = "bcm2708_dma", - .id = 0, /* first bcm2708_dma */ - .resource = bcm2708_dmaman_resources, - .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), - }; - -+static struct resource bcm2708_dmaengine_resources[] = { -+ { -+ .start = DMA_BASE, -+ .end = DMA_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_DMA0, -+ .end = IRQ_DMA0, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA1, -+ .end = IRQ_DMA1, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA2, -+ .end = IRQ_DMA2, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA3, -+ .end = IRQ_DMA3, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA4, -+ .end = IRQ_DMA4, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA5, -+ .end = IRQ_DMA5, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA6, -+ .end = IRQ_DMA6, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA7, -+ .end = IRQ_DMA7, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA8, -+ .end = IRQ_DMA8, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA9, -+ .end = IRQ_DMA9, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA10, -+ .end = IRQ_DMA10, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA11, -+ .end = IRQ_DMA11, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = IRQ_DMA12, -+ .end = IRQ_DMA12, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ - static struct platform_device bcm2708_dmaengine_device = { - .name = "bcm2708-dmaengine", - .id = -1, -+ .resource = bcm2708_dmaengine_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), - }; - - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) - -From 4111e2c08fdfcfaa72b531689e2b9bc2b8c29453 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:25:43 +0200 -Subject: [PATCH 123/216] dmaengine: bcm2708: Merge with arch dma.c driver and - disable dma.c -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Merge the legacy DMA API driver with bcm2708-dmaengine. -This is done so we can use bcm2708_fb on ARCH_BCM2835 (mailbox -driver is also needed). - -Changes to the dma.c code: -- Use BIT() macro. -- Cutdown some comments to one line. -- Add mutex to vc_dmaman and use this, since the dev lock is locked - during probing of the engine part. -- Add global g_dmaman variable since drvdata is used by the engine part. -- Restructure for readability: - vc_dmaman_chan_alloc() - vc_dmaman_chan_free() - bcm_dma_chan_free() -- Restructure bcm_dma_chan_alloc() to simplify error handling. -- Use device irq resources instead of hardcoded bcm_dma_irqs table. -- Remove dev_dmaman_register() and code it directly. -- Remove dev_dmaman_deregister() and code it directly. -- Simplify bcm_dmaman_probe() using devm_* functions. -- Get dmachans from DT if available. -- Keep 'dma.dmachans' module argument name for backwards compatibility. - -Make it available on ARCH_BCM2835 as well. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/include/mach/dma.h | 96 +-------- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/include/mach/dma.h | 96 +-------- - drivers/dma/Kconfig | 9 +- - drivers/dma/bcm2708-dmaengine.c | 333 ++++++++++++++++++++++++++++-- - include/linux/platform_data/dma-bcm2708.h | 127 ++++++++++++ - 7 files changed, 457 insertions(+), 208 deletions(-) - create mode 100644 include/linux/platform_data/dma-bcm2708.h - -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 21e3521..454408c 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index d03e7b5..d826705 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -1,94 +1,2 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/dma.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- -- --#ifndef _MACH_BCM2708_DMA_H --#define _MACH_BCM2708_DMA_H -- --#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -- --/* DMA CS Control and Status bits */ --#define BCM2708_DMA_ACTIVE (1 << 0) --#define BCM2708_DMA_INT (1 << 2) --#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ --#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ --#define BCM2708_DMA_ERR (1 << 8) --#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ --#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -- --/* DMA control block "info" field bits */ --#define BCM2708_DMA_INT_EN (1 << 0) --#define BCM2708_DMA_TDMODE (1 << 1) --#define BCM2708_DMA_WAIT_RESP (1 << 3) --#define BCM2708_DMA_D_INC (1 << 4) --#define BCM2708_DMA_D_WIDTH (1 << 5) --#define BCM2708_DMA_D_DREQ (1 << 6) --#define BCM2708_DMA_S_INC (1 << 8) --#define BCM2708_DMA_S_WIDTH (1 << 9) --#define BCM2708_DMA_S_DREQ (1 << 10) -- --#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) --#define BCM2708_DMA_PER_MAP(x) ((x) << 16) --#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -- --#define BCM2708_DMA_DREQ_EMMC 11 --#define BCM2708_DMA_DREQ_SDHOST 13 -- --#define BCM2708_DMA_CS 0x00 /* Control and Status */ --#define BCM2708_DMA_ADDR 0x04 --/* the current control block appears in the following registers - read only */ --#define BCM2708_DMA_INFO 0x08 --#define BCM2708_DMA_SOURCE_AD 0x0c --#define BCM2708_DMA_DEST_AD 0x10 --#define BCM2708_DMA_NEXTCB 0x1C --#define BCM2708_DMA_DEBUG 0x20 -- --#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) --#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -- --#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -- --struct bcm2708_dma_cb { -- unsigned long info; -- unsigned long src; -- unsigned long dst; -- unsigned long length; -- unsigned long stride; -- unsigned long next; -- unsigned long pad[2]; --}; --struct scatterlist; -- --extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); --extern void bcm_dma_start(void __iomem *dma_chan_base, -- dma_addr_t control_block); --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); --extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -- --/* When listing features we can ask for when allocating DMA channels give -- those with higher priority smaller ordinal numbers */ --#define BCM_DMA_FEATURE_FAST_ORD 0 --#define BCM_DMA_FEATURE_BULK_ORD 1 --#define BCM_DMA_FEATURE_NORMAL_ORD 2 --#define BCM_DMA_FEATURE_LITE_ORD 3 --#define BCM_DMA_FEATURE_FAST (1< -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 2a803bb..f07c38b 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -index d03e7b5..d826705 100644 ---- a/arch/arm/mach-bcm2709/include/mach/dma.h -+++ b/arch/arm/mach-bcm2709/include/mach/dma.h -@@ -1,94 +1,2 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/dma.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- -- --#ifndef _MACH_BCM2708_DMA_H --#define _MACH_BCM2708_DMA_H -- --#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" -- --/* DMA CS Control and Status bits */ --#define BCM2708_DMA_ACTIVE (1 << 0) --#define BCM2708_DMA_INT (1 << 2) --#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ --#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ --#define BCM2708_DMA_ERR (1 << 8) --#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ --#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ -- --/* DMA control block "info" field bits */ --#define BCM2708_DMA_INT_EN (1 << 0) --#define BCM2708_DMA_TDMODE (1 << 1) --#define BCM2708_DMA_WAIT_RESP (1 << 3) --#define BCM2708_DMA_D_INC (1 << 4) --#define BCM2708_DMA_D_WIDTH (1 << 5) --#define BCM2708_DMA_D_DREQ (1 << 6) --#define BCM2708_DMA_S_INC (1 << 8) --#define BCM2708_DMA_S_WIDTH (1 << 9) --#define BCM2708_DMA_S_DREQ (1 << 10) -- --#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) --#define BCM2708_DMA_PER_MAP(x) ((x) << 16) --#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) -- --#define BCM2708_DMA_DREQ_EMMC 11 --#define BCM2708_DMA_DREQ_SDHOST 13 -- --#define BCM2708_DMA_CS 0x00 /* Control and Status */ --#define BCM2708_DMA_ADDR 0x04 --/* the current control block appears in the following registers - read only */ --#define BCM2708_DMA_INFO 0x08 --#define BCM2708_DMA_SOURCE_AD 0x0c --#define BCM2708_DMA_DEST_AD 0x10 --#define BCM2708_DMA_NEXTCB 0x1C --#define BCM2708_DMA_DEBUG 0x20 -- --#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) --#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) -- --#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -- --struct bcm2708_dma_cb { -- unsigned long info; -- unsigned long src; -- unsigned long dst; -- unsigned long length; -- unsigned long stride; -- unsigned long next; -- unsigned long pad[2]; --}; --struct scatterlist; -- --extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); --extern void bcm_dma_start(void __iomem *dma_chan_base, -- dma_addr_t control_block); --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); --extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); -- --/* When listing features we can ask for when allocating DMA channels give -- those with higher priority smaller ordinal numbers */ --#define BCM_DMA_FEATURE_FAST_ORD 0 --#define BCM_DMA_FEATURE_BULK_ORD 1 --#define BCM_DMA_FEATURE_NORMAL_ORD 2 --#define BCM_DMA_FEATURE_LITE_ORD 3 --#define BCM_DMA_FEATURE_FAST (1< -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 2395f63..41097c7 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -339,10 +339,15 @@ config DMA_BCM2835 - - config DMA_BCM2708 - tristate "BCM2708 DMA engine support" -- depends on MACH_BCM2708 || MACH_BCM2709 -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -+config DMA_BCM2708_LEGACY -+ bool "BCM2708 DMA legacy API support" -+ depends on DMA_BCM2708 -+ default y -+ - config TI_CPPI41 - tristate "AM33xx CPPI41 DMA support" - depends on ARCH_OMAP -@@ -381,7 +386,7 @@ config MOXART_DMA - select DMA_VIRTUAL_CHANNELS - help - Enable support for the MOXA ART SoC DMA controller. -- -+ - config FSL_EDMA - tristate "Freescale eDMA engine support" - depends on OF -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 8182b16..937fd60 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -37,26 +37,304 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include -+#include - --#ifndef CONFIG_ARCH_BCM2835 -+#include "virt-dma.h" - --/* dma manager */ --#include -+static unsigned dma_debug; - --//#define DMA_COMPLETE DMA_SUCCESS -+/* -+ * Legacy DMA API -+ */ - --#endif -+#ifdef CONFIG_DMA_BCM2708_LEGACY - --#include --#include -+#define CACHE_LINE_MASK 31 -+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ - --#include "virt-dma.h" -+/* valid only for channels 0 - 14, 15 has its own base address */ -+#define BCM2708_DMA_CHAN(n) ((n) << 8) /* base address */ -+#define BCM2708_DMA_CHANIO(dma_base, n) \ -+ ((void __iomem *)((char *)(dma_base) + BCM2708_DMA_CHAN(n))) - --static unsigned dma_debug; -+struct vc_dmaman { -+ void __iomem *dma_base; -+ u32 chan_available; /* bitmap of available channels */ -+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ -+ struct mutex lock; -+}; -+ -+static struct device *dmaman_dev; /* we assume there's only one! */ -+static struct vc_dmaman *g_dmaman; /* DMA manager */ -+static int dmachans = -1; /* module parameter */ -+ -+/* DMA Auxiliary Functions */ -+ -+/* A DMA buffer on an arbitrary boundary may separate a cache line into a -+ section inside the DMA buffer and another section outside it. -+ Even if we flush DMA buffers from the cache there is always the chance that -+ during a DMA someone will access the part of a cache line that is outside -+ the DMA buffer - which will then bring in unwelcome data. -+ Without being able to dictate our own buffer pools we must insist that -+ DMA buffers consist of a whole number of cache lines. -+*/ -+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) -+{ -+ int i; -+ -+ for (i = 0; i < sg_len; i++) { -+ if (sg_ptr[i].offset & CACHE_LINE_MASK || -+ sg_ptr[i].length & CACHE_LINE_MASK) -+ return 0; -+ } -+ -+ return 1; -+} -+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -+ -+extern void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block) -+{ -+ dsb(); /* ARM data synchronization (push) operation */ -+ -+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); -+} -+EXPORT_SYMBOL_GPL(bcm_dma_start); -+ -+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ /* ugly busy wait only option for now */ -+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -+ cpu_relax(); -+} -+EXPORT_SYMBOL_GPL(bcm_dma_wait_idle); -+ -+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ dsb(); -+ -+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -+ -+/* Complete an ongoing DMA (assuming its results are to be ignored) -+ Does nothing if there is no DMA in progress. -+ This routine waits for the current AXI transfer to complete before -+ terminating the current DMA. If the current transfer is hung on a DREQ used -+ by an uncooperative peripheral the AXI transfer may never complete. In this -+ case the routine times out and return a non-zero error code. -+ Use of this routine doesn't guarantee that the ongoing or aborted DMA -+ does not produce an interrupt. -+*/ -+extern int bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ unsigned long int cs; -+ int rc = 0; -+ -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (BCM2708_DMA_ACTIVE & cs) { -+ long int timeout = 10000; -+ -+ /* write 0 to the active bit - pause the DMA */ -+ writel(0, dma_chan_base + BCM2708_DMA_CS); -+ -+ /* wait for any current AXI transfer to complete */ -+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -+ cs = readl(dma_chan_base + BCM2708_DMA_CS); -+ -+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -+ /* we'll un-pause when we set of our next DMA */ -+ rc = -ETIMEDOUT; -+ -+ } else if (BCM2708_DMA_ACTIVE & cs) { -+ /* terminate the control block chain */ -+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -+ -+ /* abort the whole DMA */ -+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -+ dma_chan_base + BCM2708_DMA_CS); -+ } -+ } -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_abort); -+ -+ /* DMA Manager Device Methods */ -+ -+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -+ u32 chans_available) -+{ -+ dmaman->dma_base = dma_base; -+ dmaman->chan_available = chans_available; -+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* 2 & 3 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* 0 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* 1 to 7 */ -+ dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* 8 to 14 */ -+} -+ -+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -+ unsigned preferred_feature_set) -+{ -+ u32 chans; -+ int chan = 0; -+ int feature; -+ -+ chans = dmaman->chan_available; -+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -+ /* select the subset of available channels with the desired -+ feature so long as some of the candidate channels have that -+ feature */ -+ if ((preferred_feature_set & (1 << feature)) && -+ (chans & dmaman->has_feature[feature])) -+ chans &= dmaman->has_feature[feature]; -+ -+ if (!chans) -+ return -ENOENT; -+ -+ /* return the ordinal of the first channel in the bitmap */ -+ while (chans != 0 && (chans & 1) == 0) { -+ chans >>= 1; -+ chan++; -+ } -+ /* claim the channel */ -+ dmaman->chan_available &= ~(1 << chan); -+ -+ return chan; -+} -+ -+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) -+{ -+ if (chan < 0) -+ return -EINVAL; -+ -+ if ((1 << chan) & dmaman->chan_available) -+ return -EIDRM; -+ -+ dmaman->chan_available |= (1 << chan); -+ -+ return 0; -+} -+ -+/* DMA Manager Monitor */ -+ -+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq) -+{ -+ struct vc_dmaman *dmaman = g_dmaman; -+ struct platform_device *pdev = to_platform_device(dmaman_dev); -+ struct resource *r; -+ int chan; -+ -+ if (!dmaman_dev) -+ return -ENODEV; -+ -+ mutex_lock(&dmaman->lock); -+ chan = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -+ if (chan < 0) -+ goto out; -+ -+ r = platform_get_resource(pdev, IORESOURCE_IRQ, (unsigned int)chan); -+ if (!r) { -+ dev_err(dmaman_dev, "failed to get irq for DMA channel %d\n", -+ chan); -+ vc_dmaman_chan_free(dmaman, chan); -+ chan = -ENOENT; -+ goto out; -+ } -+ -+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, chan); -+ *out_dma_irq = r->start; -+ dev_dbg(dmaman_dev, -+ "Legacy API allocated channel=%d, base=%p, irq=%i\n", -+ chan, *out_dma_base, *out_dma_irq); -+ -+out: -+ mutex_unlock(&dmaman->lock); -+ -+ return chan; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -+ -+extern int bcm_dma_chan_free(int channel) -+{ -+ struct vc_dmaman *dmaman = g_dmaman; -+ int rc; -+ -+ if (!dmaman_dev) -+ return -ENODEV; -+ -+ mutex_lock(&dmaman->lock); -+ rc = vc_dmaman_chan_free(dmaman, channel); -+ mutex_unlock(&dmaman->lock); -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -+ -+static int bcm_dmaman_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct vc_dmaman *dmaman; -+ struct resource *r; -+ void __iomem *dma_base; -+ uint32_t val; -+ -+ if (!of_property_read_u32(dev->of_node, -+ "brcm,dma-channel-mask", &val)) -+ dmachans = val; -+ else if (dmachans == -1) -+ dmachans = DEFAULT_DMACHAN_BITMAP; -+ -+ dmaman = devm_kzalloc(dev, sizeof(*dmaman), GFP_KERNEL); -+ if (!dmaman) -+ return -ENOMEM; -+ -+ mutex_init(&dmaman->lock); -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ dma_base = devm_ioremap_resource(dev, r); -+ if (IS_ERR(dma_base)) -+ return PTR_ERR(dma_base); -+ -+ vc_dmaman_init(dmaman, dma_base, dmachans); -+ g_dmaman = dmaman; -+ dmaman_dev = dev; -+ -+ dev_info(dev, "DMA legacy API manager at %p, dmachans=0x%x\n", -+ dma_base, dmachans); -+ -+ return 0; -+} -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ dmaman_dev = NULL; -+ -+ return 0; -+} -+ -+#else /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+static int bcm_dmaman_remove(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+#endif /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+/* -+ * DMA engine -+ */ - - struct bcm2835_dmadev { - struct dma_device ddev; -@@ -709,7 +987,7 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) - return 0; - } - --#ifdef CONFIG_ARCH_BCM2835 -+#ifndef CONFIG_DMA_BCM2708_LEGACY - static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - { - struct bcm2835_chan *c; -@@ -787,7 +1065,7 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, - static int bcm2835_dma_probe(struct platform_device *pdev) - { - struct bcm2835_dmadev *od; --#ifdef CONFIG_ARCH_BCM2835 -+#ifndef CONFIG_DMA_BCM2708_LEGACY - struct resource *res; - void __iomem *base; - uint32_t chans_available; -@@ -800,10 +1078,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; - -- /* If CONFIG_ARCH_BCM2835 is selected, device tree is used */ -- /* hence the difference between probing */ -- --#ifndef CONFIG_ARCH_BCM2835 -+#ifdef CONFIG_DMA_BCM2708_LEGACY - - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) -@@ -815,6 +1090,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (!od) - return -ENOMEM; - -+ rc = bcm_dmaman_probe(pdev); -+ if (rc) -+ return rc; -+ - pdev->dev.dma_parms = &od->dma_parms; - dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); - -@@ -971,6 +1250,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); -+ bcm_dmaman_remove(pdev); - - return 0; - } -@@ -985,9 +1265,30 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --module_platform_driver(bcm2835_dma_driver); -+static int bcm2835_init(void) -+{ -+ return platform_driver_register(&bcm2835_dma_driver); -+} -+ -+static void bcm2835_exit(void) -+{ -+ platform_driver_unregister(&bcm2835_dma_driver); -+} -+ -+/* -+ * Load after serial driver (arch_initcall) so we see the messages if it fails, -+ * but before drivers (module_init) that need a DMA channel. -+ */ -+subsys_initcall(bcm2835_init); -+module_exit(bcm2835_exit); - - module_param(dma_debug, uint, 0644); -+#ifdef CONFIG_DMA_BCM2708_LEGACY -+/* Keep backward compatibility: dma.dmachans= */ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX "dma." -+module_param(dmachans, int, 0644); -+#endif - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); -diff --git a/include/linux/platform_data/dma-bcm2708.h b/include/linux/platform_data/dma-bcm2708.h -new file mode 100644 -index 0000000..2310e34 ---- /dev/null -+++ b/include/linux/platform_data/dma-bcm2708.h -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef _PLAT_BCM2708_DMA_H -+#define _PLAT_BCM2708_DMA_H -+ -+/* DMA CS Control and Status bits */ -+#define BCM2708_DMA_ACTIVE BIT(0) -+#define BCM2708_DMA_INT BIT(2) -+#define BCM2708_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ -+#define BCM2708_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ -+#define BCM2708_DMA_ERR BIT(8) -+#define BCM2708_DMA_ABORT BIT(30) /* stop current CB, go to next, WO */ -+#define BCM2708_DMA_RESET BIT(31) /* WO, self clearing */ -+ -+/* DMA control block "info" field bits */ -+#define BCM2708_DMA_INT_EN BIT(0) -+#define BCM2708_DMA_TDMODE BIT(1) -+#define BCM2708_DMA_WAIT_RESP BIT(3) -+#define BCM2708_DMA_D_INC BIT(4) -+#define BCM2708_DMA_D_WIDTH BIT(5) -+#define BCM2708_DMA_D_DREQ BIT(6) -+#define BCM2708_DMA_S_INC BIT(8) -+#define BCM2708_DMA_S_WIDTH BIT(9) -+#define BCM2708_DMA_S_DREQ BIT(10) -+ -+#define BCM2708_DMA_BURST(x) (((x) & 0xf) << 12) -+#define BCM2708_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2708_DMA_WAITS(x) (((x) & 0x1f) << 21) -+ -+#define BCM2708_DMA_DREQ_EMMC 11 -+#define BCM2708_DMA_DREQ_SDHOST 13 -+ -+#define BCM2708_DMA_CS 0x00 /* Control and Status */ -+#define BCM2708_DMA_ADDR 0x04 -+/* the current control block appears in the following registers - read only */ -+#define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 -+#define BCM2708_DMA_NEXTCB 0x1C -+#define BCM2708_DMA_DEBUG 0x20 -+ -+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4) + BCM2708_DMA_CS) -+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4) + BCM2708_DMA_ADDR) -+ -+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) -+ -+/* When listing features we can ask for when allocating DMA channels give -+ those with higher priority smaller ordinal numbers */ -+#define BCM_DMA_FEATURE_FAST_ORD 0 -+#define BCM_DMA_FEATURE_BULK_ORD 1 -+#define BCM_DMA_FEATURE_NORMAL_ORD 2 -+#define BCM_DMA_FEATURE_LITE_ORD 3 -+#define BCM_DMA_FEATURE_FAST BIT(BCM_DMA_FEATURE_FAST_ORD) -+#define BCM_DMA_FEATURE_BULK BIT(BCM_DMA_FEATURE_BULK_ORD) -+#define BCM_DMA_FEATURE_NORMAL BIT(BCM_DMA_FEATURE_NORMAL_ORD) -+#define BCM_DMA_FEATURE_LITE BIT(BCM_DMA_FEATURE_LITE_ORD) -+#define BCM_DMA_FEATURE_COUNT 4 -+ -+struct bcm2708_dma_cb { -+ unsigned long info; -+ unsigned long src; -+ unsigned long dst; -+ unsigned long length; -+ unsigned long stride; -+ unsigned long next; -+ unsigned long pad[2]; -+}; -+ -+struct scatterlist; -+ -+#ifdef CONFIG_DMA_BCM2708_LEGACY -+ -+int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); -+void bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block); -+void bcm_dma_wait_idle(void __iomem *dma_chan_base); -+bool bcm_dma_is_busy(void __iomem *dma_chan_base); -+int bcm_dma_abort(void __iomem *dma_chan_base); -+ -+/* return channel no or -ve error */ -+int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, int *out_dma_irq); -+int bcm_dma_chan_free(int channel); -+ -+#else /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+static inline int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, -+ int sg_len) -+{ -+ return 0; -+} -+ -+static inline void bcm_dma_start(void __iomem *dma_chan_base, -+ dma_addr_t control_block) { } -+ -+static inline void bcm_dma_wait_idle(void __iomem *dma_chan_base) { } -+ -+static inline bool bcm_dma_is_busy(void __iomem *dma_chan_base) -+{ -+ return false; -+} -+ -+static inline int bcm_dma_abort(void __iomem *dma_chan_base) -+{ -+ return -EINVAL; -+} -+ -+static inline int bcm_dma_chan_alloc(unsigned preferred_feature_set, -+ void __iomem **out_dma_base, -+ int *out_dma_irq) -+{ -+ return -EINVAL; -+} -+ -+static inline int bcm_dma_chan_free(int channel) -+{ -+ return -EINVAL; -+} -+ -+#endif /* CONFIG_DMA_BCM2708_LEGACY */ -+ -+#endif /* _PLAT_BCM2708_DMA_H */ - -From 2b9f3386a080d00da4e6335272fe3b94cc51cfef Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:26:59 +0200 -Subject: [PATCH 124/216] BCM270x: dma: Remove driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove dma.c driver which is now merged with bcm2708-dmaengine. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/dma.c | 409 -------------------------------------------- - arch/arm/mach-bcm2709/dma.c | 409 -------------------------------------------- - 2 files changed, 818 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/dma.c - delete mode 100644 arch/arm/mach-bcm2709/dma.c - -diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c -deleted file mode 100644 -index a5e58d1..0000000 ---- a/arch/arm/mach-bcm2708/dma.c -+++ /dev/null -@@ -1,409 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/dma.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include -- --#include --#include -- --/*****************************************************************************\ -- * * -- * Configuration * -- * * --\*****************************************************************************/ -- --#define CACHE_LINE_MASK 31 --#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME --#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -- --/* valid only for channels 0 - 14, 15 has its own base address */ --#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ --#define BCM2708_DMA_CHANIO(dma_base, n) \ -- ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -- -- --/*****************************************************************************\ -- * * -- * DMA Auxilliary Functions * -- * * --\*****************************************************************************/ -- --/* A DMA buffer on an arbitrary boundary may separate a cache line into a -- section inside the DMA buffer and another section outside it. -- Even if we flush DMA buffers from the cache there is always the chance that -- during a DMA someone will access the part of a cache line that is outside -- the DMA buffer - which will then bring in unwelcome data. -- Without being able to dictate our own buffer pools we must insist that -- DMA buffers consist of a whole number of cache lines. --*/ -- --extern int --bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) --{ -- int i; -- -- for (i = 0; i < sg_len; i++) { -- if (sg_ptr[i].offset & CACHE_LINE_MASK || -- sg_ptr[i].length & CACHE_LINE_MASK) -- return 0; -- } -- -- return 1; --} --EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -- --extern void --bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) --{ -- dsb(); /* ARM data synchronization (push) operation */ -- -- writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -- writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); --} -- --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) --{ -- dsb(); -- -- /* ugly busy wait only option for now */ -- while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -- cpu_relax(); --} -- --EXPORT_SYMBOL_GPL(bcm_dma_start); -- --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) --{ -- dsb(); -- -- return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; --} --EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -- --/* Complete an ongoing DMA (assuming its results are to be ignored) -- Does nothing if there is no DMA in progress. -- This routine waits for the current AXI transfer to complete before -- terminating the current DMA. If the current transfer is hung on a DREQ used -- by an uncooperative peripheral the AXI transfer may never complete. In this -- case the routine times out and return a non-zero error code. -- Use of this routine doesn't guarantee that the ongoing or aborted DMA -- does not produce an interrupt. --*/ --extern int --bcm_dma_abort(void __iomem *dma_chan_base) --{ -- unsigned long int cs; -- int rc = 0; -- -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (BCM2708_DMA_ACTIVE & cs) { -- long int timeout = 10000; -- -- /* write 0 to the active bit - pause the DMA */ -- writel(0, dma_chan_base + BCM2708_DMA_CS); -- -- /* wait for any current AXI transfer to complete */ -- while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -- /* we'll un-pause when we set of our next DMA */ -- rc = -ETIMEDOUT; -- -- } else if (BCM2708_DMA_ACTIVE & cs) { -- /* terminate the control block chain */ -- writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -- -- /* abort the whole DMA */ -- writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -- dma_chan_base + BCM2708_DMA_CS); -- } -- } -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_dma_abort); -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Device Methods * -- * * --\*****************************************************************************/ -- --struct vc_dmaman { -- void __iomem *dma_base; -- u32 chan_available; /* bitmap of available channels */ -- u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ --}; -- --static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -- u32 chans_available) --{ -- dmaman->dma_base = dma_base; -- dmaman->chan_available = chans_available; -- dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -- dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -- dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -- dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ --} -- --static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -- unsigned preferred_feature_set) --{ -- u32 chans; -- int feature; -- -- chans = dmaman->chan_available; -- for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -- /* select the subset of available channels with the desired -- feature so long as some of the candidate channels have that -- feature */ -- if ((preferred_feature_set & (1 << feature)) && -- (chans & dmaman->has_feature[feature])) -- chans &= dmaman->has_feature[feature]; -- -- if (chans) { -- int chan = 0; -- /* return the ordinal of the first channel in the bitmap */ -- while (chans != 0 && (chans & 1) == 0) { -- chans >>= 1; -- chan++; -- } -- /* claim the channel */ -- dmaman->chan_available &= ~(1 << chan); -- return chan; -- } else -- return -ENOMEM; --} -- --static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) --{ -- if (chan < 0) -- return -EINVAL; -- else if ((1 << chan) & dmaman->chan_available) -- return -EIDRM; -- else { -- dmaman->chan_available |= (1 << chan); -- return 0; -- } --} -- --/*****************************************************************************\ -- * * -- * DMA IRQs * -- * * --\*****************************************************************************/ -- --static unsigned char bcm_dma_irqs[] = { -- IRQ_DMA0, -- IRQ_DMA1, -- IRQ_DMA2, -- IRQ_DMA3, -- IRQ_DMA4, -- IRQ_DMA5, -- IRQ_DMA6, -- IRQ_DMA7, -- IRQ_DMA8, -- IRQ_DMA9, -- IRQ_DMA10, -- IRQ_DMA11, -- IRQ_DMA12 --}; -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Monitor * -- * * --\*****************************************************************************/ -- --static struct device *dmaman_dev; /* we assume there's only one! */ -- --extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -- void __iomem **out_dma_base, int *out_dma_irq) --{ -- if (!dmaman_dev) -- return -ENODEV; -- else { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -- if (rc >= 0) { -- *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -- rc); -- *out_dma_irq = bcm_dma_irqs[rc]; -- } -- device_unlock(dmaman_dev); -- -- return rc; -- } --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -- --extern int bcm_dma_chan_free(int channel) --{ -- if (dmaman_dev) { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_free(dmaman, channel); -- device_unlock(dmaman_dev); -- -- return rc; -- } else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -- --static int dev_dmaman_register(const char *dev_name, struct device *dev) --{ -- int rc = dmaman_dev ? -EINVAL : 0; -- dmaman_dev = dev; -- return rc; --} -- --static void dev_dmaman_deregister(const char *dev_name, struct device *dev) --{ -- dmaman_dev = NULL; --} -- --/*****************************************************************************\ -- * * -- * DMA Device * -- * * --\*****************************************************************************/ -- --static int dmachans = -1; /* module parameter */ -- --static int bcm_dmaman_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_dmaman *dmaman; -- struct resource *dma_res = NULL; -- void __iomem *dma_base = NULL; -- int have_dma_region = 0; -- -- dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -- if (NULL == dmaman) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "DMA management memory\n"); -- ret = -ENOMEM; -- } else { -- -- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (dma_res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- } else if (!request_mem_region(dma_res->start, -- resource_size(dma_res), -- DRIVER_NAME)) { -- dev_err(&pdev->dev, "cannot obtain DMA region\n"); -- ret = -EBUSY; -- } else { -- have_dma_region = 1; -- dma_base = ioremap(dma_res->start, -- resource_size(dma_res)); -- if (!dma_base) { -- dev_err(&pdev->dev, "cannot map DMA region\n"); -- ret = -ENOMEM; -- } else { -- /* use module parameter if one was provided */ -- if (dmachans > 0) -- vc_dmaman_init(dmaman, dma_base, -- dmachans); -- else -- vc_dmaman_init(dmaman, dma_base, -- DEFAULT_DMACHAN_BITMAP); -- -- platform_set_drvdata(pdev, dmaman); -- dev_dmaman_register(DRIVER_NAME, &pdev->dev); -- -- printk(KERN_INFO DRIVER_NAME ": DMA manager " -- "at %p\n", dma_base); -- } -- } -- } -- if (ret != 0) { -- if (dma_base) -- iounmap(dma_base); -- if (dma_res && have_dma_region) -- release_mem_region(dma_res->start, -- resource_size(dma_res)); -- if (dmaman) -- kfree(dmaman); -- } -- return ret; --} -- --static int bcm_dmaman_remove(struct platform_device *pdev) --{ -- struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -- kfree(dmaman); -- -- return 0; --} -- --static struct platform_driver bcm_dmaman_driver = { -- .probe = bcm_dmaman_probe, -- .remove = bcm_dmaman_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --/*****************************************************************************\ -- * * -- * Driver init/exit * -- * * --\*****************************************************************************/ -- --static int __init bcm_dmaman_drv_init(void) --{ -- int ret; -- -- ret = platform_driver_register(&bcm_dmaman_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_dmaman_drv_exit(void) --{ -- platform_driver_unregister(&bcm_dmaman_driver); --} -- --module_init(bcm_dmaman_drv_init); --module_exit(bcm_dmaman_drv_exit); -- --module_param(dmachans, int, 0644); -- --MODULE_AUTHOR("Gray Girling "); --MODULE_DESCRIPTION("DMA channel manager driver"); --MODULE_LICENSE("GPL"); -- --MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); -diff --git a/arch/arm/mach-bcm2709/dma.c b/arch/arm/mach-bcm2709/dma.c -deleted file mode 100644 -index a5e58d1..0000000 ---- a/arch/arm/mach-bcm2709/dma.c -+++ /dev/null -@@ -1,409 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/dma.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include -- --#include --#include -- --/*****************************************************************************\ -- * * -- * Configuration * -- * * --\*****************************************************************************/ -- --#define CACHE_LINE_MASK 31 --#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME --#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ -- --/* valid only for channels 0 - 14, 15 has its own base address */ --#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ --#define BCM2708_DMA_CHANIO(dma_base, n) \ -- ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) -- -- --/*****************************************************************************\ -- * * -- * DMA Auxilliary Functions * -- * * --\*****************************************************************************/ -- --/* A DMA buffer on an arbitrary boundary may separate a cache line into a -- section inside the DMA buffer and another section outside it. -- Even if we flush DMA buffers from the cache there is always the chance that -- during a DMA someone will access the part of a cache line that is outside -- the DMA buffer - which will then bring in unwelcome data. -- Without being able to dictate our own buffer pools we must insist that -- DMA buffers consist of a whole number of cache lines. --*/ -- --extern int --bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) --{ -- int i; -- -- for (i = 0; i < sg_len; i++) { -- if (sg_ptr[i].offset & CACHE_LINE_MASK || -- sg_ptr[i].length & CACHE_LINE_MASK) -- return 0; -- } -- -- return 1; --} --EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); -- --extern void --bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) --{ -- dsb(); /* ARM data synchronization (push) operation */ -- -- writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); -- writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); --} -- --extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) --{ -- dsb(); -- -- /* ugly busy wait only option for now */ -- while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) -- cpu_relax(); --} -- --EXPORT_SYMBOL_GPL(bcm_dma_start); -- --extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) --{ -- dsb(); -- -- return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; --} --EXPORT_SYMBOL_GPL(bcm_dma_is_busy); -- --/* Complete an ongoing DMA (assuming its results are to be ignored) -- Does nothing if there is no DMA in progress. -- This routine waits for the current AXI transfer to complete before -- terminating the current DMA. If the current transfer is hung on a DREQ used -- by an uncooperative peripheral the AXI transfer may never complete. In this -- case the routine times out and return a non-zero error code. -- Use of this routine doesn't guarantee that the ongoing or aborted DMA -- does not produce an interrupt. --*/ --extern int --bcm_dma_abort(void __iomem *dma_chan_base) --{ -- unsigned long int cs; -- int rc = 0; -- -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (BCM2708_DMA_ACTIVE & cs) { -- long int timeout = 10000; -- -- /* write 0 to the active bit - pause the DMA */ -- writel(0, dma_chan_base + BCM2708_DMA_CS); -- -- /* wait for any current AXI transfer to complete */ -- while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) -- cs = readl(dma_chan_base + BCM2708_DMA_CS); -- -- if (0 != (cs & BCM2708_DMA_ISPAUSED)) { -- /* we'll un-pause when we set of our next DMA */ -- rc = -ETIMEDOUT; -- -- } else if (BCM2708_DMA_ACTIVE & cs) { -- /* terminate the control block chain */ -- writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); -- -- /* abort the whole DMA */ -- writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, -- dma_chan_base + BCM2708_DMA_CS); -- } -- } -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_dma_abort); -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Device Methods * -- * * --\*****************************************************************************/ -- --struct vc_dmaman { -- void __iomem *dma_base; -- u32 chan_available; /* bitmap of available channels */ -- u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ --}; -- --static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, -- u32 chans_available) --{ -- dmaman->dma_base = dma_base; -- dmaman->chan_available = chans_available; -- dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ -- dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ -- dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* chans 1 to 7 */ -- dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* chans 8 to 14 */ --} -- --static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, -- unsigned preferred_feature_set) --{ -- u32 chans; -- int feature; -- -- chans = dmaman->chan_available; -- for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) -- /* select the subset of available channels with the desired -- feature so long as some of the candidate channels have that -- feature */ -- if ((preferred_feature_set & (1 << feature)) && -- (chans & dmaman->has_feature[feature])) -- chans &= dmaman->has_feature[feature]; -- -- if (chans) { -- int chan = 0; -- /* return the ordinal of the first channel in the bitmap */ -- while (chans != 0 && (chans & 1) == 0) { -- chans >>= 1; -- chan++; -- } -- /* claim the channel */ -- dmaman->chan_available &= ~(1 << chan); -- return chan; -- } else -- return -ENOMEM; --} -- --static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) --{ -- if (chan < 0) -- return -EINVAL; -- else if ((1 << chan) & dmaman->chan_available) -- return -EIDRM; -- else { -- dmaman->chan_available |= (1 << chan); -- return 0; -- } --} -- --/*****************************************************************************\ -- * * -- * DMA IRQs * -- * * --\*****************************************************************************/ -- --static unsigned char bcm_dma_irqs[] = { -- IRQ_DMA0, -- IRQ_DMA1, -- IRQ_DMA2, -- IRQ_DMA3, -- IRQ_DMA4, -- IRQ_DMA5, -- IRQ_DMA6, -- IRQ_DMA7, -- IRQ_DMA8, -- IRQ_DMA9, -- IRQ_DMA10, -- IRQ_DMA11, -- IRQ_DMA12 --}; -- -- --/***************************************************************************** \ -- * * -- * DMA Manager Monitor * -- * * --\*****************************************************************************/ -- --static struct device *dmaman_dev; /* we assume there's only one! */ -- --extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, -- void __iomem **out_dma_base, int *out_dma_irq) --{ -- if (!dmaman_dev) -- return -ENODEV; -- else { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); -- if (rc >= 0) { -- *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, -- rc); -- *out_dma_irq = bcm_dma_irqs[rc]; -- } -- device_unlock(dmaman_dev); -- -- return rc; -- } --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); -- --extern int bcm_dma_chan_free(int channel) --{ -- if (dmaman_dev) { -- struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); -- int rc; -- -- device_lock(dmaman_dev); -- rc = vc_dmaman_chan_free(dmaman, channel); -- device_unlock(dmaman_dev); -- -- return rc; -- } else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_dma_chan_free); -- --static int dev_dmaman_register(const char *dev_name, struct device *dev) --{ -- int rc = dmaman_dev ? -EINVAL : 0; -- dmaman_dev = dev; -- return rc; --} -- --static void dev_dmaman_deregister(const char *dev_name, struct device *dev) --{ -- dmaman_dev = NULL; --} -- --/*****************************************************************************\ -- * * -- * DMA Device * -- * * --\*****************************************************************************/ -- --static int dmachans = -1; /* module parameter */ -- --static int bcm_dmaman_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_dmaman *dmaman; -- struct resource *dma_res = NULL; -- void __iomem *dma_base = NULL; -- int have_dma_region = 0; -- -- dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); -- if (NULL == dmaman) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "DMA management memory\n"); -- ret = -ENOMEM; -- } else { -- -- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (dma_res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- } else if (!request_mem_region(dma_res->start, -- resource_size(dma_res), -- DRIVER_NAME)) { -- dev_err(&pdev->dev, "cannot obtain DMA region\n"); -- ret = -EBUSY; -- } else { -- have_dma_region = 1; -- dma_base = ioremap(dma_res->start, -- resource_size(dma_res)); -- if (!dma_base) { -- dev_err(&pdev->dev, "cannot map DMA region\n"); -- ret = -ENOMEM; -- } else { -- /* use module parameter if one was provided */ -- if (dmachans > 0) -- vc_dmaman_init(dmaman, dma_base, -- dmachans); -- else -- vc_dmaman_init(dmaman, dma_base, -- DEFAULT_DMACHAN_BITMAP); -- -- platform_set_drvdata(pdev, dmaman); -- dev_dmaman_register(DRIVER_NAME, &pdev->dev); -- -- printk(KERN_INFO DRIVER_NAME ": DMA manager " -- "at %p\n", dma_base); -- } -- } -- } -- if (ret != 0) { -- if (dma_base) -- iounmap(dma_base); -- if (dma_res && have_dma_region) -- release_mem_region(dma_res->start, -- resource_size(dma_res)); -- if (dmaman) -- kfree(dmaman); -- } -- return ret; --} -- --static int bcm_dmaman_remove(struct platform_device *pdev) --{ -- struct vc_dmaman *dmaman = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); -- kfree(dmaman); -- -- return 0; --} -- --static struct platform_driver bcm_dmaman_driver = { -- .probe = bcm_dmaman_probe, -- .remove = bcm_dmaman_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --/*****************************************************************************\ -- * * -- * Driver init/exit * -- * * --\*****************************************************************************/ -- --static int __init bcm_dmaman_drv_init(void) --{ -- int ret; -- -- ret = platform_driver_register(&bcm_dmaman_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_dmaman_drv_exit(void) --{ -- platform_driver_unregister(&bcm_dmaman_driver); --} -- --module_init(bcm_dmaman_drv_init); --module_exit(bcm_dmaman_drv_exit); -- --module_param(dmachans, int, 0644); -- --MODULE_AUTHOR("Gray Girling "); --MODULE_DESCRIPTION("DMA channel manager driver"); --MODULE_LICENSE("GPL"); -- --MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); - -From d2647dd924553835bc9b8f6ec0dce6cc25662d32 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 28 Apr 2015 19:54:17 +0200 -Subject: [PATCH 125/216] BCM270x: Remove dmaman device -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove the dmaman device since the dmaengine now handles -the legacy API manager. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 16 ---------------- - arch/arm/mach-bcm2709/bcm2709.c | 16 ---------------- - 2 files changed, 32 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 703215d..486e090 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -247,21 +247,6 @@ static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - }; - --static struct resource bcm2708_dmaman_resources[] = { -- { -- .start = DMA_BASE, -- .end = DMA_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- } --}; -- --static struct platform_device bcm2708_dmaman_device = { -- .name = "bcm2708_dma", -- .id = 0, /* first bcm2708_dma */ -- .resource = bcm2708_dmaman_resources, -- .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), --}; -- - static struct resource bcm2708_dmaengine_resources[] = { - { - .start = DMA_BASE, -@@ -919,7 +904,6 @@ void __init bcm2708_init(void) - bcm2708_init_clocks(); - bcm2708_dt_init(); - -- bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 97116c3..44bfc50 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -257,21 +257,6 @@ static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - }; - --static struct resource bcm2708_dmaman_resources[] = { -- { -- .start = DMA_BASE, -- .end = DMA_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- } --}; -- --static struct platform_device bcm2708_dmaman_device = { -- .name = "bcm2708_dma", -- .id = 0, /* first bcm2708_dma */ -- .resource = bcm2708_dmaman_resources, -- .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), --}; -- - static struct resource bcm2708_dmaengine_resources[] = { - { - .start = DMA_BASE, -@@ -940,7 +925,6 @@ void __init bcm2709_init(void) - bcm2709_init_clocks(); - bcm2709_dt_init(); - -- bcm_register_device(&bcm2708_dmaman_device); - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); - #ifdef CONFIG_BCM2708_GPIO - -From 149df0acaf7510d53047e19054e3b13607f60afd Mon Sep 17 00:00:00 2001 +From d8492b31751e7eda1b9b2c92dd381b5d7df1679d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 29 Apr 2015 17:24:02 +0200 -Subject: [PATCH 126/216] bcm2835: bcm2835_defconfig +Subject: [PATCH 68/77] bcm2835: bcm2835_defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -136420,4129 +130931,1330 @@ some have changed. Update to keep functionality. No longer available: SCSI_MULTI_LUN and RESOURCE_COUNTERS. +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig enable MMC_BCM2835 + +Enable the downstream bcm2835-mmc driver and DMA support. + +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig enable BCM2708_MBOX + +Enable the mailbox driver. + +Signed-off-by: Noralf Trønnes + +bcm2835: bcm2835_defconfig use FB_BCM2708 + +Enable the bcm2708 framebuffer driver. +Disable the simple framebuffer driver, which matches the +device handed over by u-boot. + +Signed-off-by: Noralf Trønnes + +bcm2835: Merge bcm2835_defconfig with bcmrpi_defconfig + +These commands where used to make this commit: + +./scripts/diffconfig -m arch/arm/configs/bcm2835_defconfig arch/arm/configs/bcmrpi_defconfig > merge.cfg + +cat << EOF > filter +CONFIG_ARCH_BCM2708 +CONFIG_BCM2708_DT +CONFIG_ARM_PATCH_PHYS_VIRT +CONFIG_PHYS_OFFSET +CONFIG_CMDLINE +CONFIG_BCM2708_WDT +CONFIG_HW_RANDOM_BCM2708 +CONFIG_I2C_BCM2708 +CONFIG_SPI_BCM2708 +CONFIG_SND_BCM2708_SOC_I2S +CONFIG_USB_DWCOTG +CONFIG_LIRC_RPI +EOF + +grep -F -v -f filter merge.cfg > filtered.cfg + +cat << EOF > added.cfg +CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y +CONFIG_MISC_FILESYSTEMS=y +CONFIG_SND_BCM2835_SOC_I2S=m +EOF + +ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2835_defconfig filtered.cfg added.cfg +ARCH=arm make oldconfig + +ARCH=arm make savedefconfig +cp defconfig arch/arm/configs/bcm2835_defconfig + +rm merge.cfg filter filtered.cfg added.cfg defconfig + +ARCH=arm make bcm2835_defconfig +ARCH=arm make oldconfig + Signed-off-by: Noralf Trønnes --- - arch/arm/configs/bcm2835_defconfig | 14 +++++--------- - 1 file changed, 5 insertions(+), 9 deletions(-) + arch/arm/configs/bcm2835_defconfig | 1132 +++++++++++++++++++++++++++++++++++- + 1 file changed, 1107 insertions(+), 25 deletions(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 31cb073..245aede 100644 +index 31cb073..2e8a95a 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig -@@ -10,7 +10,6 @@ CONFIG_CGROUP_FREEZER=y +@@ -1,105 +1,1071 @@ + # CONFIG_LOCALVERSION_AUTO is not set + CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y + CONFIG_FHANDLE=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y + CONFIG_BSD_PROCESS_ACCT=y + CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y + CONFIG_LOG_BUF_SHIFT=18 + CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y ++CONFIG_MEMCG=y CONFIG_CGROUP_PERF=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y -@@ -18,10 +17,6 @@ CONFIG_NAMESPACES=y ++CONFIG_BLK_CGROUP=y + CONFIG_NAMESPACES=y CONFIG_SCHED_AUTOGROUP=y - CONFIG_RELAY=y +-CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y - CONFIG_KALLSYMS_ALL=y +-CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -@@ -29,6 +24,7 @@ CONFIG_EMBEDDED=y + # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y - CONFIG_OPROFILE=y +-CONFIG_OPROFILE=y ++CONFIG_OPROFILE=m ++CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_MAC_PARTITION=y ++CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_ARCH_MULTI_V6=y # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_BCM=y -@@ -38,7 +34,6 @@ CONFIG_AEABI=y + CONFIG_ARCH_BCM2835=y +-CONFIG_PREEMPT_VOLUNTARY=y ++CONFIG_PREEMPT=y + CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y CONFIG_KSM=y CONFIG_CLEANCACHE=y ++CONFIG_FRONTSWAP=y ++CONFIG_CMA=y ++CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y -CONFIG_CC_STACKPROTECTOR=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=m ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_VFP=y -@@ -57,7 +52,6 @@ CONFIG_DEVTMPFS_MOUNT=y + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_MISC=m + # CONFIG_SUSPEND is not set + CONFIG_NET=y + CONFIG_PACKET=y + CONFIG_UNIX=y ++CONFIG_XFRM_USER=y ++CONFIG_NET_KEY=m + CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_LRO=m ++CONFIG_INET_DIAG=m ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y + CONFIG_NETWORK_SECMARK=y + CONFIG_NETFILTER=y +-CONFIG_CFG80211=y +-CONFIG_MAC80211=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_CLUSTERIP=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_SCTP_COOKIE_HMAC_SHA1=y ++CONFIG_ATM=m ++CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_ATALK=m ++CONFIG_6LOWPAN=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_BATMAN_ADV=m ++CONFIG_OPENVSWITCH=m ++CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_MCP251X=m ++CONFIG_IRDA=m ++CONFIG_IRLAN=m ++CONFIG_IRNET=m ++CONFIG_IRCOMM=m ++CONFIG_IRDA_ULTRA=y ++CONFIG_IRDA_CACHE_LAST_LSAP=y ++CONFIG_IRDA_FAST_RR=y ++CONFIG_IRTTY_SIR=m ++CONFIG_KINGSUN_DONGLE=m ++CONFIG_KSDAZZLE_DONGLE=m ++CONFIG_KS959_DONGLE=m ++CONFIG_USB_IRDA=m ++CONFIG_SIGMATEL_FIR=m ++CONFIG_MCS_FIR=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIBCM203X=m ++CONFIG_BT_HCIBPA10X=m ++CONFIG_BT_HCIBFUSB=m ++CONFIG_BT_HCIVHCI=m ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_WILINK=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_WIMAX=m ++CONFIG_RFKILL=m ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NFC=m ++CONFIG_NFC_PN533=m + CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_CDROM_PKTCDVD=m ++CONFIG_ATA_OVER_ETH=m ++CONFIG_EEPROM_AT24=m CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_ISCSI_ATTRS=y ++CONFIG_ISCSI_TCP=m ++CONFIG_ISCSI_BOOT_SYSFS=m ++CONFIG_MD=y ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m CONFIG_NETDEVICES=y -@@ -83,11 +77,15 @@ CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_NETCONSOLE=m ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_ENC28J60=m ++CONFIG_MDIO_BITBANG=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m + CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m + CONFIG_USB_NET_SMSC95XX=y +-CONFIG_ZD1211RW=y +-CONFIG_INPUT_EVDEV=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_AT76C50X_USB=m ++CONFIG_USB_ZD1201=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_RTL8187=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_ATH_CARDS=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_B43=m ++# CONFIG_B43_PHY_N is not set ++CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++CONFIG_BRCMFMAC_USB=y ++CONFIG_HOSTAP=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RT2800USB_UNKNOWN=y ++CONFIG_RTL8192CU=m ++CONFIG_ZD1211RW=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_WIMAX_I2400M_USB=m ++CONFIG_INPUT_POLLDEV=m ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=m ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=y ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_STMPE=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_UINPUT=m ++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m ++CONFIG_INPUT_ADXL34X=m ++CONFIG_INPUT_CMA3000=m ++CONFIG_SERIO=m ++CONFIG_SERIO_RAW=m ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + CONFIG_TTY_PRINTK=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_BCM2835=m ++CONFIG_RAW_DRIVER=y ++CONFIG_BRCM_CHAR_DRIVERS=y ++CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VC_SM=y + CONFIG_I2C=y +-CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_CHARDEV=m + CONFIG_I2C_BCM2835=y + CONFIG_SPI=y +-CONFIG_SPI_BCM2835=y ++CONFIG_SPI_BCM2835=m ++CONFIG_SPI_SPIDEV=y ++CONFIG_PPS=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m + CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_ARIZONA=m ++CONFIG_GPIO_STMPE=y ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_BQ27000=m ++CONFIG_BATTERY_DS2760=m + # CONFIG_HWMON is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_BCM2835=y ++CONFIG_WATCHDOG=y ++CONFIG_BCM2835_WDT=y ++CONFIG_UCB1400_CORE=m ++CONFIG_MFD_STMPE=y ++CONFIG_STMPE_SPI=y ++CONFIG_MFD_ARIZONA_I2C=m ++CONFIG_MFD_ARIZONA_SPI=m ++CONFIG_MFD_WM5102=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++CONFIG_MEDIA_RADIO_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_MEDIA_CONTROLLER=y ++CONFIG_LIRC=m ++CONFIG_RC_DEVICES=y ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_IR_GPIO_CIR=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_PWC=m ++CONFIG_VIDEO_CPIA2=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_VIDEO_STK1160_COMMON=m ++CONFIG_VIDEO_STK1160_AC97=y ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_TM6000=m ++CONFIG_VIDEO_TM6000_ALSA=m ++CONFIG_VIDEO_TM6000_DVB=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_AS102=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_VIDEO_BCM2835=y ++CONFIG_VIDEO_BCM2835_MMAL=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI470X=m ++CONFIG_RADIO_SI4713=m ++CONFIG_I2C_SI4713=m ++CONFIG_USB_MR800=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_RADIO_TEA5764=m ++CONFIG_RADIO_SAA7706H=m ++CONFIG_RADIO_TEF6862=m ++CONFIG_RADIO_WL1273=m ++CONFIG_RADIO_WL128X=m ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++CONFIG_VIDEO_UDA1342=m ++CONFIG_VIDEO_SONY_BTF_MPX=m ++CONFIG_VIDEO_TVP5150=m ++CONFIG_VIDEO_TW2804=m ++CONFIG_VIDEO_TW9903=m ++CONFIG_VIDEO_TW9906=m ++CONFIG_VIDEO_OV7640=m ++CONFIG_VIDEO_MT9V011=m + CONFIG_FB=y +-CONFIG_FB_SIMPLE=y ++CONFIG_FB_BCM2708=y ++CONFIG_FB_SSD1307=m ++# CONFIG_BACKLIGHT_GENERIC is not set ++CONFIG_BACKLIGHT_GPIO=m + CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=m ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_SEQUENCER_OSS=y ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_BCM2835=m ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_SOC=m ++CONFIG_SND_BCM2835_SOC_I2S=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_DAC=m ++CONFIG_SND_BCM2708_SOC_RPI_PROTO=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SOUND_PRIME=m ++CONFIG_HIDRAW=y ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LOGITECH=m ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_MON=m ++CONFIG_USB_PRINTER=m CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_HOST=m +CONFIG_USB_DWC2=y ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_XIRCOM=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_RIO500=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_LED=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_FTDI_ELAN=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_ATM=m ++CONFIG_USB_SPEEDTOUCH=m ++CONFIG_USB_CXACRU=m ++CONFIG_USB_UEAGLEATM=m ++CONFIG_USB_XUSBATM=m CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y ++CONFIG_MMC_BCM2835_SDHOST=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_BCM2835=y -+CONFIG_NEW_LEDS=y ++CONFIG_MMC_SPI=m +CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -@@ -97,8 +95,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y - CONFIG_LEDS_TRIGGER_TRANSIENT=y - CONFIG_LEDS_TRIGGER_CAMERA=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y + CONFIG_LEDS_TRIGGER_CPU=y + CONFIG_LEDS_TRIGGER_GPIO=y + CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +-CONFIG_LEDS_TRIGGER_TRANSIENT=y +-CONFIG_LEDS_TRIGGER_CAMERA=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1374=m ++CONFIG_RTC_DRV_DS1672=m ++CONFIG_RTC_DRV_DS3232=m ++CONFIG_RTC_DRV_MAX6900=m ++CONFIG_RTC_DRV_RS5C372=m ++CONFIG_RTC_DRV_ISL1208=m ++CONFIG_RTC_DRV_ISL12022=m ++CONFIG_RTC_DRV_ISL12057=m ++CONFIG_RTC_DRV_X1205=m ++CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_PCF8523=m ++CONFIG_RTC_DRV_PCF8563=m ++CONFIG_RTC_DRV_PCF8583=m ++CONFIG_RTC_DRV_M41T80=m ++CONFIG_RTC_DRV_BQ32K=m ++CONFIG_RTC_DRV_S35390A=m ++CONFIG_RTC_DRV_FM3130=m ++CONFIG_RTC_DRV_RX8581=m ++CONFIG_RTC_DRV_RX8025=m ++CONFIG_RTC_DRV_EM3027=m ++CONFIG_RTC_DRV_RV3029C2=m ++CONFIG_RTC_DRV_M41T93=m ++CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1305=m ++CONFIG_RTC_DRV_DS1390=m ++CONFIG_RTC_DRV_MAX6902=m ++CONFIG_RTC_DRV_R9701=m ++CONFIG_RTC_DRV_RS5C348=m ++CONFIG_RTC_DRV_DS3234=m ++CONFIG_RTC_DRV_PCF2123=m ++CONFIG_RTC_DRV_RX4581=m ++CONFIG_DMADEVICES=y ++CONFIG_DMA_BCM2708=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m CONFIG_STAGING=y -CONFIG_USB_DWC2=y -CONFIG_USB_DWC2_HOST=y ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_R8188EU=m ++CONFIG_R8723AU=m ++CONFIG_VT6656=m ++CONFIG_SPEAKUP=m ++CONFIG_SPEAKUP_SYNTH_SOFT=m ++CONFIG_STAGING_MEDIA=y ++CONFIG_LIRC_STAGING=y ++CONFIG_LIRC_IMON=m ++CONFIG_LIRC_SASEM=m ++CONFIG_LIRC_SERIAL=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_FB_TFT_WATTEROTT=m ++CONFIG_FB_FLEX=m ++CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_MAILBOX=y ++CONFIG_BCM2708_MBOX=y # CONFIG_IOMMU_SUPPORT is not set ++CONFIG_EXTCON=m ++CONFIG_EXTCON_ARIZONA=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y - -From 40cd8a80edbedd6bef0da2bcd55e777f80ef30ae Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:24:46 +0200 -Subject: [PATCH 127/216] mmc: bcm2835-mmc: Make available on ARCH_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the bcm2835-mmc driver available for use on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/mmc/host/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 1666c6c..41d6e47 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" - - config MMC_BCM2835 - tristate "MMC support on BCM2835" -- depends on (MACH_BCM2708 || MACH_BCM2709) -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - help - This selects the MMC Interface on BCM2835. - - -From 6c0c225509561cc261c594db00d429f2c032ebfa Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:28:22 +0200 -Subject: [PATCH 128/216] bcm2835: bcm2835_defconfig enable MMC_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the downstream bcm2835-mmc driver and DMA support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 245aede..cf2e7a6 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -79,6 +79,8 @@ CONFIG_USB=y - CONFIG_USB_STORAGE=y - CONFIG_USB_DWC2=y - CONFIG_MMC=y -+CONFIG_MMC_BCM2835=y -+CONFIG_MMC_BCM2835_DMA=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2835=y -@@ -94,6 +96,8 @@ CONFIG_LEDS_TRIGGER_GPIO=y - CONFIG_LEDS_TRIGGER_DEFAULT_ON=y - CONFIG_LEDS_TRIGGER_TRANSIENT=y - CONFIG_LEDS_TRIGGER_CAMERA=y -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2708=y - CONFIG_STAGING=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT2_FS=y - -From 8bff84b0504771b895a12dcc5975b26345a3f9a1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 29 Apr 2015 17:29:04 +0200 -Subject: [PATCH 129/216] bcm2835: Change to use bcm2835-mmc in Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use downstream bcm2835-mmc driver to get increased throughput -and DMA support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 2 +- - arch/arm/boot/dts/bcm2835.dtsi | 9 ++++++--- - 2 files changed, 7 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index c706448..9f4ed2f 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -45,7 +45,7 @@ - clock-frequency = <100000>; - }; - --&sdhci { -+&mmc { - status = "okay"; - bus-width = <4>; - }; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 3342cb1..f2dec21 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -122,11 +122,14 @@ - status = "disabled"; - }; - -- sdhci: sdhci@7e300000 { -- compatible = "brcm,bcm2835-sdhci"; -+ mmc: mmc@7e300000 { -+ compatible = "brcm,bcm2835-mmc"; - reg = <0x7e300000 0x100>; - interrupts = <2 30>; - clocks = <&clk_mmc>; -+ dmas = <&dma 11>, -+ <&dma 11>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - -@@ -161,7 +164,7 @@ - reg = <0>; - #clock-cells = <0>; - clock-output-names = "mmc"; -- clock-frequency = <100000000>; -+ clock-frequency = <250000000>; - }; - - clk_i2c: clock@1 { - -From 89df9a42f6e60b3c54c4b49b1fafff7ef201ac72 Mon Sep 17 00:00:00 2001 -From: Christopher Freeman -Date: Wed, 4 Mar 2015 01:16:58 -0800 -Subject: [PATCH 130/216] dmaengine: increment privatecnt when using - dma_get_any_slave_channel - -Channels allocated via dma_get_any_slave_channel were not increasing -the counter tracking private allocations. When these channels were -released, privatecnt may erroneously fall to zero. The DMA device -would then lose its DMA_PRIVATE cap and fail to allocate future private -channels (via private_candidate) as any allocations still outstanding -would incorrectly be seen as public allocations. - -Signed-off-by: Christopher Freeman -Signed-off-by: Vinod Koul ---- - drivers/dma/dmaengine.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c -index ac336a9..bb2b914 100644 ---- a/drivers/dma/dmaengine.c -+++ b/drivers/dma/dmaengine.c -@@ -589,11 +589,15 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) - - chan = private_candidate(&mask, device, NULL, NULL); - if (chan) { -+ dma_cap_set(DMA_PRIVATE, device->cap_mask); -+ device->privatecnt++; - err = dma_chan_get(chan); - if (err) { - pr_debug("%s: failed to get %s: (%d)\n", - __func__, dma_chan_name(chan), err); - chan = NULL; -+ if (--device->privatecnt == 0) -+ dma_cap_clear(DMA_PRIVATE, device->cap_mask); - } - } - - -From 0ecdaeb739edb714add6d8ae452d12d2ce821573 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 1 May 2015 17:46:56 +0100 -Subject: [PATCH 131/216] bcm2835-mmc: Add locks when accessing sdhost - registers - ---- - drivers/mmc/host/bcm2835-mmc.c | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index eef0d351..1c34f476 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -133,17 +133,20 @@ struct bcm2835_host { - - static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) - { -+ lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); - } - - static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg) - { -+ lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - } - - static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) - { -+ lockdep_assert_held_once(&host->lock); - return readl(host->ioaddr + reg); - } - -@@ -255,7 +258,9 @@ static void bcm2835_mmc_dumpregs(struct bcm2835_host *host) - static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) - { - unsigned long timeout; -+ unsigned long flags; - -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET); - - if (mask & SDHCI_RESET_ALL) -@@ -273,19 +278,23 @@ static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) - return; - } - timeout--; -+ spin_unlock_irqrestore(&host->lock, flags); - mdelay(1); -+ spin_lock_irqsave(&host->lock, flags); - } - - if (100-timeout > 10 && 100-timeout > host->max_delay) { - host->max_delay = 100-timeout; - pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay); - } -+ spin_unlock_irqrestore(&host->lock, flags); - } - - static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); - - static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - { -+ unsigned long flags; - if (soft) - bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); - else -@@ -297,8 +306,10 @@ static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | - SDHCI_INT_RESPONSE; - -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); - bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ spin_unlock_irqrestore(&host->lock, flags); - - if (soft) { - /* force clock reconfiguration */ -@@ -497,11 +508,14 @@ static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host) - dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); - } - if (desc) { -+ unsigned long flags; -+ spin_lock_irqsave(&host->lock, flags); - bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | - SDHCI_INT_SPACE_AVAIL); - host->tx_desc = desc; - desc->callback = bcm2835_mmc_dma_complete; - desc->callback_param = host; -+ spin_unlock_irqrestore(&host->lock, flags); - dmaengine_submit(desc); - dma_async_issue_pending(dma_chan); - } -@@ -1243,8 +1257,10 @@ static void bcm2835_mmc_tasklet_finish(unsigned long param) - (mrq->data && (mrq->data->error || - (mrq->data->stop && mrq->data->stop->error))))) { - -+ spin_unlock_irqrestore(&host->lock, flags); - bcm2835_mmc_reset(host, SDHCI_RESET_CMD); - bcm2835_mmc_reset(host, SDHCI_RESET_DATA); -+ spin_lock_irqsave(&host->lock, flags); - } - - host->mrq = NULL; -@@ -1259,7 +1275,7 @@ static void bcm2835_mmc_tasklet_finish(unsigned long param) - - - --int bcm2835_mmc_add_host(struct bcm2835_host *host) -+static int bcm2835_mmc_add_host(struct bcm2835_host *host) - { - struct mmc_host *mmc = host->mmc; - struct device *dev = mmc->parent; -@@ -1287,8 +1303,6 @@ int bcm2835_mmc_add_host(struct bcm2835_host *host) - - host->flags = SDHCI_AUTO_CMD23; - -- spin_lock_init(&host->lock); -- - #ifdef FORCE_PIO - dev_info(dev, "Forcing PIO mode\n"); - host->have_dma = false; - -From d7580af2f81793fd3312608de95a9009123d8710 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Apr 2015 23:34:50 +0100 -Subject: [PATCH 132/216] bcm2835-mmc: Add range of debug options for slowing - things down - -bcm2835-mmc: Add option to disable some delays - -bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23 - -bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23 ---- - drivers/mmc/core/quirks.c | 2 ++ - drivers/mmc/host/bcm2835-mmc.c | 44 ++++++++++++++++++++++++++++-------------- - 2 files changed, 32 insertions(+), 14 deletions(-) - -diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c -index f472082..bc3bbad 100644 ---- a/drivers/mmc/core/quirks.c -+++ b/drivers/mmc/core/quirks.c -@@ -71,6 +71,7 @@ static const struct mmc_fixup mmc_fixup_methods[] = { - - void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - { -+ extern unsigned mmc_debug; - const struct mmc_fixup *f; - u64 rev = cid_rev_card(card); - -@@ -98,6 +99,7 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail. - * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers). - */ -+ if (mmc_debug & (1<<13)) - card->quirks |= MMC_QUIRK_BLK_NO_CMD23; - } - EXPORT_SYMBOL(mmc_fixup_device); -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index 1c34f476..68314d5 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -71,6 +71,9 @@ pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) - #define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE) - - -+unsigned mmc_debug; -+unsigned mmc_debug2; -+ - struct bcm2835_host { - spinlock_t lock; - -@@ -131,17 +134,27 @@ struct bcm2835_host { - }; - - --static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg) -+static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from) - { -+ unsigned delay; - lockdep_assert_held_once(&host->lock); - writel(val, host->ioaddr + reg); - udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); -+ -+ delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf); -+ if (delay && !((1<lock); - writel(val, host->ioaddr + reg); -+ -+ delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf); -+ if (delay) -+ udelay(delay); - } - - static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) -@@ -162,7 +175,7 @@ static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int re - if (reg == SDHCI_TRANSFER_MODE) - host->shadow = newval; - else -- bcm2835_mmc_writel(host, newval, reg & ~3); -+ bcm2835_mmc_writel(host, newval, reg & ~3, 0); - - } - -@@ -174,7 +187,7 @@ static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg - u32 mask = 0xff << byte_shift; - u32 newval = (oldval & ~mask) | (val << byte_shift); - -- bcm2835_mmc_writel(host, newval, reg & ~3); -+ bcm2835_mmc_writel(host, newval, reg & ~3, 1); - } - - -@@ -206,7 +219,7 @@ static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear) - ier &= ~clear; - /* change which requests generate IRQs - makes no difference to - the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ -- bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2); - } - - -@@ -307,8 +320,8 @@ static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) - SDHCI_INT_RESPONSE; - - spin_lock_irqsave(&host->lock, flags); -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3); - spin_unlock_irqrestore(&host->lock, flags); - - if (soft) { -@@ -534,8 +547,8 @@ static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host) - else - host->ier = (host->ier & ~dma_irqs) | pio_irqs; - -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4); - } - - -@@ -617,7 +630,7 @@ static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host, - mode |= SDHCI_TRNS_AUTO_CMD12; - else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { - mode |= SDHCI_TRNS_AUTO_CMD23; -- bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2); -+ bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5); - } - } - -@@ -680,7 +693,7 @@ void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd - - bcm2835_mmc_prepare_data(host, cmd); - -- bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT); -+ bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6); - - bcm2835_mmc_set_transfer_mode(host, cmd); - -@@ -837,8 +850,8 @@ static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int en - else - host->ier &= ~SDHCI_INT_CARD_INT; - -- bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE); -- bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7); -+ bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7); - mmiowb(); - } - } -@@ -985,7 +998,7 @@ static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id) - /* Clear selected interrupts. */ - mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | - SDHCI_INT_BUS_POWER); -- bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS); -+ bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8); - - - if (intmask & SDHCI_INT_CMD_MASK) -@@ -1015,7 +1028,7 @@ static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id) - - if (intmask) { - unexpected |= intmask; -- bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS); -+ bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9); - } - - if (result == IRQ_NONE) -@@ -1303,6 +1316,7 @@ static int bcm2835_mmc_add_host(struct bcm2835_host *host) - - host->flags = SDHCI_AUTO_CMD23; - -+ dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2); - #ifdef FORCE_PIO - dev_info(dev, "Forcing PIO mode\n"); - host->have_dma = false; -@@ -1514,6 +1528,8 @@ static struct platform_driver bcm2835_mmc_driver = { - }; - module_platform_driver(bcm2835_mmc_driver); - -+module_param(mmc_debug, uint, 0644); -+module_param(mmc_debug2, uint, 0644); - MODULE_ALIAS("platform:mmc-bcm2835"); - MODULE_DESCRIPTION("BCM2835 SDHCI driver"); - MODULE_LICENSE("GPL v2"); - -From e34578092803603a960a2a7bcccde5d0c8240b9a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 19:08:54 +0200 -Subject: [PATCH 133/216] BCM270x: Correct vcio device memory resource and add - irq resource -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The vcio driver hardcodes these resources, so this is the first -step in correcting this. Spell out the device name so we don't -have to include mach/vcio.h, since this header file will eventually -go away when the driver is later moved to drivers/mailbox. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 17 ++++++++++------- - arch/arm/mach-bcm2708/include/mach/platform.h | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 17 ++++++++++------- - arch/arm/mach-bcm2709/include/mach/platform.h | 1 + - 4 files changed, 22 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 486e090..51f8efa 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -55,7 +55,6 @@ - #include - - #include --#include - #include - - #include -@@ -414,17 +413,21 @@ static struct platform_device bcm2708_usb_device = { - }; - - static struct resource bcm2708_vcio_resources[] = { -- [0] = { /* mailbox/semaphore/doorbell access */ -- .start = MCORE_BASE, -- .end = MCORE_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -+ { -+ .start = ARMCTRL_0_MAIL0_BASE, -+ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_MAILBOX, -+ .end = IRQ_ARM_MAILBOX, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_vcio_device = { -- .name = BCM_VCIO_DRIVER_NAME, -+ .name = "bcm2708_vcio", - .id = -1, /* only one VideoCore I/O area */ - .resource = bcm2708_vcio_resources, - .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index 2e7e1bb..bef3e5a 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - /* -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 44bfc50..8ed88b4 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -56,7 +56,6 @@ - #include - - #include --#include - #include - - #include -@@ -433,17 +432,21 @@ static struct platform_device bcm2708_usb_device = { - }; - - static struct resource bcm2708_vcio_resources[] = { -- [0] = { /* mailbox/semaphore/doorbell access */ -- .start = MCORE_BASE, -- .end = MCORE_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -+ { -+ .start = ARMCTRL_0_MAIL0_BASE, -+ .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_MAILBOX, -+ .end = IRQ_ARM_MAILBOX, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); - - static struct platform_device bcm2708_vcio_device = { -- .name = BCM_VCIO_DRIVER_NAME, -+ .name = "bcm2708_vcio", - .id = -1, /* only one VideoCore I/O area */ - .resource = bcm2708_vcio_resources, - .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 7157f38..5574bb5 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - /* - -From 4b03fd4291b9ed1cd100b359967f1b1fdc39984a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:55:53 +0200 -Subject: [PATCH 134/216] video: fbdev: bcm2708_fb: Don't panic on error -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to panic the kernel if the video driver fails. -Just print a message and return an error. - -Signed-off-by: Noralf Trønnes ---- - drivers/video/fbdev/bcm2708_fb.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 9179291..52e655a 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -325,8 +325,8 @@ static int bcm2708_fb_set_par(struct fb_info *info) - /* the console may currently be locked */ - console_trylock(); - console_unlock(); -- -- BUG(); /* what can we do here */ -+ pr_err("bcm2708_fb_set_par: Failed to set screen_base\n"); -+ return -EIO; - } - } - print_debug -@@ -677,7 +677,9 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) - */ - - fb_set_var(&fb->fb, &fb->fb.var); -- bcm2708_fb_set_par(&fb->fb); -+ ret = bcm2708_fb_set_par(&fb->fb); -+ if (ret) -+ return ret; - - print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth, - fbheight, fbdepth, fbswap); - -From 1965f1d8dcc748e1f9ba3ff28c8fb5191e081a4d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 20:49:04 +0200 -Subject: [PATCH 135/216] BCM2708: vcio: Fix checkpatch issues -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -checkpatch.pl errors and warnings: -Many whitespace related issues in some form or another. -Consider using instead of . -braces {} are not necessary for single statement blocks. -Use pr_* instead of printk. -Do not initialise statics to 0 or NULL. -Avoid CamelCase. -sizeof size should be sizeof(size). -break is not useful after a goto or return. -struct file_operations should normally be const -Possible unnecessary 'out of memory' message -Comparison to NULL could be written "!res" -quoted string split across lines. - -This has not been adressed: -WARNING: consider using a completion - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 12 ++- - arch/arm/mach-bcm2708/vcio.c | 123 ++++++++++++++---------------- - 2 files changed, 62 insertions(+), 73 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -index 8e11d67e..58188b74 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -12,10 +12,6 @@ - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - #ifndef _MACH_BCM2708_VCIO_H - #define _MACH_BCM2708_VCIO_H -@@ -34,12 +30,14 @@ - #define MBOX_CHAN_COUNT 9 - - enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 -+ VCMSG_PROCESS_REQUEST = 0x00000000 - }; -+ - enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 - }; -+ - /* Mailbox property tags */ - enum { - VCMSG_PROPERTY_END = 0x00000000, -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 700bff4..5e9e777 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -37,8 +37,7 @@ - #include - #include - --#include -- -+#include - - #define DRIVER_NAME BCM_VCIO_DRIVER_NAME - -@@ -61,7 +60,9 @@ - #define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) - - #define MBOX_MAGIC 0xd0d0c0de --static struct class *vcio_class = NULL; -+ -+static struct class *vcio_class; -+ - struct vc_mailbox { - struct device *dev; /* parent device */ - void __iomem *status; -@@ -102,9 +103,9 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - { - int rc; - -- if (mbox->magic != MBOX_MAGIC) -+ if (mbox->magic != MBOX_MAGIC) { - rc = -EINVAL; -- else { -+ } else { - /* wait for the mailbox FIFO to have some space in it */ - while (0 != (readl(mbox->status) & ARM_MS_FULL)) - cpu_relax(); -@@ -119,9 +120,9 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - { - int rc; - -- if (mbox->magic != MBOX_MAGIC) -+ if (mbox->magic != MBOX_MAGIC) { - rc = -EINVAL; -- else { -+ } else { - down(&mbox->sema[chan]); - *data28 = MBOX_DATA28(mbox->msg[chan]); - mbox->msg[chan] = 0; -@@ -133,17 +134,18 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - static irqreturn_t mbox_irq(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; - int status = readl(mbox->status); - int ret = IRQ_NONE; - - while (!(status & ARM_MS_EMPTY)) { - uint32_t msg = readl(mbox->read); - int chan = MBOX_CHAN(msg); -+ - if (chan < MBOX_CHAN_COUNT) { - if (mbox->msg[chan]) { - /* Overflow */ -- printk(KERN_ERR DRIVER_NAME -+ pr_err(DRIVER_NAME - ": mbox chan %d overflow - drop %08x\n", - chan, msg); - } else { -@@ -151,7 +153,7 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - up(&mbox->sema[chan]); - } - } else { -- printk(KERN_ERR DRIVER_NAME -+ pr_err(DRIVER_NAME - ": invalid channel selector (msg %08x)\n", msg); - } - ret = IRQ_HANDLED; -@@ -174,9 +176,9 @@ static struct device *mbox_dev; /* we assume there's only one! */ - - static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) - { -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); - int rc; - -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); - device_lock(dev); - rc = mbox_write(mailbox, chan, data28); - device_unlock(dev); -@@ -186,9 +188,9 @@ static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) - - static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) - { -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); - int rc; - -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); - device_lock(dev); - rc = mbox_read(mailbox, chan, data28); - device_unlock(dev); -@@ -221,41 +223,36 @@ static void dev_mbox_register(const char *dev_name, struct device *dev) - - static int mbox_copy_from_user(void *dst, const void *src, int size) - { -- if ( (uint32_t)src < TASK_SIZE) -- { -+ if ((uint32_t)src < TASK_SIZE) - return copy_from_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } -+ -+ memcpy(dst, src, size); -+ -+ return 0; - } - - static int mbox_copy_to_user(void *dst, const void *src, int size) - { -- if ( (uint32_t)dst < TASK_SIZE) -- { -+ if ((uint32_t)dst < TASK_SIZE) - return copy_to_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } -+ -+ memcpy(dst, src, size); -+ -+ return 0; - } - - static DEFINE_MUTEX(mailbox_lock); - extern int bcm_mailbox_property(void *data, int size) - { - uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ - int s = 0; - -- mutex_lock(&mailbox_lock); -+ mutex_lock(&mailbox_lock); - /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -+ GFP_ATOMIC); - if (mem_kern) { - /* create the message */ - mbox_copy_from_user(mem_kern, data, size); -@@ -263,9 +260,8 @@ extern int bcm_mailbox_property(void *data, int size) - /* send the message */ - wmb(); - s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) { -+ if (s == 0) - s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- } - if (s == 0) { - /* copy the response */ - rmb(); -@@ -276,9 +272,9 @@ extern int bcm_mailbox_property(void *data, int size) - s = -ENOMEM; - } - if (s != 0) -- printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); - -- mutex_unlock(&mailbox_lock); -+ mutex_unlock(&mailbox_lock); - return s; - } - EXPORT_SYMBOL_GPL(bcm_mailbox_property); -@@ -291,7 +287,7 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); - * Is the device open right now? Used to prevent - * concurent access into the same device - */ --static int Device_Open = 0; -+static bool device_is_open; - - /* - * This is called whenever a process attempts to open the device file -@@ -301,10 +297,10 @@ static int device_open(struct inode *inode, struct file *file) - /* - * We don't want to talk to two processes at the same time - */ -- if (Device_Open) -+ if (device_is_open) - return -EBUSY; - -- Device_Open++; -+ device_is_open = true; - /* - * Initialize the message - */ -@@ -317,7 +313,7 @@ static int device_release(struct inode *inode, struct file *file) - /* - * We're now ready for our next caller - */ -- Device_Open--; -+ device_is_open = false; - - module_put(THIS_MODULE); - return 0; -@@ -333,9 +329,8 @@ static int device_release(struct inode *inode, struct file *file) - * calling process), the ioctl call returns the output of this function. - * - */ --static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -- unsigned int ioctl_num, /* number and param for ioctl */ -- unsigned long ioctl_param) -+static long device_ioctl(struct file *file, unsigned int ioctl_num, -+ unsigned long ioctl_param) - { - unsigned size; - /* -@@ -348,11 +343,10 @@ static long device_ioctl(struct file *file, /* see include/linux/fs.h */ - * to be the device's message. Get the parameter given to - * ioctl by the process. - */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); - return bcm_mailbox_property((void *)ioctl_param, size); -- break; - default: -- printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); - return -EINVAL; - } - -@@ -368,7 +362,7 @@ static long device_ioctl(struct file *file, /* see include/linux/fs.h */ - * the devices table, it can't be local to - * init_module. NULL is for unimplemented functios. - */ --struct file_operations fops = { -+const struct file_operations fops = { - .unlocked_ioctl = device_ioctl, - .open = device_open, - .release = device_release, /* a.k.a. close */ -@@ -380,17 +374,15 @@ static int bcm_vcio_probe(struct platform_device *pdev) - struct vc_mailbox *mailbox; - - mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (NULL == mailbox) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "mailbox memory\n"); -+ if (!mailbox) { - ret = -ENOMEM; - } else { - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -+ if (!res) { -+ pr_err(DRIVER_NAME -+ ": failed to obtain memory resource\n"); - ret = -ENODEV; - kfree(mailbox); - } else { -@@ -402,8 +394,8 @@ static int bcm_vcio_probe(struct platform_device *pdev) - - mbox_irqaction.dev_id = mailbox; - setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -+ dev_info(&pdev->dev, "mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); - } - } - -@@ -417,17 +409,18 @@ static int bcm_vcio_probe(struct platform_device *pdev) - * Negative values signify an error - */ - if (ret < 0) { -- printk(KERN_ERR DRIVER_NAME -- "Failed registering the character device %d\n", ret); -+ pr_err(DRIVER_NAME -+ "Failed registering the character device %d\n", -+ ret); - return ret; - } - vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); - if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret ; -+ ret = PTR_ERR(vcio_class); -+ return ret; - } - device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -+ "vcio"); - } - return ret; - } -@@ -456,20 +449,18 @@ static int __init bcm_mbox_init(void) - { - int ret; - -- printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ pr_info("mailbox: Broadcom VideoCore Mailbox driver\n"); - - ret = platform_driver_register(&bcm_mbox_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -+ if (ret) -+ pr_err(DRIVER_NAME ": failed to register on platform\n"); - - return ret; - } - - static void __exit bcm_mbox_exit(void) - { -- device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); - class_destroy(vcio_class); - unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - -From f7567a97143abdc87b5dc258b3b628ba115ce0b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:02:44 +0200 -Subject: [PATCH 136/216] BCM2708: vcio: Remove unused code and compact - comments -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The config reference SERIAL_BCM_MBOX_CONSOLE does not exist, -so remove the whole clause as it will always be false. - -Remove includes that are not needed. -Add . -Also sort include headers alphabetically, since this -is now the preferred coding style. - -Remove vc_mailbox->dev since it is not used. - -Compact some comments to one line. -Remove superfluous comments. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 68 ++++++++++---------------------------------- - 1 file changed, 15 insertions(+), 53 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 5e9e777..270f126 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -12,39 +12,24 @@ - * VideoCore processor - */ - --#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) --#define SUPPORT_SYSRQ --#endif -- -+#include -+#include - #include --#include --#include --#include - #include --#include -+#include - #include --#include --#include --#include --#include --#include --#include - #include --#include -- - #include -+#include -+#include -+#include -+#include - - #include - #include - --#include -- - #define DRIVER_NAME BCM_VCIO_DRIVER_NAME - --/* ---------------------------------------------------------------------- -- * Mailbox -- * -------------------------------------------------------------------- */ -- - /* offsets from a mail box base address */ - #define MAIL_WRT 0x00 /* write - and next 4 words */ - #define MAIL_RD 0x00 /* read - and next 4 words */ -@@ -64,7 +49,6 @@ - static struct class *vcio_class; - - struct vc_mailbox { -- struct device *dev; /* parent device */ - void __iomem *status; - void __iomem *config; - void __iomem *read; -@@ -79,7 +63,6 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - { - int i; - -- mbox_out->dev = dev; - mbox_out->status = __io_address(addr_mbox + MAIL_STA); - mbox_out->config = __io_address(addr_mbox + MAIL_CNF); - mbox_out->read = __io_address(addr_mbox + MAIL_RD); -@@ -144,7 +127,6 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - - if (chan < MBOX_CHAN_COUNT) { - if (mbox->msg[chan]) { -- /* Overflow */ - pr_err(DRIVER_NAME - ": mbox chan %d overflow - drop %08x\n", - chan, msg); -@@ -168,9 +150,7 @@ static struct irqaction mbox_irqaction = { - .handler = mbox_irq, - }; - --/* ---------------------------------------------------------------------- -- * Mailbox Methods -- * -------------------------------------------------------------------- */ -+/* Mailbox Methods */ - - static struct device *mbox_dev; /* we assume there's only one! */ - -@@ -279,9 +259,7 @@ extern int bcm_mailbox_property(void *data, int size) - } - EXPORT_SYMBOL_GPL(bcm_mailbox_property); - --/* ---------------------------------------------------------------------- -- * Platform Device for Mailbox -- * -------------------------------------------------------------------- */ -+/* Platform Device for Mailbox */ - - /* - * Is the device open right now? Used to prevent -@@ -289,33 +267,26 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); - */ - static bool device_is_open; - --/* -- * This is called whenever a process attempts to open the device file -- */ -+/* This is called whenever a process attempts to open the device file */ - static int device_open(struct inode *inode, struct file *file) - { -- /* -- * We don't want to talk to two processes at the same time -- */ -+ /* We don't want to talk to two processes at the same time */ - if (device_is_open) - return -EBUSY; - - device_is_open = true; -- /* -- * Initialize the message -- */ - try_module_get(THIS_MODULE); -+ - return 0; - } - - static int device_release(struct inode *inode, struct file *file) - { -- /* -- * We're now ready for our next caller -- */ -+ /* We're now ready for our next caller */ - device_is_open = false; - - module_put(THIS_MODULE); -+ - return 0; - } - -@@ -333,9 +304,7 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, - unsigned long ioctl_param) - { - unsigned size; -- /* -- * Switch according to the ioctl called -- */ -+ - switch (ioctl_num) { - case IOCTL_MBOX_PROPERTY: - /* -@@ -400,14 +369,7 @@ static int bcm_vcio_probe(struct platform_device *pdev) - } - - if (ret == 0) { -- /* -- * Register the character device -- */ - ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- -- /* -- * Negative values signify an error -- */ - if (ret < 0) { - pr_err(DRIVER_NAME - "Failed registering the character device %d\n", - -From 406f0f628a2f978a1da4d25dda3b5eafb94cefd0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:10:18 +0200 -Subject: [PATCH 137/216] BCM2708: vcio: Move character device teardown to - driver remove -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -chrdev is created in the probe function, but teared down in module exit. -Move chrdev teardown to happen on device removal. -Also add missing mbox_dev disabling. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 270f126..cac8dd7 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -391,8 +391,12 @@ static int bcm_vcio_remove(struct platform_device *pdev) - { - struct vc_mailbox *mailbox = platform_get_drvdata(pdev); - -+ mbox_dev = NULL; - platform_set_drvdata(pdev, NULL); - kfree(mailbox); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - - return 0; - } -@@ -422,9 +426,6 @@ static int __init bcm_mbox_init(void) - - static void __exit bcm_mbox_exit(void) - { -- device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); - platform_driver_unregister(&bcm_mbox_driver); - } - - -From fa189cd5d18e5cda8438873181a329fc489a6649 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:20:46 +0200 -Subject: [PATCH 138/216] BCM2708: vcio: Restructure error paths -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to use if/else clauses on error when return can be used directly. -Also test for errors first if possible. -This is done to enhance readability. -bcm_vcio_probe() is not touched, it will be reworked later. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 48 +++++++++++++++++++------------------------- - 1 file changed, 21 insertions(+), 27 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index cac8dd7..36e0f1e 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -84,34 +84,28 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - - static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - { -- int rc; -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; - -- if (mbox->magic != MBOX_MAGIC) { -- rc = -EINVAL; -- } else { -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -- cpu_relax(); -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); - -- writel(MBOX_MSG(chan, data28), mbox->write); -- rc = 0; -- } -- return rc; -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ -+ return 0; - } - - static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - { -- int rc; -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; - -- if (mbox->magic != MBOX_MAGIC) { -- rc = -EINVAL; -- } else { -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- rc = 0; -- } -- return rc; -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ -+ return 0; - } - - static irqreturn_t mbox_irq(int irq, void *dev_id) -@@ -180,19 +174,19 @@ static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) - - extern int bcm_mailbox_write(unsigned chan, uint32_t data28) - { -- if (mbox_dev) -- return dev_mbox_write(mbox_dev, chan, data28); -- else -+ if (!mbox_dev) - return -ENODEV; -+ -+ return dev_mbox_write(mbox_dev, chan, data28); - } - EXPORT_SYMBOL_GPL(bcm_mailbox_write); - - extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) - { -- if (mbox_dev) -- return dev_mbox_read(mbox_dev, chan, data28); -- else -+ if (!mbox_dev) - return -ENODEV; -+ -+ return dev_mbox_read(mbox_dev, chan, data28); - } - EXPORT_SYMBOL_GPL(bcm_mailbox_read); - - -From ce2c991a11f0a94679423655dceed9bb80604892 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:28:31 +0200 -Subject: [PATCH 139/216] BCM2708: vcio: Move some macros from header to driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Move some macros that are only used by the driver: -MAJOR_NUM -IOCTL_MBOX_PROPERTY -DEVICE_FILE_NAME - -This one becomes superfluous: BCM_VCIO_DRIVER_NAME - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 35 ------------------------------- - arch/arm/mach-bcm2708/vcio.c | 9 ++++++-- - 2 files changed, 7 insertions(+), 37 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -index 58188b74..95ad121 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ b/arch/arm/mach-bcm2708/include/mach/vcio.h -@@ -20,8 +20,6 @@ - * (semaphores, doorbells, mailboxes) - */ - --#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -- - /* Constants shared with the ARM identifying separate mailbox channels */ - #define MBOX_CHAN_POWER 0 /* for use by the power management interface */ - #define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -@@ -127,37 +125,4 @@ extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); - extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); - extern int /*rc*/ bcm_mailbox_property(void *data, int size); - --#include -- --/* -- * The major device number. We can't rely on dynamic -- * registration any more, because ioctls need to know -- * it. -- */ --#define MAJOR_NUM 100 -- --/* -- * Set the message of the device driver -- */ --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) --/* -- * _IOWR means that we're creating an ioctl command -- * number for passing information from a user process -- * to the kernel module and from the kernel module to user process -- * -- * The first arguments, MAJOR_NUM, is the major device -- * number we're using. -- * -- * The second argument is the number of the command -- * (there could be several with different meanings). -- * -- * The third argument is the type we want to get from -- * the process to the kernel. -- */ -- --/* -- * The name of the device file -- */ --#define DEVICE_FILE_NAME "vcio" -- - #endif -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 36e0f1e..75cf955 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -28,7 +29,8 @@ - #include - #include - --#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+#define DRIVER_NAME "bcm2708_vcio" -+#define DEVICE_FILE_NAME "vcio" - - /* offsets from a mail box base address */ - #define MAIL_WRT 0x00 /* write - and next 4 words */ -@@ -46,6 +48,9 @@ - - #define MBOX_MAGIC 0xd0d0c0de - -+#define MAJOR_NUM 100 -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+ - static struct class *vcio_class; - - struct vc_mailbox { -@@ -370,7 +375,7 @@ static int bcm_vcio_probe(struct platform_device *pdev) - ret); - return ret; - } -- vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); - if (IS_ERR(vcio_class)) { - ret = PTR_ERR(vcio_class); - return ret; - -From 71c6a7270af56930e1e31ff243048c1ac12ebc1f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:40:03 +0200 -Subject: [PATCH 140/216] BCM2708: vcio: Only store the register base address -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to keep pointers to the sub registers. Only -store the base address. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 37 ++++++++++++++----------------------- - 1 file changed, 14 insertions(+), 23 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index 75cf955..e67fa3e 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -33,12 +33,12 @@ - #define DEVICE_FILE_NAME "vcio" - - /* offsets from a mail box base address */ --#define MAIL_WRT 0x00 /* write - and next 4 words */ --#define MAIL_RD 0x00 /* read - and next 4 words */ --#define MAIL_POL 0x10 /* read without popping the fifo */ --#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL_STA 0x18 /* status */ --#define MAIL_CNF 0x1C /* configuration */ -+#define MAIL0_RD 0x00 /* read - and next 4 words */ -+#define MAIL0_POL 0x10 /* read without popping the fifo */ -+#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL0_STA 0x18 /* status */ -+#define MAIL0_CNF 0x1C /* configuration */ -+#define MAIL1_WRT 0x20 /* write - and next 4 words */ - - #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) - #define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -@@ -54,10 +54,7 @@ - static struct class *vcio_class; - - struct vc_mailbox { -- void __iomem *status; -- void __iomem *config; -- void __iomem *read; -- void __iomem *write; -+ void __iomem *regs; - uint32_t msg[MBOX_CHAN_COUNT]; - struct semaphore sema[MBOX_CHAN_COUNT]; - uint32_t magic; -@@ -68,13 +65,7 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - { - int i; - -- mbox_out->status = __io_address(addr_mbox + MAIL_STA); -- mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -- mbox_out->read = __io_address(addr_mbox + MAIL_RD); -- /* Write to the other mailbox */ -- mbox_out->write = -- __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -- MAIL_WRT); -+ mbox_out->regs = __io_address(addr_mbox); - - for (i = 0; i < MBOX_CHAN_COUNT; i++) { - mbox_out->msg[i] = 0; -@@ -82,7 +73,7 @@ static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, - } - - /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); - - mbox_out->magic = MBOX_MAGIC; - } -@@ -93,10 +84,10 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - return -EINVAL; - - /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) - cpu_relax(); - -- writel(MBOX_MSG(chan, data28), mbox->write); -+ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); - - return 0; - } -@@ -117,11 +108,11 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ - struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -- int status = readl(mbox->status); -+ int status = readl(mbox->regs + MAIL0_STA); - int ret = IRQ_NONE; - - while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->read); -+ uint32_t msg = readl(mbox->regs + MAIL0_RD); - int chan = MBOX_CHAN(msg); - - if (chan < MBOX_CHAN_COUNT) { -@@ -138,7 +129,7 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - ": invalid channel selector (msg %08x)\n", msg); - } - ret = IRQ_HANDLED; -- status = readl(mbox->status); -+ status = readl(mbox->regs + MAIL0_STA); - } - return ret; - } - -From 30e7622ceffd50a31b6544e3a3e05bb0743c3bc2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 21:44:39 +0200 -Subject: [PATCH 141/216] BCM2708: vcio: Do not print messages in module init -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It is not common practice to print messages from a -module init function that only register a driver. -Remove obsolete module alias. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 11 +---------- - 1 file changed, 1 insertion(+), 10 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index e67fa3e..ff50ebd 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -403,15 +403,7 @@ static struct platform_driver bcm_mbox_driver = { - - static int __init bcm_mbox_init(void) - { -- int ret; -- -- pr_info("mailbox: Broadcom VideoCore Mailbox driver\n"); -- -- ret = platform_driver_register(&bcm_mbox_driver); -- if (ret) -- pr_err(DRIVER_NAME ": failed to register on platform\n"); -- -- return ret; -+ return platform_driver_register(&bcm_mbox_driver); - } - - static void __exit bcm_mbox_exit(void) -@@ -425,4 +417,3 @@ module_exit(bcm_mbox_exit); - MODULE_AUTHOR("Gray Girling"); - MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); - MODULE_LICENSE("GPL"); --MODULE_ALIAS("platform:bcm-mbox"); - -From 7a9128973d51200625a3d3f8ff72a4580cb9f14b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 30 Apr 2015 23:33:43 +0200 -Subject: [PATCH 142/216] BCM2708: vcio: Use device resources -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use device resources instead of hardcoding them. -Use devm_* functions where possible. -Merge dev_mbox_register() with probe function. -Add Device Tree support. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/vcio.c | 122 +++++++++++++++++++++---------------------- - 1 file changed, 61 insertions(+), 61 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -index ff50ebd..c4c2bcd 100644 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ b/arch/arm/mach-bcm2708/vcio.c -@@ -21,13 +21,10 @@ - #include - #include - #include --#include - #include --#include - #include - - #include --#include - - #define DRIVER_NAME "bcm2708_vcio" - #define DEVICE_FILE_NAME "vcio" -@@ -60,13 +57,10 @@ struct vc_mailbox { - uint32_t magic; - }; - --static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -- uint32_t addr_mbox) -+static void mbox_init(struct vc_mailbox *mbox_out) - { - int i; - -- mbox_out->regs = __io_address(addr_mbox); -- - for (i = 0; i < MBOX_CHAN_COUNT; i++) { - mbox_out->msg[i] = 0; - sema_init(&mbox_out->sema[i], 0); -@@ -104,7 +98,7 @@ static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) - return 0; - } - --static irqreturn_t mbox_irq(int irq, void *dev_id) -+static irqreturn_t mbox_irq_handler(int irq, void *dev_id) - { - /* wait for the mailbox FIFO to have some data in it */ - struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -@@ -134,12 +128,6 @@ static irqreturn_t mbox_irq(int irq, void *dev_id) - return ret; - } - --static struct irqaction mbox_irqaction = { -- .name = "ARM Mailbox IRQ", -- .flags = IRQF_DISABLED | IRQF_IRQPOLL, -- .handler = mbox_irq, --}; -- - /* Mailbox Methods */ - - static struct device *mbox_dev; /* we assume there's only one! */ -@@ -186,11 +174,6 @@ extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) - } - EXPORT_SYMBOL_GPL(bcm_mailbox_read); - --static void dev_mbox_register(const char *dev_name, struct device *dev) --{ -- mbox_dev = dev; --} -- - static int mbox_copy_from_user(void *dst, const void *src, int size) - { - if ((uint32_t)src < TASK_SIZE) -@@ -329,61 +312,71 @@ const struct file_operations fops = { - - static int bcm_vcio_probe(struct platform_device *pdev) - { -- int ret = 0; -+ struct device *dev = &pdev->dev; -+ struct device *vdev; - struct vc_mailbox *mailbox; -+ struct resource *res; -+ int irq, ret; -+ -+ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -+ if (!mailbox) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mailbox->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(mailbox->regs)) -+ return PTR_ERR(mailbox->regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ ret = devm_request_irq(dev, irq, mbox_irq_handler, -+ IRQF_DISABLED | IRQF_IRQPOLL, -+ dev_name(dev), mailbox); -+ if (ret) { -+ dev_err(dev, "Interrupt request failed %d\n", ret); -+ return ret; -+ } - -- mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (!mailbox) { -- ret = -ENOMEM; -- } else { -- struct resource *res; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!res) { -- pr_err(DRIVER_NAME -- ": failed to obtain memory resource\n"); -- ret = -ENODEV; -- kfree(mailbox); -- } else { -- /* should be based on the registers from res really */ -- mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -- -- platform_set_drvdata(pdev, mailbox); -- dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ if (ret < 0) { -+ pr_err("Character device registration failed %d\n", ret); -+ return ret; -+ } - -- mbox_irqaction.dev_id = mailbox; -- setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- dev_info(&pdev->dev, "mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -- } -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ pr_err("Class creation failed %d\n", ret); -+ goto err_class; - } - -- if (ret == 0) { -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- if (ret < 0) { -- pr_err(DRIVER_NAME -- "Failed registering the character device %d\n", -- ret); -- return ret; -- } -- vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret; -- } -- device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -+ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); -+ if (IS_ERR(vdev)) { -+ ret = PTR_ERR(vdev); -+ pr_err("Device creation failed %d\n", ret); -+ goto err_dev; - } -+ -+ mbox_init(mailbox); -+ platform_set_drvdata(pdev, mailbox); -+ mbox_dev = dev; -+ -+ dev_info(dev, "mailbox at %p\n", mailbox->regs); -+ -+ return 0; -+ -+err_dev: -+ class_destroy(vcio_class); -+err_class: -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ - return ret; - } - - static int bcm_vcio_remove(struct platform_device *pdev) - { -- struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -- - mbox_dev = NULL; - platform_set_drvdata(pdev, NULL); -- kfree(mailbox); - device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); - class_destroy(vcio_class); - unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -@@ -391,6 +384,12 @@ static int bcm_vcio_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id bcm_vcio_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-vcio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -+ - static struct platform_driver bcm_mbox_driver = { - .probe = bcm_vcio_probe, - .remove = bcm_vcio_remove, -@@ -398,6 +397,7 @@ static struct platform_driver bcm_mbox_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm_vcio_of_match_table, - }, - }; - - -From bb294088d80bcba531bc3d58b4a6c08b8cdcb0b0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 19:11:03 +0200 -Subject: [PATCH 143/216] mailbox: bcm2708: Add bcm2708-vcio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Copy the arch vcio.c driver to drivers/mailbox. -This is done to make it available on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/Kconfig | 6 + - drivers/mailbox/Makefile | 2 + - drivers/mailbox/bcm2708-vcio.c | 426 ++++++++++++++++++++++++++ - include/linux/platform_data/mailbox-bcm2708.h | 126 ++++++++ - 4 files changed, 560 insertions(+) - create mode 100644 drivers/mailbox/bcm2708-vcio.c - create mode 100644 include/linux/platform_data/mailbox-bcm2708.h - -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index 84325f2..fdcb206 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -6,6 +6,12 @@ menuconfig MAILBOX - signals. Say Y if your platform supports hardware mailboxes. - - if MAILBOX -+config BCM2708_MBOX -+ bool "Broadcom BCM2708 Mailbox (vcio)" -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ help -+ Broadcom BCM2708 Mailbox (vcio) -+ - config PL320_MBOX - bool "ARM PL320 Mailbox" - depends on ARM_AMBA -diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile -index 2e79231..c2d2bed 100644 ---- a/drivers/mailbox/Makefile -+++ b/drivers/mailbox/Makefile -@@ -2,6 +2,8 @@ - - obj-$(CONFIG_MAILBOX) += mailbox.o - -+obj-$(CONFIG_BCM2708_MBOX) += bcm2708-vcio.o -+ - obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o - - obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -new file mode 100644 -index 0000000..ee3e778 ---- /dev/null -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -0,0 +1,426 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_vcio" -+#define DEVICE_FILE_NAME "vcio" -+ -+/* offsets from a mail box base address */ -+#define MAIL0_RD 0x00 /* read - and next 4 words */ -+#define MAIL0_POL 0x10 /* read without popping the fifo */ -+#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL0_STA 0x18 /* status */ -+#define MAIL0_CNF 0x1C /* configuration */ -+#define MAIL1_WRT 0x20 /* write - and next 4 words */ -+ -+/* On MACH_BCM270x these come through (arm_control.h ) */ -+#ifndef ARM_MS_EMPTY -+#define ARM_MS_EMPTY BIT(30) -+#define ARM_MS_FULL BIT(31) -+ -+#define ARM_MC_IHAVEDATAIRQEN BIT(0) -+#endif -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+#define MAJOR_NUM 100 -+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -+ -+static struct class *vcio_class; -+ -+struct vc_mailbox { -+ void __iomem *regs; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out) -+{ -+ int i; -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; -+ -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); -+ -+ return 0; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ if (mbox->magic != MBOX_MAGIC) -+ return -EINVAL; -+ -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ -+ return 0; -+} -+ -+static irqreturn_t mbox_irq_handler(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -+ int status = readl(mbox->regs + MAIL0_STA); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->regs + MAIL0_RD); -+ int chan = MBOX_CHAN(msg); -+ -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ pr_err(DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ pr_err(DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->regs + MAIL0_STA); -+ } -+ return ret; -+} -+ -+/* Mailbox Methods */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ int rc; -+ -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ int rc; -+ -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (!mbox_dev) -+ return -ENODEV; -+ -+ return dev_mbox_write(mbox_dev, chan, data28); -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (!mbox_dev) -+ return -ENODEV; -+ -+ return dev_mbox_read(mbox_dev, chan, data28); -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static int mbox_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)src < TASK_SIZE) -+ return copy_from_user(dst, src, size); -+ -+ memcpy(dst, src, size); -+ -+ return 0; -+} -+ -+static int mbox_copy_to_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)dst < TASK_SIZE) -+ return copy_to_user(dst, src, size); -+ -+ memcpy(dst, src, size); -+ -+ return 0; -+} -+ -+static DEFINE_MUTEX(mailbox_lock); -+extern int bcm_mailbox_property(void *data, int size) -+{ -+ uint32_t success; -+ dma_addr_t mem_bus; /* the memory address accessed from videocore */ -+ void *mem_kern; /* the memory address accessed from driver */ -+ int s = 0; -+ -+ mutex_lock(&mailbox_lock); -+ /* allocate some memory for the messages communicating with GPU */ -+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -+ GFP_ATOMIC); -+ if (mem_kern) { -+ /* create the message */ -+ mbox_copy_from_user(mem_kern, data, size); -+ -+ /* send the message */ -+ wmb(); -+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -+ if (s == 0) -+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -+ if (s == 0) { -+ /* copy the response */ -+ rmb(); -+ mbox_copy_to_user(data, mem_kern, size); -+ } -+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -+ } else { -+ s = -ENOMEM; -+ } -+ if (s != 0) -+ pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); -+ -+ mutex_unlock(&mailbox_lock); -+ return s; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_property); -+ -+/* Platform Device for Mailbox */ -+ -+/* -+ * Is the device open right now? Used to prevent -+ * concurent access into the same device -+ */ -+static bool device_is_open; -+ -+/* This is called whenever a process attempts to open the device file */ -+static int device_open(struct inode *inode, struct file *file) -+{ -+ /* We don't want to talk to two processes at the same time */ -+ if (device_is_open) -+ return -EBUSY; -+ -+ device_is_open = true; -+ try_module_get(THIS_MODULE); -+ -+ return 0; -+} -+ -+static int device_release(struct inode *inode, struct file *file) -+{ -+ /* We're now ready for our next caller */ -+ device_is_open = false; -+ -+ module_put(THIS_MODULE); -+ -+ return 0; -+} -+ -+/* -+ * This function is called whenever a process tries to do an ioctl on our -+ * device file. We get two extra parameters (additional to the inode and file -+ * structures, which all device functions get): the number of the ioctl called -+ * and the parameter given to the ioctl function. -+ * -+ * If the ioctl is write or read/write (meaning output is returned to the -+ * calling process), the ioctl call returns the output of this function. -+ * -+ */ -+static long device_ioctl(struct file *file, unsigned int ioctl_num, -+ unsigned long ioctl_param) -+{ -+ unsigned size; -+ -+ switch (ioctl_num) { -+ case IOCTL_MBOX_PROPERTY: -+ /* -+ * Receive a pointer to a message (in user space) and set that -+ * to be the device's message. Get the parameter given to -+ * ioctl by the process. -+ */ -+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); -+ return bcm_mailbox_property((void *)ioctl_param, size); -+ default: -+ pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Module Declarations */ -+ -+/* -+ * This structure will hold the functions to be called -+ * when a process does something to the device we -+ * created. Since a pointer to this structure is kept in -+ * the devices table, it can't be local to -+ * init_module. NULL is for unimplemented functios. -+ */ -+const struct file_operations fops = { -+ .unlocked_ioctl = device_ioctl, -+ .open = device_open, -+ .release = device_release, /* a.k.a. close */ -+}; -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device *vdev; -+ struct vc_mailbox *mailbox; -+ struct resource *res; -+ int irq, ret; -+ -+ mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -+ if (!mailbox) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mailbox->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(mailbox->regs)) -+ return PTR_ERR(mailbox->regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ ret = devm_request_irq(dev, irq, mbox_irq_handler, -+ IRQF_DISABLED | IRQF_IRQPOLL, -+ dev_name(dev), mailbox); -+ if (ret) { -+ dev_err(dev, "Interrupt request failed %d\n", ret); -+ return ret; -+ } -+ -+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -+ if (ret < 0) { -+ pr_err("Character device registration failed %d\n", ret); -+ return ret; -+ } -+ -+ vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vcio_class)) { -+ ret = PTR_ERR(vcio_class); -+ pr_err("Class creation failed %d\n", ret); -+ goto err_class; -+ } -+ -+ vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -+ "vcio"); -+ if (IS_ERR(vdev)) { -+ ret = PTR_ERR(vdev); -+ pr_err("Device creation failed %d\n", ret); -+ goto err_dev; -+ } -+ -+ mbox_init(mailbox); -+ platform_set_drvdata(pdev, mailbox); -+ mbox_dev = dev; -+ -+ dev_info(dev, "mailbox at %p\n", mailbox->regs); -+ -+ return 0; -+ -+err_dev: -+ class_destroy(vcio_class); -+err_class: -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ mbox_dev = NULL; -+ platform_set_drvdata(pdev, NULL); -+ device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -+ class_destroy(vcio_class); -+ unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm_vcio_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-vcio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = bcm_vcio_of_match_table, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ return platform_driver_register(&bcm_mbox_driver); -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -diff --git a/include/linux/platform_data/mailbox-bcm2708.h b/include/linux/platform_data/mailbox-bcm2708.h -new file mode 100644 -index 0000000..cc284ed ---- /dev/null -+++ b/include/linux/platform_data/mailbox-bcm2708.h -@@ -0,0 +1,126 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#ifndef _PLAT_MAILBOX_BCM2708_H -+#define _PLAT_MAILBOX_BCM2708_H -+ -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ -+#define MBOX_CHAN_COUNT 9 -+ -+enum { -+ VCMSG_PROCESS_REQUEST = 0x00000000 -+}; -+ -+enum { -+ VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -+ VCMSG_REQUEST_FAILED = 0x80000001 -+}; -+ -+/* Mailbox property tags */ -+enum { -+ VCMSG_PROPERTY_END = 0x00000000, -+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -+ VCMSG_GET_BOARD_MODEL = 0x00010001, -+ VCMSG_GET_BOARD_REVISION = 0x00010002, -+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -+ VCMSG_GET_BOARD_SERIAL = 0x00010004, -+ VCMSG_GET_ARM_MEMORY = 0x00010005, -+ VCMSG_GET_VC_MEMORY = 0x00010006, -+ VCMSG_GET_CLOCKS = 0x00010007, -+ VCMSG_GET_COMMAND_LINE = 0x00050001, -+ VCMSG_GET_DMA_CHANNELS = 0x00060001, -+ VCMSG_GET_POWER_STATE = 0x00020001, -+ VCMSG_GET_TIMING = 0x00020002, -+ VCMSG_SET_POWER_STATE = 0x00028001, -+ VCMSG_GET_CLOCK_STATE = 0x00030001, -+ VCMSG_SET_CLOCK_STATE = 0x00038001, -+ VCMSG_GET_CLOCK_RATE = 0x00030002, -+ VCMSG_SET_CLOCK_RATE = 0x00038002, -+ VCMSG_GET_VOLTAGE = 0x00030003, -+ VCMSG_SET_VOLTAGE = 0x00038003, -+ VCMSG_GET_MAX_CLOCK = 0x00030004, -+ VCMSG_GET_MAX_VOLTAGE = 0x00030005, -+ VCMSG_GET_TEMPERATURE = 0x00030006, -+ VCMSG_GET_MIN_CLOCK = 0x00030007, -+ VCMSG_GET_MIN_VOLTAGE = 0x00030008, -+ VCMSG_GET_TURBO = 0x00030009, -+ VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -+ VCMSG_GET_STC = 0x0003000b, -+ VCMSG_SET_TURBO = 0x00038009, -+ VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -+ VCMSG_SET_LOCK_MEM = 0x0003000d, -+ VCMSG_SET_UNLOCK_MEM = 0x0003000e, -+ VCMSG_SET_RELEASE_MEM = 0x0003000f, -+ VCMSG_SET_EXECUTE_CODE = 0x00030010, -+ VCMSG_SET_EXECUTE_QPU = 0x00030011, -+ VCMSG_SET_ENABLE_QPU = 0x00030012, -+ VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -+ VCMSG_GET_EDID_BLOCK = 0x00030020, -+ VCMSG_GET_CUSTOMER_OTP = 0x00030021, -+ VCMSG_SET_CUSTOMER_OTP = 0x00038021, -+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -+ VCMSG_SET_RELEASE_BUFFER = 0x00048001, -+ VCMSG_SET_BLANK_SCREEN = 0x00040002, -+ VCMSG_TST_BLANK_SCREEN = 0x00044002, -+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -+ VCMSG_GET_DEPTH = 0x00040005, -+ VCMSG_TST_DEPTH = 0x00044005, -+ VCMSG_SET_DEPTH = 0x00048005, -+ VCMSG_GET_PIXEL_ORDER = 0x00040006, -+ VCMSG_TST_PIXEL_ORDER = 0x00044006, -+ VCMSG_SET_PIXEL_ORDER = 0x00048006, -+ VCMSG_GET_ALPHA_MODE = 0x00040007, -+ VCMSG_TST_ALPHA_MODE = 0x00044007, -+ VCMSG_SET_ALPHA_MODE = 0x00048007, -+ VCMSG_GET_PITCH = 0x00040008, -+ VCMSG_TST_PITCH = 0x00044008, -+ VCMSG_SET_PITCH = 0x00048008, -+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -+ VCMSG_GET_OVERSCAN = 0x0004000a, -+ VCMSG_TST_OVERSCAN = 0x0004400a, -+ VCMSG_SET_OVERSCAN = 0x0004800a, -+ VCMSG_GET_PALETTE = 0x0004000b, -+ VCMSG_TST_PALETTE = 0x0004400b, -+ VCMSG_SET_PALETTE = 0x0004800b, -+ VCMSG_GET_LAYER = 0x0004000c, -+ VCMSG_TST_LAYER = 0x0004400c, -+ VCMSG_SET_LAYER = 0x0004800c, -+ VCMSG_GET_TRANSFORM = 0x0004000d, -+ VCMSG_TST_TRANSFORM = 0x0004400d, -+ VCMSG_SET_TRANSFORM = 0x0004800d, -+ VCMSG_TST_VSYNC = 0x0004400e, -+ VCMSG_SET_VSYNC = 0x0004800e, -+ VCMSG_SET_CURSOR_INFO = 0x00008010, -+ VCMSG_SET_CURSOR_STATE = 0x00008011, -+}; -+ -+int bcm_mailbox_read(unsigned chan, uint32_t *data28); -+int bcm_mailbox_write(unsigned chan, uint32_t data28); -+int bcm_mailbox_property(void *data, int size); -+ -+#endif - -From 1e5c7135fc145addcf195d02759a45e162f2daac Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 19:11:58 +0200 -Subject: [PATCH 144/216] BCM270x: power: Change initcall level to subsys -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Load ordering of modules are determined by the initcall used. -If it's the same initcall level, makefile ordering decides. -Now that the mailbox driver is being moved, it's no longer -placed before the power driver by the linker. -So use a later initcall level to let the mailbox driver -load first. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/power.c | 6 +++++- - arch/arm/mach-bcm2709/power.c | 6 +++++- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -index 2696be9..0db355d 100644 ---- a/arch/arm/mach-bcm2708/power.c -+++ b/arch/arm/mach-bcm2708/power.c -@@ -189,7 +189,11 @@ static void __exit bcm_power_exit(void) - bcm_mailbox_write(MBOX_CHAN_POWER, 0); - } - --arch_initcall(bcm_power_init); /* Initialize early */ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); - module_exit(bcm_power_exit); - - MODULE_AUTHOR("Phil Elwell"); -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -index 3421057..88c1e28 100644 ---- a/arch/arm/mach-bcm2709/power.c -+++ b/arch/arm/mach-bcm2709/power.c -@@ -187,7 +187,11 @@ static void __exit bcm_power_exit(void) - bcm_mailbox_write(MBOX_CHAN_POWER, 0); - } - --arch_initcall(bcm_power_init); /* Initialize early */ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); - module_exit(bcm_power_exit); - - MODULE_AUTHOR("Phil Elwell"); - -From 41e80f86dc78015856087cccd8e4f9a251042f9d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:34:26 +0200 -Subject: [PATCH 145/216] BCM270x: Use bcm2708-vcio -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use bcm2708-vcio instead of the arch version. -Change affected drivers to use linux/platform_data/mailbox-bcm2708.h - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/power.c | 2 +- - arch/arm/mach-bcm2708/vc_mem.c | 2 +- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/power.c | 2 +- - arch/arm/mach-bcm2709/vc_mem.c | 2 +- - arch/arm/mach-bcm2709/vc_support.c | 2 +- - drivers/cpufreq/bcm2835-cpufreq.c | 2 +- - drivers/hwmon/bcm2835-hwmon.c | 2 +- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- - drivers/thermal/bcm2835-thermal.c | 2 +- - drivers/video/fbdev/bcm2708_fb.c | 2 +- - 14 files changed, 16 insertions(+), 12 deletions(-) - mode change 100755 => 100644 arch/arm/mach-bcm2709/vc_support.c - mode change 100755 => 100644 drivers/cpufreq/bcm2835-cpufreq.c - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 367a04a..ff87581 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1052,6 +1052,8 @@ CONFIG_FB_TFT_UPD161704=m - CONFIG_FB_TFT_WATTEROTT=m - CONFIG_FB_FLEX=m - CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXTCON=m - CONFIG_EXTCON_ARIZONA=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index db287f3..e339979 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1045,6 +1045,8 @@ CONFIG_FB_TFT_UPD161704=m - CONFIG_FB_TFT_WATTEROTT=m - CONFIG_FB_FLEX=m - CONFIG_FB_TFT_FBTFT_DEVICE=m -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXTCON=m - CONFIG_EXTCON_ARIZONA=m -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 454408c..c1e7d41 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o vcio.o power.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -index 0db355d..796837f 100644 ---- a/arch/arm/mach-bcm2708/power.c -+++ b/arch/arm/mach-bcm2708/power.c -@@ -14,8 +14,8 @@ - #include - #include - #include -+#include - #include --#include - #include - - #define DRIVER_NAME "bcm2708_power" -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index 2982af7..226b737 100644 ---- a/arch/arm/mach-bcm2708/vc_mem.c -+++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_ARCH_KONA - #include -@@ -31,7 +32,6 @@ - #endif - - #include "mach/vc_mem.h" --#include - - #define DRIVER_NAME "vc-mem" - -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index f07c38b..77b8429 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o vcio.o power.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o power.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -index 88c1e28..960e472 100644 ---- a/arch/arm/mach-bcm2709/power.c -+++ b/arch/arm/mach-bcm2709/power.c -@@ -14,8 +14,8 @@ - #include - #include - #include -+#include - #include --#include - #include - - #define DRIVER_NAME "bcm2708_power" -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -index ac578db..d2adfd1 100644 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ b/arch/arm/mach-bcm2709/vc_mem.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_ARCH_KONA - #include -@@ -31,7 +32,6 @@ - #endif - - #include "mach/vc_mem.h" --#include - - #define DRIVER_NAME "vc-mem" - -diff --git a/arch/arm/mach-bcm2709/vc_support.c b/arch/arm/mach-bcm2709/vc_support.c -old mode 100755 -new mode 100644 -index 0bc41c4..c4dc7d6 ---- a/arch/arm/mach-bcm2709/vc_support.c -+++ b/arch/arm/mach-bcm2709/vc_support.c -@@ -6,7 +6,7 @@ - */ - - #include --#include -+#include - - #ifdef ECLIPSE_IGNORE - -diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c -old mode 100755 -new mode 100644 -index 447ca09..6735da9 ---- a/drivers/cpufreq/bcm2835-cpufreq.c -+++ b/drivers/cpufreq/bcm2835-cpufreq.c -@@ -26,7 +26,7 @@ - #include - #include - #include --#include -+#include - - /* ---------- DEFINES ---------- */ - /*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */ -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -index 5bbed45..d14502c 100644 ---- a/drivers/hwmon/bcm2835-hwmon.c -+++ b/drivers/hwmon/bcm2835-hwmon.c -@@ -17,9 +17,9 @@ - #include - #include - #include -+#include - #include - #include --#include - #include - #include - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 8ec88bb..70e5086 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -40,13 +40,13 @@ - #include - #include - #include -+#include - #include - #include - - #include - - #include --#include - - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - -diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c -index 85fceb5..0c556d1 100644 ---- a/drivers/thermal/bcm2835-thermal.c -+++ b/drivers/thermal/bcm2835-thermal.c -@@ -15,10 +15,10 @@ - #include - #include - #include -+#include - #include - #include - #include --#include - #include - - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 52e655a..345c15e 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,7 +33,6 @@ - - #include - #include --#include - - #include - #include - -From 5bb0a0c80fc46ae0edea87f97244f28fb167dfe0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 2 May 2015 09:35:07 +0200 -Subject: [PATCH 146/216] BCM270x: Remove arch driver vcio.c -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Remove the arch vcio.c driver and header file. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/vcio.h | 128 -------- - arch/arm/mach-bcm2708/vcio.c | 419 -------------------------- - arch/arm/mach-bcm2709/include/mach/vcio.h | 165 ---------- - arch/arm/mach-bcm2709/vcio.c | 484 ------------------------------ - 4 files changed, 1196 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h - delete mode 100644 arch/arm/mach-bcm2708/vcio.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vcio.h - delete mode 100644 arch/arm/mach-bcm2709/vcio.c - -diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h -deleted file mode 100644 -index 95ad121..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/vcio.h -+++ /dev/null -@@ -1,128 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vcio.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- */ --#ifndef _MACH_BCM2708_VCIO_H --#define _MACH_BCM2708_VCIO_H -- --/* Routines to handle I/O via the VideoCore "ARM control" registers -- * (semaphores, doorbells, mailboxes) -- */ -- --/* Constants shared with the ARM identifying separate mailbox channels */ --#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ --#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ --#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ --#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ --#define MBOX_CHAN_COUNT 9 -- --enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 --}; -- --enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 --}; -- --/* Mailbox property tags */ --enum { -- VCMSG_PROPERTY_END = 0x00000000, -- VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -- VCMSG_GET_BOARD_MODEL = 0x00010001, -- VCMSG_GET_BOARD_REVISION = 0x00010002, -- VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -- VCMSG_GET_BOARD_SERIAL = 0x00010004, -- VCMSG_GET_ARM_MEMORY = 0x00010005, -- VCMSG_GET_VC_MEMORY = 0x00010006, -- VCMSG_GET_CLOCKS = 0x00010007, -- VCMSG_GET_COMMAND_LINE = 0x00050001, -- VCMSG_GET_DMA_CHANNELS = 0x00060001, -- VCMSG_GET_POWER_STATE = 0x00020001, -- VCMSG_GET_TIMING = 0x00020002, -- VCMSG_SET_POWER_STATE = 0x00028001, -- VCMSG_GET_CLOCK_STATE = 0x00030001, -- VCMSG_SET_CLOCK_STATE = 0x00038001, -- VCMSG_GET_CLOCK_RATE = 0x00030002, -- VCMSG_SET_CLOCK_RATE = 0x00038002, -- VCMSG_GET_VOLTAGE = 0x00030003, -- VCMSG_SET_VOLTAGE = 0x00038003, -- VCMSG_GET_MAX_CLOCK = 0x00030004, -- VCMSG_GET_MAX_VOLTAGE = 0x00030005, -- VCMSG_GET_TEMPERATURE = 0x00030006, -- VCMSG_GET_MIN_CLOCK = 0x00030007, -- VCMSG_GET_MIN_VOLTAGE = 0x00030008, -- VCMSG_GET_TURBO = 0x00030009, -- VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -- VCMSG_GET_STC = 0x0003000b, -- VCMSG_SET_TURBO = 0x00038009, -- VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -- VCMSG_SET_LOCK_MEM = 0x0003000d, -- VCMSG_SET_UNLOCK_MEM = 0x0003000e, -- VCMSG_SET_RELEASE_MEM = 0x0003000f, -- VCMSG_SET_EXECUTE_CODE = 0x00030010, -- VCMSG_SET_EXECUTE_QPU = 0x00030011, -- VCMSG_SET_ENABLE_QPU = 0x00030012, -- VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -- VCMSG_GET_EDID_BLOCK = 0x00030020, -- VCMSG_GET_CUSTOMER_OTP = 0x00030021, -- VCMSG_SET_CUSTOMER_OTP = 0x00038021, -- VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -- VCMSG_SET_RELEASE_BUFFER = 0x00048001, -- VCMSG_SET_BLANK_SCREEN = 0x00040002, -- VCMSG_TST_BLANK_SCREEN = 0x00044002, -- VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -- VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -- VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -- VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -- VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -- VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -- VCMSG_GET_DEPTH = 0x00040005, -- VCMSG_TST_DEPTH = 0x00044005, -- VCMSG_SET_DEPTH = 0x00048005, -- VCMSG_GET_PIXEL_ORDER = 0x00040006, -- VCMSG_TST_PIXEL_ORDER = 0x00044006, -- VCMSG_SET_PIXEL_ORDER = 0x00048006, -- VCMSG_GET_ALPHA_MODE = 0x00040007, -- VCMSG_TST_ALPHA_MODE = 0x00044007, -- VCMSG_SET_ALPHA_MODE = 0x00048007, -- VCMSG_GET_PITCH = 0x00040008, -- VCMSG_TST_PITCH = 0x00044008, -- VCMSG_SET_PITCH = 0x00048008, -- VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -- VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -- VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -- VCMSG_GET_OVERSCAN = 0x0004000a, -- VCMSG_TST_OVERSCAN = 0x0004400a, -- VCMSG_SET_OVERSCAN = 0x0004800a, -- VCMSG_GET_PALETTE = 0x0004000b, -- VCMSG_TST_PALETTE = 0x0004400b, -- VCMSG_SET_PALETTE = 0x0004800b, -- VCMSG_GET_LAYER = 0x0004000c, -- VCMSG_TST_LAYER = 0x0004400c, -- VCMSG_SET_LAYER = 0x0004800c, -- VCMSG_GET_TRANSFORM = 0x0004000d, -- VCMSG_TST_TRANSFORM = 0x0004400d, -- VCMSG_SET_TRANSFORM = 0x0004800d, -- VCMSG_TST_VSYNC = 0x0004400e, -- VCMSG_SET_VSYNC = 0x0004800e, -- VCMSG_SET_CURSOR_INFO = 0x00008010, -- VCMSG_SET_CURSOR_STATE = 0x00008011, --}; -- --extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); --extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); --extern int /*rc*/ bcm_mailbox_property(void *data, int size); -- --#endif -diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c -deleted file mode 100644 -index c4c2bcd..0000000 ---- a/arch/arm/mach-bcm2708/vcio.c -+++ /dev/null -@@ -1,419 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/vcio.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for writing to the mailboxes, -- * semaphores, doorbells etc. that are shared between the ARM and the -- * VideoCore processor -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#define DRIVER_NAME "bcm2708_vcio" --#define DEVICE_FILE_NAME "vcio" -- --/* offsets from a mail box base address */ --#define MAIL0_RD 0x00 /* read - and next 4 words */ --#define MAIL0_POL 0x10 /* read without popping the fifo */ --#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL0_STA 0x18 /* status */ --#define MAIL0_CNF 0x1C /* configuration */ --#define MAIL1_WRT 0x20 /* write - and next 4 words */ -- --#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) --#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) --#define MBOX_CHAN(msg) ((msg) & 0xf) --#define MBOX_DATA28(msg) ((msg) & ~0xf) --#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -- --#define MBOX_MAGIC 0xd0d0c0de -- --#define MAJOR_NUM 100 --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -- --static struct class *vcio_class; -- --struct vc_mailbox { -- void __iomem *regs; -- uint32_t msg[MBOX_CHAN_COUNT]; -- struct semaphore sema[MBOX_CHAN_COUNT]; -- uint32_t magic; --}; -- --static void mbox_init(struct vc_mailbox *mbox_out) --{ -- int i; -- -- for (i = 0; i < MBOX_CHAN_COUNT; i++) { -- mbox_out->msg[i] = 0; -- sema_init(&mbox_out->sema[i], 0); -- } -- -- /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); -- -- mbox_out->magic = MBOX_MAGIC; --} -- --static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) --{ -- if (mbox->magic != MBOX_MAGIC) -- return -EINVAL; -- -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -- cpu_relax(); -- -- writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); -- -- return 0; --} -- --static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) --{ -- if (mbox->magic != MBOX_MAGIC) -- return -EINVAL; -- -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- -- return 0; --} -- --static irqreturn_t mbox_irq_handler(int irq, void *dev_id) --{ -- /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; -- int status = readl(mbox->regs + MAIL0_STA); -- int ret = IRQ_NONE; -- -- while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->regs + MAIL0_RD); -- int chan = MBOX_CHAN(msg); -- -- if (chan < MBOX_CHAN_COUNT) { -- if (mbox->msg[chan]) { -- pr_err(DRIVER_NAME -- ": mbox chan %d overflow - drop %08x\n", -- chan, msg); -- } else { -- mbox->msg[chan] = (msg | 0xf); -- up(&mbox->sema[chan]); -- } -- } else { -- pr_err(DRIVER_NAME -- ": invalid channel selector (msg %08x)\n", msg); -- } -- ret = IRQ_HANDLED; -- status = readl(mbox->regs + MAIL0_STA); -- } -- return ret; --} -- --/* Mailbox Methods */ -- --static struct device *mbox_dev; /* we assume there's only one! */ -- --static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) --{ -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- int rc; -- -- device_lock(dev); -- rc = mbox_write(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) --{ -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- int rc; -- -- device_lock(dev); -- rc = mbox_read(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --extern int bcm_mailbox_write(unsigned chan, uint32_t data28) --{ -- if (!mbox_dev) -- return -ENODEV; -- -- return dev_mbox_write(mbox_dev, chan, data28); --} --EXPORT_SYMBOL_GPL(bcm_mailbox_write); -- --extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) --{ -- if (!mbox_dev) -- return -ENODEV; -- -- return dev_mbox_read(mbox_dev, chan, data28); --} --EXPORT_SYMBOL_GPL(bcm_mailbox_read); -- --static int mbox_copy_from_user(void *dst, const void *src, int size) --{ -- if ((uint32_t)src < TASK_SIZE) -- return copy_from_user(dst, src, size); -- -- memcpy(dst, src, size); -- -- return 0; --} -- --static int mbox_copy_to_user(void *dst, const void *src, int size) --{ -- if ((uint32_t)dst < TASK_SIZE) -- return copy_to_user(dst, src, size); -- -- memcpy(dst, src, size); -- -- return 0; --} -- --static DEFINE_MUTEX(mailbox_lock); --extern int bcm_mailbox_property(void *data, int size) --{ -- uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -- int s = 0; -- -- mutex_lock(&mailbox_lock); -- /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -- GFP_ATOMIC); -- if (mem_kern) { -- /* create the message */ -- mbox_copy_from_user(mem_kern, data, size); -- -- /* send the message */ -- wmb(); -- s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) -- s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- if (s == 0) { -- /* copy the response */ -- rmb(); -- mbox_copy_to_user(data, mem_kern, size); -- } -- dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -- } else { -- s = -ENOMEM; -- } -- if (s != 0) -- pr_err(DRIVER_NAME ": %s failed (%d)\n", __func__, s); -- -- mutex_unlock(&mailbox_lock); -- return s; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_property); -- --/* Platform Device for Mailbox */ -- --/* -- * Is the device open right now? Used to prevent -- * concurent access into the same device -- */ --static bool device_is_open; -- --/* This is called whenever a process attempts to open the device file */ --static int device_open(struct inode *inode, struct file *file) --{ -- /* We don't want to talk to two processes at the same time */ -- if (device_is_open) -- return -EBUSY; -- -- device_is_open = true; -- try_module_get(THIS_MODULE); -- -- return 0; --} -- --static int device_release(struct inode *inode, struct file *file) --{ -- /* We're now ready for our next caller */ -- device_is_open = false; -- -- module_put(THIS_MODULE); -- -- return 0; --} -- --/* -- * This function is called whenever a process tries to do an ioctl on our -- * device file. We get two extra parameters (additional to the inode and file -- * structures, which all device functions get): the number of the ioctl called -- * and the parameter given to the ioctl function. -- * -- * If the ioctl is write or read/write (meaning output is returned to the -- * calling process), the ioctl call returns the output of this function. -- * -- */ --static long device_ioctl(struct file *file, unsigned int ioctl_num, -- unsigned long ioctl_param) --{ -- unsigned size; -- -- switch (ioctl_num) { -- case IOCTL_MBOX_PROPERTY: -- /* -- * Receive a pointer to a message (in user space) and set that -- * to be the device's message. Get the parameter given to -- * ioctl by the process. -- */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); -- return bcm_mailbox_property((void *)ioctl_param, size); -- default: -- pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -- return -EINVAL; -- } -- -- return 0; --} -- --/* Module Declarations */ -- --/* -- * This structure will hold the functions to be called -- * when a process does something to the device we -- * created. Since a pointer to this structure is kept in -- * the devices table, it can't be local to -- * init_module. NULL is for unimplemented functios. -- */ --const struct file_operations fops = { -- .unlocked_ioctl = device_ioctl, -- .open = device_open, -- .release = device_release, /* a.k.a. close */ --}; -- --static int bcm_vcio_probe(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- struct device *vdev; -- struct vc_mailbox *mailbox; -- struct resource *res; -- int irq, ret; -- -- mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); -- if (!mailbox) -- return -ENOMEM; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- mailbox->regs = devm_ioremap_resource(dev, res); -- if (IS_ERR(mailbox->regs)) -- return PTR_ERR(mailbox->regs); -- -- irq = platform_get_irq(pdev, 0); -- ret = devm_request_irq(dev, irq, mbox_irq_handler, -- IRQF_DISABLED | IRQF_IRQPOLL, -- dev_name(dev), mailbox); -- if (ret) { -- dev_err(dev, "Interrupt request failed %d\n", ret); -- return ret; -- } -- -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- if (ret < 0) { -- pr_err("Character device registration failed %d\n", ret); -- return ret; -- } -- -- vcio_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- pr_err("Class creation failed %d\n", ret); -- goto err_class; -- } -- -- vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -- if (IS_ERR(vdev)) { -- ret = PTR_ERR(vdev); -- pr_err("Device creation failed %d\n", ret); -- goto err_dev; -- } -- -- mbox_init(mailbox); -- platform_set_drvdata(pdev, mailbox); -- mbox_dev = dev; -- -- dev_info(dev, "mailbox at %p\n", mailbox->regs); -- -- return 0; -- --err_dev: -- class_destroy(vcio_class); --err_class: -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- -- return ret; --} -- --static int bcm_vcio_remove(struct platform_device *pdev) --{ -- mbox_dev = NULL; -- platform_set_drvdata(pdev, NULL); -- device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- -- return 0; --} -- --static const struct of_device_id bcm_vcio_of_match_table[] = { -- { .compatible = "brcm,bcm2708-vcio", }, -- {}, --}; --MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); -- --static struct platform_driver bcm_mbox_driver = { -- .probe = bcm_vcio_probe, -- .remove = bcm_vcio_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- .of_match_table = bcm_vcio_of_match_table, -- }, --}; -- --static int __init bcm_mbox_init(void) --{ -- return platform_driver_register(&bcm_mbox_driver); --} -- --static void __exit bcm_mbox_exit(void) --{ -- platform_driver_unregister(&bcm_mbox_driver); --} -- --arch_initcall(bcm_mbox_init); /* Initialize early */ --module_exit(bcm_mbox_exit); -- --MODULE_AUTHOR("Gray Girling"); --MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); --MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2709/include/mach/vcio.h b/arch/arm/mach-bcm2709/include/mach/vcio.h -deleted file mode 100644 -index 8e11d67e..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/vcio.h -+++ /dev/null -@@ -1,165 +0,0 @@ --/* -- * arch/arm/mach-bcm2708/include/mach/vcio.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#ifndef _MACH_BCM2708_VCIO_H --#define _MACH_BCM2708_VCIO_H -- --/* Routines to handle I/O via the VideoCore "ARM control" registers -- * (semaphores, doorbells, mailboxes) -- */ -- --#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -- --/* Constants shared with the ARM identifying separate mailbox channels */ --#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ --#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ --#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ --#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ --#define MBOX_CHAN_COUNT 9 -- --enum { -- VCMSG_PROCESS_REQUEST = 0x00000000 --}; --enum { -- VCMSG_REQUEST_SUCCESSFUL = 0x80000000, -- VCMSG_REQUEST_FAILED = 0x80000001 --}; --/* Mailbox property tags */ --enum { -- VCMSG_PROPERTY_END = 0x00000000, -- VCMSG_GET_FIRMWARE_REVISION = 0x00000001, -- VCMSG_GET_BOARD_MODEL = 0x00010001, -- VCMSG_GET_BOARD_REVISION = 0x00010002, -- VCMSG_GET_BOARD_MAC_ADDRESS = 0x00010003, -- VCMSG_GET_BOARD_SERIAL = 0x00010004, -- VCMSG_GET_ARM_MEMORY = 0x00010005, -- VCMSG_GET_VC_MEMORY = 0x00010006, -- VCMSG_GET_CLOCKS = 0x00010007, -- VCMSG_GET_COMMAND_LINE = 0x00050001, -- VCMSG_GET_DMA_CHANNELS = 0x00060001, -- VCMSG_GET_POWER_STATE = 0x00020001, -- VCMSG_GET_TIMING = 0x00020002, -- VCMSG_SET_POWER_STATE = 0x00028001, -- VCMSG_GET_CLOCK_STATE = 0x00030001, -- VCMSG_SET_CLOCK_STATE = 0x00038001, -- VCMSG_GET_CLOCK_RATE = 0x00030002, -- VCMSG_SET_CLOCK_RATE = 0x00038002, -- VCMSG_GET_VOLTAGE = 0x00030003, -- VCMSG_SET_VOLTAGE = 0x00038003, -- VCMSG_GET_MAX_CLOCK = 0x00030004, -- VCMSG_GET_MAX_VOLTAGE = 0x00030005, -- VCMSG_GET_TEMPERATURE = 0x00030006, -- VCMSG_GET_MIN_CLOCK = 0x00030007, -- VCMSG_GET_MIN_VOLTAGE = 0x00030008, -- VCMSG_GET_TURBO = 0x00030009, -- VCMSG_GET_MAX_TEMPERATURE = 0x0003000a, -- VCMSG_GET_STC = 0x0003000b, -- VCMSG_SET_TURBO = 0x00038009, -- VCMSG_SET_ALLOCATE_MEM = 0x0003000c, -- VCMSG_SET_LOCK_MEM = 0x0003000d, -- VCMSG_SET_UNLOCK_MEM = 0x0003000e, -- VCMSG_SET_RELEASE_MEM = 0x0003000f, -- VCMSG_SET_EXECUTE_CODE = 0x00030010, -- VCMSG_SET_EXECUTE_QPU = 0x00030011, -- VCMSG_SET_ENABLE_QPU = 0x00030012, -- VCMSG_GET_RESOURCE_HANDLE = 0x00030014, -- VCMSG_GET_EDID_BLOCK = 0x00030020, -- VCMSG_GET_CUSTOMER_OTP = 0x00030021, -- VCMSG_SET_CUSTOMER_OTP = 0x00038021, -- VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, -- VCMSG_SET_RELEASE_BUFFER = 0x00048001, -- VCMSG_SET_BLANK_SCREEN = 0x00040002, -- VCMSG_TST_BLANK_SCREEN = 0x00044002, -- VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, -- VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, -- VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, -- VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, -- VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, -- VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, -- VCMSG_GET_DEPTH = 0x00040005, -- VCMSG_TST_DEPTH = 0x00044005, -- VCMSG_SET_DEPTH = 0x00048005, -- VCMSG_GET_PIXEL_ORDER = 0x00040006, -- VCMSG_TST_PIXEL_ORDER = 0x00044006, -- VCMSG_SET_PIXEL_ORDER = 0x00048006, -- VCMSG_GET_ALPHA_MODE = 0x00040007, -- VCMSG_TST_ALPHA_MODE = 0x00044007, -- VCMSG_SET_ALPHA_MODE = 0x00048007, -- VCMSG_GET_PITCH = 0x00040008, -- VCMSG_TST_PITCH = 0x00044008, -- VCMSG_SET_PITCH = 0x00048008, -- VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, -- VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, -- VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, -- VCMSG_GET_OVERSCAN = 0x0004000a, -- VCMSG_TST_OVERSCAN = 0x0004400a, -- VCMSG_SET_OVERSCAN = 0x0004800a, -- VCMSG_GET_PALETTE = 0x0004000b, -- VCMSG_TST_PALETTE = 0x0004400b, -- VCMSG_SET_PALETTE = 0x0004800b, -- VCMSG_GET_LAYER = 0x0004000c, -- VCMSG_TST_LAYER = 0x0004400c, -- VCMSG_SET_LAYER = 0x0004800c, -- VCMSG_GET_TRANSFORM = 0x0004000d, -- VCMSG_TST_TRANSFORM = 0x0004400d, -- VCMSG_SET_TRANSFORM = 0x0004800d, -- VCMSG_TST_VSYNC = 0x0004400e, -- VCMSG_SET_VSYNC = 0x0004800e, -- VCMSG_SET_CURSOR_INFO = 0x00008010, -- VCMSG_SET_CURSOR_STATE = 0x00008011, --}; -- --extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); --extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); --extern int /*rc*/ bcm_mailbox_property(void *data, int size); -- --#include -- --/* -- * The major device number. We can't rely on dynamic -- * registration any more, because ioctls need to know -- * it. -- */ --#define MAJOR_NUM 100 -- --/* -- * Set the message of the device driver -- */ --#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) --/* -- * _IOWR means that we're creating an ioctl command -- * number for passing information from a user process -- * to the kernel module and from the kernel module to user process -- * -- * The first arguments, MAJOR_NUM, is the major device -- * number we're using. -- * -- * The second argument is the number of the command -- * (there could be several with different meanings). -- * -- * The third argument is the type we want to get from -- * the process to the kernel. -- */ -- --/* -- * The name of the device file -- */ --#define DEVICE_FILE_NAME "vcio" -- --#endif -diff --git a/arch/arm/mach-bcm2709/vcio.c b/arch/arm/mach-bcm2709/vcio.c -deleted file mode 100644 -index 700bff4..0000000 ---- a/arch/arm/mach-bcm2709/vcio.c -+++ /dev/null -@@ -1,484 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/vcio.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for writing to the mailboxes, -- * semaphores, doorbells etc. that are shared between the ARM and the -- * VideoCore processor -- */ -- --#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) --#define SUPPORT_SYSRQ --#endif -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include --#include -- --#include -- -- --#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -- --/* ---------------------------------------------------------------------- -- * Mailbox -- * -------------------------------------------------------------------- */ -- --/* offsets from a mail box base address */ --#define MAIL_WRT 0x00 /* write - and next 4 words */ --#define MAIL_RD 0x00 /* read - and next 4 words */ --#define MAIL_POL 0x10 /* read without popping the fifo */ --#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ --#define MAIL_STA 0x18 /* status */ --#define MAIL_CNF 0x1C /* configuration */ -- --#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) --#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) --#define MBOX_CHAN(msg) ((msg) & 0xf) --#define MBOX_DATA28(msg) ((msg) & ~0xf) --#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -- --#define MBOX_MAGIC 0xd0d0c0de --static struct class *vcio_class = NULL; --struct vc_mailbox { -- struct device *dev; /* parent device */ -- void __iomem *status; -- void __iomem *config; -- void __iomem *read; -- void __iomem *write; -- uint32_t msg[MBOX_CHAN_COUNT]; -- struct semaphore sema[MBOX_CHAN_COUNT]; -- uint32_t magic; --}; -- --static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -- uint32_t addr_mbox) --{ -- int i; -- -- mbox_out->dev = dev; -- mbox_out->status = __io_address(addr_mbox + MAIL_STA); -- mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -- mbox_out->read = __io_address(addr_mbox + MAIL_RD); -- /* Write to the other mailbox */ -- mbox_out->write = -- __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -- MAIL_WRT); -- -- for (i = 0; i < MBOX_CHAN_COUNT; i++) { -- mbox_out->msg[i] = 0; -- sema_init(&mbox_out->sema[i], 0); -- } -- -- /* Enable the interrupt on data reception */ -- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -- -- mbox_out->magic = MBOX_MAGIC; --} -- --static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) --{ -- int rc; -- -- if (mbox->magic != MBOX_MAGIC) -- rc = -EINVAL; -- else { -- /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->status) & ARM_MS_FULL)) -- cpu_relax(); -- -- writel(MBOX_MSG(chan, data28), mbox->write); -- rc = 0; -- } -- return rc; --} -- --static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) --{ -- int rc; -- -- if (mbox->magic != MBOX_MAGIC) -- rc = -EINVAL; -- else { -- down(&mbox->sema[chan]); -- *data28 = MBOX_DATA28(mbox->msg[chan]); -- mbox->msg[chan] = 0; -- rc = 0; -- } -- return rc; --} -- --static irqreturn_t mbox_irq(int irq, void *dev_id) --{ -- /* wait for the mailbox FIFO to have some data in it */ -- struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -- int status = readl(mbox->status); -- int ret = IRQ_NONE; -- -- while (!(status & ARM_MS_EMPTY)) { -- uint32_t msg = readl(mbox->read); -- int chan = MBOX_CHAN(msg); -- if (chan < MBOX_CHAN_COUNT) { -- if (mbox->msg[chan]) { -- /* Overflow */ -- printk(KERN_ERR DRIVER_NAME -- ": mbox chan %d overflow - drop %08x\n", -- chan, msg); -- } else { -- mbox->msg[chan] = (msg | 0xf); -- up(&mbox->sema[chan]); -- } -- } else { -- printk(KERN_ERR DRIVER_NAME -- ": invalid channel selector (msg %08x)\n", msg); -- } -- ret = IRQ_HANDLED; -- status = readl(mbox->status); -- } -- return ret; --} -- --static struct irqaction mbox_irqaction = { -- .name = "ARM Mailbox IRQ", -- .flags = IRQF_DISABLED | IRQF_IRQPOLL, -- .handler = mbox_irq, --}; -- --/* ---------------------------------------------------------------------- -- * Mailbox Methods -- * -------------------------------------------------------------------- */ -- --static struct device *mbox_dev; /* we assume there's only one! */ -- --static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) --{ -- int rc; -- -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- device_lock(dev); -- rc = mbox_write(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) --{ -- int rc; -- -- struct vc_mailbox *mailbox = dev_get_drvdata(dev); -- device_lock(dev); -- rc = mbox_read(mailbox, chan, data28); -- device_unlock(dev); -- -- return rc; --} -- --extern int bcm_mailbox_write(unsigned chan, uint32_t data28) --{ -- if (mbox_dev) -- return dev_mbox_write(mbox_dev, chan, data28); -- else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_write); -- --extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) --{ -- if (mbox_dev) -- return dev_mbox_read(mbox_dev, chan, data28); -- else -- return -ENODEV; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_read); -- --static void dev_mbox_register(const char *dev_name, struct device *dev) --{ -- mbox_dev = dev; --} -- --static int mbox_copy_from_user(void *dst, const void *src, int size) --{ -- if ( (uint32_t)src < TASK_SIZE) -- { -- return copy_from_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } --} -- --static int mbox_copy_to_user(void *dst, const void *src, int size) --{ -- if ( (uint32_t)dst < TASK_SIZE) -- { -- return copy_to_user(dst, src, size); -- } -- else -- { -- memcpy( dst, src, size ); -- return 0; -- } --} -- --static DEFINE_MUTEX(mailbox_lock); --extern int bcm_mailbox_property(void *data, int size) --{ -- uint32_t success; -- dma_addr_t mem_bus; /* the memory address accessed from videocore */ -- void *mem_kern; /* the memory address accessed from driver */ -- int s = 0; -- -- mutex_lock(&mailbox_lock); -- /* allocate some memory for the messages communicating with GPU */ -- mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); -- if (mem_kern) { -- /* create the message */ -- mbox_copy_from_user(mem_kern, data, size); -- -- /* send the message */ -- wmb(); -- s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); -- if (s == 0) { -- s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); -- } -- if (s == 0) { -- /* copy the response */ -- rmb(); -- mbox_copy_to_user(data, mem_kern, size); -- } -- dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); -- } else { -- s = -ENOMEM; -- } -- if (s != 0) -- printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); -- -- mutex_unlock(&mailbox_lock); -- return s; --} --EXPORT_SYMBOL_GPL(bcm_mailbox_property); -- --/* ---------------------------------------------------------------------- -- * Platform Device for Mailbox -- * -------------------------------------------------------------------- */ -- --/* -- * Is the device open right now? Used to prevent -- * concurent access into the same device -- */ --static int Device_Open = 0; -- --/* -- * This is called whenever a process attempts to open the device file -- */ --static int device_open(struct inode *inode, struct file *file) --{ -- /* -- * We don't want to talk to two processes at the same time -- */ -- if (Device_Open) -- return -EBUSY; -- -- Device_Open++; -- /* -- * Initialize the message -- */ -- try_module_get(THIS_MODULE); -- return 0; --} -- --static int device_release(struct inode *inode, struct file *file) --{ -- /* -- * We're now ready for our next caller -- */ -- Device_Open--; -- -- module_put(THIS_MODULE); -- return 0; --} -- --/* -- * This function is called whenever a process tries to do an ioctl on our -- * device file. We get two extra parameters (additional to the inode and file -- * structures, which all device functions get): the number of the ioctl called -- * and the parameter given to the ioctl function. -- * -- * If the ioctl is write or read/write (meaning output is returned to the -- * calling process), the ioctl call returns the output of this function. -- * -- */ --static long device_ioctl(struct file *file, /* see include/linux/fs.h */ -- unsigned int ioctl_num, /* number and param for ioctl */ -- unsigned long ioctl_param) --{ -- unsigned size; -- /* -- * Switch according to the ioctl called -- */ -- switch (ioctl_num) { -- case IOCTL_MBOX_PROPERTY: -- /* -- * Receive a pointer to a message (in user space) and set that -- * to be the device's message. Get the parameter given to -- * ioctl by the process. -- */ -- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); -- return bcm_mailbox_property((void *)ioctl_param, size); -- break; -- default: -- printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); -- return -EINVAL; -- } -- -- return 0; --} -- --/* Module Declarations */ -- --/* -- * This structure will hold the functions to be called -- * when a process does something to the device we -- * created. Since a pointer to this structure is kept in -- * the devices table, it can't be local to -- * init_module. NULL is for unimplemented functios. -- */ --struct file_operations fops = { -- .unlocked_ioctl = device_ioctl, -- .open = device_open, -- .release = device_release, /* a.k.a. close */ --}; -- --static int bcm_vcio_probe(struct platform_device *pdev) --{ -- int ret = 0; -- struct vc_mailbox *mailbox; -- -- mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -- if (NULL == mailbox) { -- printk(KERN_ERR DRIVER_NAME ": failed to allocate " -- "mailbox memory\n"); -- ret = -ENOMEM; -- } else { -- struct resource *res; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (res == NULL) { -- printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -- "resource\n"); -- ret = -ENODEV; -- kfree(mailbox); -- } else { -- /* should be based on the registers from res really */ -- mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -- -- platform_set_drvdata(pdev, mailbox); -- dev_mbox_register(DRIVER_NAME, &pdev->dev); -- -- mbox_irqaction.dev_id = mailbox; -- setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -- printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -- __io_address(ARM_0_MAIL0_RD)); -- } -- } -- -- if (ret == 0) { -- /* -- * Register the character device -- */ -- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); -- -- /* -- * Negative values signify an error -- */ -- if (ret < 0) { -- printk(KERN_ERR DRIVER_NAME -- "Failed registering the character device %d\n", ret); -- return ret; -- } -- vcio_class = class_create(THIS_MODULE, BCM_VCIO_DRIVER_NAME); -- if (IS_ERR(vcio_class)) { -- ret = PTR_ERR(vcio_class); -- return ret ; -- } -- device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, -- "vcio"); -- } -- return ret; --} -- --static int bcm_vcio_remove(struct platform_device *pdev) --{ -- struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -- -- platform_set_drvdata(pdev, NULL); -- kfree(mailbox); -- -- return 0; --} -- --static struct platform_driver bcm_mbox_driver = { -- .probe = bcm_vcio_probe, -- .remove = bcm_vcio_remove, -- -- .driver = { -- .name = DRIVER_NAME, -- .owner = THIS_MODULE, -- }, --}; -- --static int __init bcm_mbox_init(void) --{ -- int ret; -- -- printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -- -- ret = platform_driver_register(&bcm_mbox_driver); -- if (ret != 0) { -- printk(KERN_ERR DRIVER_NAME ": failed to register " -- "on platform\n"); -- } -- -- return ret; --} -- --static void __exit bcm_mbox_exit(void) --{ -- device_destroy(vcio_class,MKDEV(MAJOR_NUM, 0)); -- class_destroy(vcio_class); -- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); -- platform_driver_unregister(&bcm_mbox_driver); --} -- --arch_initcall(bcm_mbox_init); /* Initialize early */ --module_exit(bcm_mbox_exit); -- --MODULE_AUTHOR("Gray Girling"); --MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); --MODULE_LICENSE("GPL"); --MODULE_ALIAS("platform:bcm-mbox"); - -From ca452e4734877d6b36d1a836d473b81f3d561c3f Mon Sep 17 00:00:00 2001 + CONFIG_EXT2_FS_POSIX_ACL=y +@@ -107,18 +1073,110 @@ CONFIG_EXT3_FS=y + CONFIG_EXT3_FS_POSIX_ACL=y + CONFIG_EXT4_FS=y + CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_GFS2_FS=m ++CONFIG_OCFS2_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_NILFS2_FS=m + CONFIG_FANOTIFY=y ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_FSCACHE_HISTOGRAM=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m + CONFIG_MSDOS_FS=y + CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y + CONFIG_TMPFS=y + CONFIG_TMPFS_POSIX_ACL=y +-# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_CONFIGFS_FS=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_F2FS_FS=y + CONFIG_NFS_FS=y +-CONFIG_NFSD=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_CIFS=m ++CONFIG_CIFS_WEAK_PW_HASH=y ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_9P_FS=m ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_NLS_DEFAULT="utf8" + CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m + CONFIG_NLS_ASCII=y +-CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m + CONFIG_NLS_UTF8=y ++CONFIG_DLM=m + CONFIG_PRINTK_TIME=y + CONFIG_BOOT_PRINTK_DELAY=y + CONFIG_DYNAMIC_DEBUG=y +@@ -128,14 +1186,38 @@ CONFIG_DEBUG_INFO=y + CONFIG_UNUSED_SYMBOLS=y + CONFIG_DEBUG_MEMORY_INIT=y + CONFIG_LOCKUP_DETECTOR=y ++CONFIG_TIMER_STATS=y ++# CONFIG_DEBUG_PREEMPT is not set ++CONFIG_LATENCYTOP=y ++CONFIG_IRQSOFF_TRACER=y + CONFIG_SCHED_TRACER=y + CONFIG_STACK_TRACER=y ++CONFIG_BLK_DEV_IO_TRACE=y ++# CONFIG_KPROBE_EVENT is not set + CONFIG_FUNCTION_PROFILER=y + CONFIG_TEST_KSTRTOX=y + CONFIG_KGDB=y + CONFIG_KGDB_KDB=y ++CONFIG_KDB_KEYBOARD=y + CONFIG_STRICT_DEVMEM=y + CONFIG_DEBUG_LL=y + CONFIG_EARLY_PRINTK=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_CRYPTD=m ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y + # CONFIG_XZ_DEC_ARM is not set + # CONFIG_XZ_DEC_ARMTHUMB is not set + +From 4e2ed4a7a7971ea763017bc6234d30cdc5bfb984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 23:00:15 +0200 -Subject: [PATCH 147/216] BCM270x_DT: Add mailbox bcm2708-vcio +Subject: [PATCH 69/77] BCM270x_DT: Add mailbox bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -140552,193 +132264,41 @@ platform device when booting in DT mode. Signed-off-by: Noralf Trønnes --- - arch/arm/boot/dts/bcm2708_common.dtsi | 6 ++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 3 files changed, 8 insertions(+), 2 deletions(-) + arch/arm/mach-bcm2708/bcm2708.c | 2 +- + arch/arm/mach-bcm2709/bcm2709.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 065a424..1c8c1af 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -36,6 +36,12 @@ - #interrupt-cells = <2>; - }; - -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2708-vcio"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ }; -+ - gpio: gpio { - compatible = "brcm,bcm2835-gpio"; - reg = <0x7e200000 0xb4>; diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 51f8efa..7cc47c1 100644 +index e42f5a5..de2f93a 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -908,7 +908,7 @@ void __init bcm2708_init(void) +@@ -870,7 +870,7 @@ void __init bcm2708_init(void) bcm2708_dt_init(); bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); - #endif diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8ed88b4..2c0a664 100644 +index 95223ff..350647a 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -929,7 +929,7 @@ void __init bcm2709_init(void) +@@ -890,7 +890,7 @@ void __init bcm2709_init(void) bcm2709_dt_init(); bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_vchiq_device); #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); - #endif -From 8cb40db6e93540a4cf0d45ee23eb9b0441050543 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 23:00:45 +0200 -Subject: [PATCH 148/216] bcm2835: bcm2835_defconfig enable BCM2708_MBOX -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the mailbox driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index cf2e7a6..26b4c75 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -99,6 +99,8 @@ CONFIG_LEDS_TRIGGER_CAMERA=y - CONFIG_DMADEVICES=y - CONFIG_DMA_BCM2708=y - CONFIG_STAGING=y -+CONFIG_MAILBOX=y -+CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT2_FS=y - CONFIG_EXT2_FS_XATTR=y - -From c03f517d41d6da89f70794d6bf20974e81ac72f1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 1 May 2015 23:02:46 +0200 -Subject: [PATCH 149/216] bcm2835: Add mailbox bcm2708-vcio to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add mailbox to Device Tree. There are no kernel users yet, -but it's available to userspace. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f2dec21..06cba29 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -60,6 +60,12 @@ - reg = <0x7e104000 0x10>; - }; - -+ mailbox: mailbox@7e00b800 { -+ compatible = "brcm,bcm2708-vcio"; -+ reg = <0x7e00b880 0x40>; -+ interrupts = <0 1>; -+ }; -+ - gpio: gpio@7e200000 { - compatible = "brcm,bcm2835-gpio"; - reg = <0x7e200000 0xb4>; - -From 2010049aa53c210156598c979fd38dc893baa049 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 12 May 2015 11:48:18 +0200 -Subject: [PATCH 150/216] mailbox: bcm2708-vcio: Allocation does not need to be - atomic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -No need to do atomic allocation in a context that can sleep. - -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/bcm2708-vcio.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -index ee3e778..74a7fcb 100644 ---- a/drivers/mailbox/bcm2708-vcio.c -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -212,7 +212,7 @@ extern int bcm_mailbox_property(void *data, int size) - mutex_lock(&mailbox_lock); - /* allocate some memory for the messages communicating with GPU */ - mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, -- GFP_ATOMIC); -+ GFP_KERNEL); - if (mem_kern) { - /* create the message */ - mbox_copy_from_user(mem_kern, data, size); - -From f86559819816a393e05426b6dac30d84582fa13d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 12 May 2015 13:45:32 +0200 -Subject: [PATCH 151/216] mailbox: bcm2708-vcio: Check the correct status - register before writing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With the VC reader blocked and the ARM writing, MAIL0_STA reads -empty permanently while MAIL1_STA goes from empty (0x40000000) -to non-empty (0x00000001-0x00000007) to full (0x80000008). - -Suggested-by: Phil Elwell -Signed-off-by: Noralf Trønnes ---- - drivers/mailbox/bcm2708-vcio.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c -index 74a7fcb..19ecfe8 100644 ---- a/drivers/mailbox/bcm2708-vcio.c -+++ b/drivers/mailbox/bcm2708-vcio.c -@@ -35,6 +35,7 @@ - #define MAIL0_STA 0x18 /* status */ - #define MAIL0_CNF 0x1C /* configuration */ - #define MAIL1_WRT 0x20 /* write - and next 4 words */ -+#define MAIL1_STA 0x38 /* status */ - - /* On MACH_BCM270x these come through (arm_control.h ) */ - #ifndef ARM_MS_EMPTY -@@ -85,7 +86,7 @@ static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) - return -EINVAL; - - /* wait for the mailbox FIFO to have some space in it */ -- while (0 != (readl(mbox->regs + MAIL0_STA) & ARM_MS_FULL)) -+ while (0 != (readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL)) - cpu_relax(); - - writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); - -From 94bbfc4066df94c006edec5a48fe4df6547a1b01 Mon Sep 17 00:00:00 2001 +From 2867da0a54803e6eb8e748b63a474877e16899b0 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 152/216] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 70/77] rpi-ft5406: Add touchscreen driver for pi LCD display --- drivers/input/touchscreen/Kconfig | 7 + @@ -140749,10 +132309,10 @@ Subject: [PATCH 152/216] rpi-ft5406: Add touchscreen driver for pi LCD display create mode 100644 drivers/input/touchscreen/rpi-ft5406.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 6261fd6..e7e9416 100644 +index 80f6386..5848562 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig -@@ -557,6 +557,13 @@ config TOUCHSCREEN_EDT_FT5X06 +@@ -583,6 +583,13 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. @@ -140767,10 +132327,10 @@ index 6261fd6..e7e9416 100644 tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index 0242fea..e0268f0 100644 +index 44deea7..a1be09f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o +@@ -29,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o @@ -141055,1985 +132615,10 @@ index cc284ed..d3ea839 100644 VCMSG_SET_CURSOR_STATE = 0x00008011, }; -From 7a6f093876247b186c1465ef0f45132b0c804af2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 7 May 2015 09:22:23 +0100 -Subject: [PATCH 153/216] bcm2835-sdhost: Error handling fix, and code - clarification - ---- - drivers/mmc/host/bcm2835-sdhost.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 0c311b5..542ae12 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -1041,13 +1041,14 @@ static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) - host->cmd->error = -EILSEQ; - - /* Use the block interrupt for writes after the first block */ -- if (!(host->data->flags & MMC_DATA_READ)) { -+ if (host->data->flags & MMC_DATA_WRITE) { - host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); - host->hcfg |= SDHCFG_BLOCK_IRPT_EN; - bcm2835_sdhost_write(host, host->hcfg, SDHCFG); - if (host->data->error) - bcm2835_sdhost_finish_data(host); -- bcm2835_sdhost_transfer_pio(host); -+ else -+ bcm2835_sdhost_transfer_pio(host); - } else { - if (!host->data->error) { - bcm2835_sdhost_transfer_pio(host); -@@ -1132,12 +1133,12 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) - bcm2835_sdhost_dumpregs(host); - } - -- if (loops) -- early |= handled; -- - if (!handled) - break; - -+ if (loops) -+ early |= handled; -+ - result = IRQ_HANDLED; - - /* Clear all interrupts and notifications */ - -From d502512774e7121bd6787008f5956daefa3ac138 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 14 May 2015 11:48:40 +0100 -Subject: [PATCH 154/216] bcm2835-sdhost: Adding overclocking option - -Allow a different clock speed to be substitued for a requested 50MHz. -This option is exposed using the "overclock_50" DT parameter. -Note that the sdhost interface is restricted to integer divisions of -core_freq, and the highest sensible option for a core_freq of 250MHz -is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too -high. - -Use at your own risk. ---- - arch/arm/boot/dts/sdhost-overlay.dts | 6 ++++-- - drivers/mmc/host/bcm2835-sdhost.c | 17 +++++++++++++++-- - 2 files changed, 19 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -index 33db96e..b2653e9 100644 ---- a/arch/arm/boot/dts/sdhost-overlay.dts -+++ b/arch/arm/boot/dts/sdhost-overlay.dts -@@ -13,14 +13,15 @@ - sdhost: sdhost@7e202000 { - compatible = "brcm,bcm2835-sdhost"; - reg = <0x7e202000 0x100>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; - interrupts = <2 24>; - clocks = <&clk_sdhost>; - dmas = <&dma 13>, - <&dma 13>; - dma-names = "tx", "rx"; - brcm,delay-after-stop = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&sdhost_pins>; -+ brcm,overclock-50 = <0>; - status = "okay"; - }; - -@@ -67,6 +68,7 @@ - - __overrides__ { - delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; - force_pio = <&sdhost>,"brcm,force-pio?"; - sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; - }; -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 542ae12..2a9eb9f 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -184,6 +184,7 @@ struct bcm2835_host { - int max_delay; /* maximum length of time spent waiting */ - struct timeval stop_time; /* when the last stop was issued */ - u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ -+ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ - }; - - -@@ -1223,6 +1224,10 @@ static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) - void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - { - int div = 0; /* Initialized for compiler warning */ -+ unsigned int input_clock = clock; -+ -+ if (host->overclock_50 && (clock == 50000000)) -+ clock = host->overclock_50 * 1000000; - - /* The SDCDIV register has 11 bits, and holds (div - 2). - But in data mode the max is 50MHz wihout a minimum, and only the -@@ -1266,13 +1271,18 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - if (div > SDCDIV_MAX_CDIV) - div = SDCDIV_MAX_CDIV; - -- host->mmc->actual_clock = host->max_clk / (div + 2); -+ clock = host->max_clk / (div + 2); -+ host->mmc->actual_clock = clock; -+ -+ if (clock > input_clock) -+ pr_warn("%s: Overclocking to %dHz\n", -+ mmc_hostname(host->mmc), clock); - - host->cdiv = div; - bcm2835_sdhost_write(host, host->cdiv, SDCDIV); - - pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", -- clock, host->max_clk, host->cdiv, host->mmc->actual_clock); -+ input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); - } - - static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) -@@ -1572,6 +1582,9 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) - of_property_read_u32(node, - "brcm,delay-after-stop", - &host->delay_after_stop); -+ of_property_read_u32(node, -+ "brcm,overclock-50", -+ &host->overclock_50); - host->allow_dma = ALLOW_DMA && - !of_property_read_bool(node, "brcm,force-pio"); - } - -From ae7169ee054f60e3db61f1a5bb6eb1f52913886a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 14 May 2015 11:55:57 +0100 -Subject: [PATCH 155/216] bcm2835-mmc: Adding overclocking option - -Allow a different clock speed to be substitued for a requested 50MHz. -This option is exposed using the "overclock_50" DT parameter. -Note that the mmc interface is restricted to EVEN integer divisions of -250MHz, and the highest sensible option is 63 (250/4 = 62.5), the -next being 125 (250/2) which is much too high. - -Use at your own risk. ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/mmc-overlay.dts | 19 +++++++++++++++++++ - drivers/mmc/host/bcm2835-mmc.c | 25 ++++++++++++++++++++++--- - 3 files changed, 42 insertions(+), 3 deletions(-) - create mode 100644 arch/arm/boot/dts/mmc-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 9cb5a2d..a21afc5 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -27,6 +27,7 @@ dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb -diff --git a/arch/arm/boot/dts/mmc-overlay.dts b/arch/arm/boot/dts/mmc-overlay.dts -new file mode 100644 -index 0000000..0a37cf4 ---- /dev/null -+++ b/arch/arm/boot/dts/mmc-overlay.dts -@@ -0,0 +1,19 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ -+ __overlay__ { -+ brcm,overclock-50 = <0>; -+ }; -+ }; -+ -+ __overrides__ { -+ overclock_50 = <&mmc>,"brcm,overclock-50:0"; -+ force_pio = <&mmc>,"brcm,force-pio?"; -+ }; -+}; -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index 68314d5..c7c2ca1 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -131,6 +131,8 @@ struct bcm2835_host { - #define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ - #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ - #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ -+ -+ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ - }; - - -@@ -1086,7 +1088,10 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - int real_div = div, clk_mul = 1; - u16 clk = 0; - unsigned long timeout; -+ unsigned int input_clock = clock; - -+ if (host->overclock_50 && (clock == 50000000)) -+ clock = host->overclock_50 * 1000000; - - host->mmc->actual_clock = 0; - -@@ -1110,7 +1115,12 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - div >>= 1; - - if (real_div) -- host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; -+ clock = (host->max_clk * clk_mul) / real_div; -+ host->mmc->actual_clock = clock; -+ -+ if (clock > input_clock) -+ pr_warn("%s: Overclocking to %dHz\n", -+ mmc_hostname(host->mmc), clock); - - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; - clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) -@@ -1177,6 +1187,9 @@ static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) - u8 ctrl; - u16 clk, ctrl_2; - -+ pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", -+ ios->clock, ios->power_mode, ios->bus_width, -+ ios->timing, ios->signal_voltage, ios->drv_type); - - spin_lock_irqsave(&host->lock, flags); - -@@ -1444,10 +1457,16 @@ static int bcm2835_mmc_probe(struct platform_device *pdev) - goto err; - } - -- if (node) -+ if (node) { - mmc_of_parse(mmc); -- else -+ -+ /* Read any custom properties */ -+ of_property_read_u32(node, -+ "brcm,overclock-50", -+ &host->overclock_50); -+ } else { - mmc->caps |= MMC_CAP_4_BIT_DATA; -+ } - - ret = bcm2835_mmc_add_host(host); - if (ret) - -From 4b4b9568bc6fbfc222d59a28b2727ae5c725a92a Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Fri, 15 May 2015 14:21:32 +0200 -Subject: [PATCH 156/216] dmaengine: bcm2708: set residue_granularity field - -bcm2708-dmaengine supports residue reporting at burst level -but didn't report this via the residue_granularity field. - -Without this field set properly we get playback issues with I2S cards. ---- - drivers/dma/bcm2708-dmaengine.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -index 937fd60..987ed53 100644 ---- a/drivers/dma/bcm2708-dmaengine.c -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -1112,6 +1112,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); -@@ -1180,6 +1181,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); - -From 1ddcc631437e913995361718209077d8247c10b0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 12 May 2015 17:26:35 +0100 -Subject: [PATCH 157/216] BCM2708_DT: Adding starter Compute Module DTS files - ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+) - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts - create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index a21afc5..f3558df 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -3,6 +3,7 @@ ifeq ($(CONFIG_OF),y) - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb - dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb -+dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb - - # Raspberry Pi - ifeq ($(CONFIG_BCM2708_DT),y) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -new file mode 100755 -index 0000000..45f8244 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,7 @@ -+/dts-v1/; -+ -+/include/ "bcm2708-rpi-cm.dtsi" -+ -+/ { -+ model = "Raspberry Pi Compute Module"; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -new file mode 100755 -index 0000000..d0a6fb8 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -0,0 +1,30 @@ -+/include/ "bcm2708.dtsi" -+ -+/ { -+ aliases { -+ soc = &soc; -+ gpio = &gpio; -+ intc = &intc; -+ leds = &leds; -+ sound = &sound; -+ }; -+ -+ sound: sound { -+ }; -+}; -+ -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ }; -+}; - -From 210157c8363fc0ac4c99273d3ed8f54ed9929b0f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 11:57:29 +0100 -Subject: [PATCH 158/216] bcm2835-sdhost: Round up the overclock, so 62 works - for 62.5Mhz - -Also only warn once for each overclock setting. ---- - drivers/mmc/host/bcm2835-sdhost.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c -index 2a9eb9f..eef8a24 100644 ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -185,6 +185,7 @@ struct bcm2835_host { - struct timeval stop_time; /* when the last stop was issued */ - u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ - u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ -+ u32 max_overclock; /* Highest reported */ - }; - - -@@ -1227,7 +1228,7 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - unsigned int input_clock = clock; - - if (host->overclock_50 && (clock == 50000000)) -- clock = host->overclock_50 * 1000000; -+ clock = host->overclock_50 * 1000000 + 999999; - - /* The SDCDIV register has 11 bits, and holds (div - 2). - But in data mode the max is 50MHz wihout a minimum, and only the -@@ -1274,9 +1275,11 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) - clock = host->max_clk / (div + 2); - host->mmc->actual_clock = clock; - -- if (clock > input_clock) -+ if ((clock > input_clock) && (clock > host->max_overclock)) { - pr_warn("%s: Overclocking to %dHz\n", - mmc_hostname(host->mmc), clock); -+ host->max_overclock = clock; -+ } - - host->cdiv = div; - bcm2835_sdhost_write(host, host->cdiv, SDCDIV); - -From a946e70fd45a1f24f99816f72f5bbb0a7de0c1f3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 12:29:42 +0100 -Subject: [PATCH 159/216] bcm2835-mmc: Round up the overclock, so 62 works for - 62.5Mhz - -Also only warn once for each overclock setting. ---- - drivers/mmc/host/bcm2835-mmc.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c -index c7c2ca1..b7c4883 100644 ---- a/drivers/mmc/host/bcm2835-mmc.c -+++ b/drivers/mmc/host/bcm2835-mmc.c -@@ -133,6 +133,7 @@ struct bcm2835_host { - #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ - - u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ -+ u32 max_overclock; /* Highest reported */ - }; - - -@@ -1091,7 +1092,7 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - unsigned int input_clock = clock; - - if (host->overclock_50 && (clock == 50000000)) -- clock = host->overclock_50 * 1000000; -+ clock = host->overclock_50 * 1000000 + 999999; - - host->mmc->actual_clock = 0; - -@@ -1118,9 +1119,11 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) - clock = (host->max_clk * clk_mul) / real_div; - host->mmc->actual_clock = clock; - -- if (clock > input_clock) -+ if ((clock > input_clock) && (clock > host->max_overclock)) { - pr_warn("%s: Overclocking to %dHz\n", - mmc_hostname(host->mmc), clock); -+ host->max_overclock = clock; -+ } - - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; - clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) - -From f80dd3188715edaa5c23e3d99793170aa7dbd877 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 18 May 2015 13:05:27 +0100 -Subject: [PATCH 160/216] BCM2708_DT: Add missing CM aliases - ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index d0a6fb8..8340c1e 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -3,6 +3,10 @@ - / { - aliases { - soc = &soc; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; - gpio = &gpio; - intc = &intc; - leds = &leds; - -From 90c3a2ff9838fdf619c6f391c27ce2fe02f083cf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 15 May 2015 20:20:09 +0200 -Subject: [PATCH 161/216] usb: dwc_otg: Don't use dma_to_virt() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit 6ce0d20 changes dma_to_virt() which breaks this driver. -Open code the old dma_to_virt() implementation to work around this. - -Limit the use of __bus_to_virt() to cases where transfer_buffer_length -is set and transfer_buffer is not set. This is done to increase the -chance that this driver will also work on ARCH_BCM2835. - -transfer_buffer should not be NULL if the length is set, but the -comment in the code indicates that there are situations where this -might happen. drivers/usb/isp1760/isp1760-hcd.c also has a similar -comment pointing to a possible: 'usb storage / SCSI bug'. - -Signed-off-by: Noralf Trønnes ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 1d28459..6aad9c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -766,16 +766,17 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, - !(usb_pipein(urb->pipe)))); - - buf = urb->transfer_buffer; -- if (hcd->self.uses_dma) { -+ if (hcd->self.uses_dma && !buf && urb->transfer_buffer_length) { - /* - * Calculate virtual address from physical address, - * because some class driver may not fill transfer_buffer. - * In Buffer DMA mode virual address is used, - * when handling non DWORD aligned buffers. - */ -- //buf = phys_to_virt(urb->transfer_dma); -- // DMA addresses are bus addresses not physical addresses! -- buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); -+ buf = (void *)__bus_to_virt((unsigned long)urb->transfer_dma); -+ dev_warn_once(&urb->dev->dev, -+ "USB transfer_buffer was NULL, will use __bus_to_virt(%pad)=%p\n", -+ &urb->transfer_dma, buf); - } - - if (!(urb->transfer_flags & URB_NO_INTERRUPT)) - -From 785584eaa255550270eb4496bdc31f241561b26c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Fri, 15 May 2015 20:20:26 +0200 -Subject: [PATCH 162/216] fixup: restore dma-mapping.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -dwc_otg has been fixed, so no need to revert 6ce0d20: -ARM: dma: Use dma_pfn_offset for dma address translation - -The pfn_to_dma/dma_to_pfn changes that came with that commit -is needed to use the 'dma-ranges' DT property on ARCH_BCM2835. -dma-ranges is needed by bcm2708_fb and vchiq on ARCH_BCM2835. -If not the mailbox call fails to hand over the correct -bus address to videocore. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/include/asm/dma-mapping.h | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h -index f5572d9..b52101d3 100644 ---- a/arch/arm/include/asm/dma-mapping.h -+++ b/arch/arm/include/asm/dma-mapping.h -@@ -58,21 +58,37 @@ static inline int dma_set_mask(struct device *dev, u64 mask) - #ifndef __arch_pfn_to_dma - static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) - { -+ if (dev) -+ pfn -= dev->dma_pfn_offset; - return (dma_addr_t)__pfn_to_bus(pfn); - } - - static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) - { -- return __bus_to_pfn(addr); -+ unsigned long pfn = __bus_to_pfn(addr); -+ -+ if (dev) -+ pfn += dev->dma_pfn_offset; -+ -+ return pfn; - } - - static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) - { -+ if (dev) { -+ unsigned long pfn = dma_to_pfn(dev, addr); -+ -+ return phys_to_virt(__pfn_to_phys(pfn)); -+ } -+ - return (void *)__bus_to_virt((unsigned long)addr); - } - - static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) - { -+ if (dev) -+ return pfn_to_dma(dev, virt_to_pfn(addr)); -+ - return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); - } - - -From 1b1de68277ff97f836021328e6ac6fbb24494c73 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:18:28 +0200 -Subject: [PATCH 163/216] fbdev: bcm2708_fb: Add ARCH_BCM2835 support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support. -Pass the device to dma_alloc_coherent() in order to get the -correct bus address on ARCH_BCM2835. -Use the new DMA legacy API header file. -Including is not necessary. - -Signed-off-by: Noralf Trønnes ---- - drivers/video/fbdev/bcm2708_fb.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c -index 345c15e..f6ac7da 100644 ---- a/drivers/video/fbdev/bcm2708_fb.c -+++ b/drivers/video/fbdev/bcm2708_fb.c -@@ -24,16 +24,13 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -- --#include --#include -- - #include - #include - #include -@@ -628,7 +625,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) - void *mem; - - mem = -- dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma, -+ dma_alloc_coherent(&fb->dev->dev, PAGE_ALIGN(sizeof(*fb->info)), &dma, - GFP_KERNEL); - - if (NULL == mem) { -@@ -783,12 +780,19 @@ static int bcm2708_fb_remove(struct platform_device *dev) - return 0; - } - -+static const struct of_device_id bcm2708_fb_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-fb", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2708_fb_of_match_table); -+ - static struct platform_driver bcm2708_fb_driver = { - .probe = bcm2708_fb_probe, - .remove = bcm2708_fb_remove, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -+ .of_match_table = bcm2708_fb_of_match_table, - }, - }; - - -From e6d3d3d4102639777a7261d9eb6f195176fc50bb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:20:00 +0200 -Subject: [PATCH 164/216] BCM270x: Remove header file mach/dma.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This header file can be removed since there are no more users. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/include/mach/dma.h | 2 -- - arch/arm/mach-bcm2709/include/mach/dma.h | 2 -- - 2 files changed, 4 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/dma.h - -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -deleted file mode 100644 -index d826705..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ /dev/null -@@ -1,2 +0,0 @@ --/* This file can be removed when all the drivers have been updated */ --#include -diff --git a/arch/arm/mach-bcm2709/include/mach/dma.h b/arch/arm/mach-bcm2709/include/mach/dma.h -deleted file mode 100644 -index d826705..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/dma.h -+++ /dev/null -@@ -1,2 +0,0 @@ --/* This file can be removed when all the drivers have been updated */ --#include - -From 11e908510cac293a92b124f36476ae7fe4c581ec Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:21:31 +0200 -Subject: [PATCH 165/216] BCM270x_DT: Add bcm2708-fb device -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add bcm2708-fb to Device Tree and don't add the -platform device when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ++++ - arch/arm/boot/dts/bcm2708_common.dtsi | 5 +++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 6 files changed, 19 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index f25563a..9a8fed0 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 17b4b8c..cf67ec9 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 1c8c1af..c5ed34b 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -109,6 +109,11 @@ - leds: leds { - compatible = "gpio-leds"; - }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ status = "disabled"; -+ }; - }; - - clocks { -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index c73249b..1c865de 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -49,6 +49,10 @@ - bus-width = <4>; - }; - -+&fb { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7cc47c1..cde2124 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -928,7 +928,7 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&w1_device); - #endif - bcm_register_device(&bcm2708_systemtimer_device); -- bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 2c0a664..95db41ff 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -951,7 +951,7 @@ void __init bcm2709_init(void) - #ifdef SYSTEM_TIMER - bcm_register_device(&bcm2708_systemtimer_device); - #endif -- bcm_register_device(&bcm2708_fb_device); -+ bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -From 0abe9b6fa045617f9fb0f8afe64b69072821d241 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 5 May 2015 13:10:11 -0700 -Subject: [PATCH 166/216] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses to - SDRAM. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There exists a tiny MMU, configurable only by the VC (running the -closed firmware), which maps from the ARM's physical addresses to bus -addresses. These bus addresses determine the caching behavior in the -VC's L1/L2 (note: separate from the ARM's L1/L2) according to the top -2 bits. The bits in the bus address mean: - -From the VideoCore processor: -0x0... L1 and L2 cache allocating and coherent -0x4... L1 non-allocating, but coherent. L2 allocating and coherent -0x8... L1 non-allocating, but coherent. L2 non-allocating, but coherent -0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent - -From the GPU peripherals (note: all peripherals bypass the L1 -cache. The ARM will see this view once through the VC MMU): -0x0... Do not use -0x4... L1 non-allocating, and incoherent. L2 allocating and coherent. -0x8... L1 non-allocating, and incoherent. L2 non-allocating, but coherent -0xc... SDRAM alias. Cache is bypassed. Not L1 or L2 allocating or coherent - -The 2835 firmware always configures the MMU to turn ARM physical -addresses with 0x0 top bits to 0x4, meaning present in L2 but -incoherent with L1. However, any bus addresses we were generating in -the kernel to be passed to a device had 0x0 bits. That would be a -reserved (possibly totally incoherent) value if sent to a GPU -peripheral like USB, or L1 allocating if sent to the VC (like a -firmware property request). By setting dma-ranges, all of the devices -below it get a dev->dma_pfn_offset, so that dma_alloc_coherent() and -friends return addresses with 0x4 bits and avoid cache incoherency. - -This matches the behavior in the downstream 2708 kernel (see -BUS_OFFSET in arch/arm/mach-bcm2708/include/mach/memory.h). - -Signed-off-by: Eric Anholt -Tested-by: Noralf Trønnes -Acked-by: Stephen Warren -Cc: popcornmix@gmail.com ---- - arch/arm/boot/dts/bcm2835.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 06cba29..f91db90 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -14,6 +14,7 @@ - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x7e000000 0x20000000 0x02000000>; -+ dma-ranges = <0x40000000 0x00000000 0x20000000>; - - timer@7e003000 { - compatible = "brcm,bcm2835-system-timer"; - -From fabd2cdba17ab122a41957bced0c06e993b559a8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:24:13 +0200 -Subject: [PATCH 167/216] bcm2835: Add bcm2708-fb to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add framebuffer device to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 ++++ - arch/arm/boot/dts/bcm2835.dtsi | 5 +++++ - 2 files changed, 9 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index 9f4ed2f..f2ce803 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -49,3 +49,7 @@ - status = "okay"; - bus-width = <4>; - }; -+ -+&fb { -+ status = "okay"; -+}; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f91db90..f3ab9b3 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -159,6 +159,11 @@ - arm-pmu { - compatible = "arm,arm1176-pmu"; - }; -+ -+ fb: fb { -+ compatible = "brcm,bcm2708-fb"; -+ status = "disabled"; -+ }; - }; - - clocks { - -From 81530cfc1eb8c2069f7083fa2cc56b3b7470eb29 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 18 May 2015 17:24:35 +0200 -Subject: [PATCH 168/216] bcm2835: bcm2835_defconfig use FB_BCM2708 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Enable the bcm2708 framebuffer driver. -Disable the simple framebuffer driver, which matches the -device handed over by u-boot. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 26b4c75..1af6069 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -72,7 +72,7 @@ CONFIG_SPI_BCM2835=y - CONFIG_GPIO_SYSFS=y - # CONFIG_HWMON is not set - CONFIG_FB=y --CONFIG_FB_SIMPLE=y -+CONFIG_FB_BCM2708=y - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y - CONFIG_USB=y - -From 9e0da80c0836b21773e84b699f2e94e50680b485 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 19 May 2015 11:41:11 +0100 -Subject: [PATCH 169/216] BCM2708_DT: Enable mmc and fb in the CM dtsi - ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 8340c1e..815a3a4 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -25,6 +25,15 @@ - }; - }; - -+&mmc { -+ status = "okay"; -+ bus-width = <4>; -+}; -+ -+&fb { -+ status = "okay"; -+}; -+ - / { - __overrides__ { - act_led_gpio = <&act_led>,"gpios:4"; - -From c95de8db34841f61ef2cb38afb8b84973bd9aa6c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:31:50 +0200 -Subject: [PATCH 170/216] BCM270x: Add vchiq device to platform file and Device - Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Prepare to turn the vchiq module into a driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 6 ++++++ - arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ - arch/arm/mach-bcm2708/include/mach/platform.h | 1 + - arch/arm/mach-bcm2709/bcm2709.c | 26 ++++++++++++++++++++++++++ - arch/arm/mach-bcm2709/include/mach/platform.h | 1 + - 5 files changed, 60 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index c5ed34b..2d9bcd8 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -114,6 +114,12 @@ - compatible = "brcm,bcm2708-fb"; - status = "disabled"; - }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ }; - }; - - clocks { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cde2124..81cc988 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -437,6 +437,31 @@ static struct platform_device bcm2708_vcio_device = { - }, - }; - -+static struct resource bcm2708_vchiq_resources[] = { -+ { -+ .start = ARMCTRL_0_BELL_BASE, -+ .end = ARMCTRL_0_BELL_BASE + 16, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_DOORBELL_0, -+ .end = IRQ_ARM_DOORBELL_0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_vchiq_device = { -+ .name = "bcm2835_vchiq", -+ .id = -1, -+ .resource = bcm2708_vchiq_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), -+ .dev = { -+ .dma_mask = &vchiq_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ - #ifdef CONFIG_BCM2708_GPIO - #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" - -@@ -909,6 +934,7 @@ void __init bcm2708_init(void) - - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device_dt(&bcm2708_vcio_device); -+ bcm_register_device_dt(&bcm2708_vchiq_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index bef3e5a..69674e9 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ - #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 95db41ff..528bf6e 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -456,6 +456,31 @@ static struct platform_device bcm2708_vcio_device = { - }, - }; - -+static struct resource bcm2708_vchiq_resources[] = { -+ { -+ .start = ARMCTRL_0_BELL_BASE, -+ .end = ARMCTRL_0_BELL_BASE + 16, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_ARM_DOORBELL_0, -+ .end = IRQ_ARM_DOORBELL_0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -+ -+static struct platform_device bcm2708_vchiq_device = { -+ .name = "bcm2835_vchiq", -+ .id = -1, -+ .resource = bcm2708_vchiq_resources, -+ .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), -+ .dev = { -+ .dma_mask = &vchiq_dmamask, -+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -+ }, -+}; -+ - #ifdef CONFIG_BCM2708_GPIO - #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" - -@@ -930,6 +955,7 @@ void __init bcm2709_init(void) - - bcm_register_device_dt(&bcm2708_dmaengine_device); - bcm_register_device_dt(&bcm2708_vcio_device); -+ bcm_register_device_dt(&bcm2708_vchiq_device); - #ifdef CONFIG_BCM2708_GPIO - bcm_register_device_dt(&bcm2708_gpio_device); - #endif -diff --git a/arch/arm/mach-bcm2709/include/mach/platform.h b/arch/arm/mach-bcm2709/include/mach/platform.h -index 5574bb5..be99733 100644 ---- a/arch/arm/mach-bcm2709/include/mach/platform.h -+++ b/arch/arm/mach-bcm2709/include/mach/platform.h -@@ -81,6 +81,7 @@ - #define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ - #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ - #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ -+#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ - #define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ - - - -From b723b4395acda96c805d6cd382d5732efa6e449c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:32:34 +0200 -Subject: [PATCH 171/216] bcm2708: vchiq: Add Device Tree support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Turn vchiq into a driver and stop hardcoding resources. -Use devm_* functions in probe path to simplify cleanup. -A global variable is used to hold the register address. This is done -to keep this patch as small as possible. -Also make available on ARCH_BCM2835. -Based on work by Lubomir Rintel. - -Signed-off-by: Noralf Trønnes ---- - drivers/misc/vc04_services/Kconfig | 2 +- - .../interface/vchiq_arm/vchiq_2835_arm.c | 124 +++++++++------------ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 44 ++++---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 7 +- - 4 files changed, 79 insertions(+), 98 deletions(-) - -diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig -index b94e6cd..b4198c2 100644 ---- a/drivers/misc/vc04_services/Kconfig -+++ b/drivers/misc/vc04_services/Kconfig -@@ -1,6 +1,6 @@ - config BCM2708_VCHIQ - tristate "Videocore VCHIQ" -- depends on MACH_BCM2708 || MACH_BCM2709 -+ depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 - default y - help - Kernel to VideoCore communication interface for the -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 70e5086..660aad2 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -35,22 +35,17 @@ - #include - #include - #include --#include - #include - #include - #include - #include - #include -+#include - #include - #include - --#include -- --#include -- - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - --#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0 - #define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) - - #include "vchiq_arm.h" -@@ -60,14 +55,15 @@ - - #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) - -+#define BELL0 0x00 -+#define BELL2 0x08 -+ - typedef struct vchiq_2835_state_struct { - int inited; - VCHIQ_ARM_STATE_T arm_state; - } VCHIQ_2835_ARM_STATE_T; - --static char *g_slot_mem; --static int g_slot_mem_size; --dma_addr_t g_slot_phys; -+static void __iomem *g_regs; - static FRAGMENTS_T *g_fragments_base; - static FRAGMENTS_T *g_free_fragments; - struct semaphore g_free_fragments_sema; -@@ -86,43 +82,40 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, - static void - free_pagelist(PAGELIST_T *pagelist, int actual); - --int __init --vchiq_platform_init(VCHIQ_STATE_T *state) -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) - { -+ struct device *dev = &pdev->dev; - VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; -- int frag_mem_size; -- int err; -- int i; -+ struct resource *res; -+ void *slot_mem; -+ dma_addr_t slot_phys; -+ int slot_mem_size, frag_mem_size; -+ int err, irq, i; - - /* Allocate space for the channels in coherent memory */ -- g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); -+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); - frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); - -- g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size, -- &g_slot_phys, GFP_KERNEL); -- -- if (!g_slot_mem) { -- vchiq_log_error(vchiq_arm_log_level, -- "Unable to allocate channel memory"); -- err = -ENOMEM; -- goto failed_alloc; -+ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, -+ &slot_phys, GFP_KERNEL); -+ if (!slot_mem) { -+ dev_err(dev, "could not allocate DMA memory\n"); -+ return -ENOMEM; - } - -- WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0); -+ WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); - -- vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size); -- if (!vchiq_slot_zero) { -- err = -EINVAL; -- goto failed_init_slots; -- } -+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); -+ if (!vchiq_slot_zero) -+ return -EINVAL; - - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = -- (int)g_slot_phys + g_slot_mem_size; -+ (int)slot_phys + slot_mem_size; - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = - MAX_FRAGMENTS; - -- g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size); -- g_slot_mem_size += frag_mem_size; -+ g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); -+ slot_mem_size += frag_mem_size; - - g_free_fragments = g_fragments_base; - for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { -@@ -132,54 +125,46 @@ vchiq_platform_init(VCHIQ_STATE_T *state) - *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; - sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); - -- if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) != -- VCHIQ_SUCCESS) { -- err = -EINVAL; -- goto failed_vchiq_init; -+ if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) -+ return -EINVAL; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ g_regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(g_regs)) -+ return PTR_ERR(g_regs); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "failed to get IRQ\n"); -+ return irq; - } - -- err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq, -- IRQF_IRQPOLL, "VCHIQ doorbell", -- state); -- if (err < 0) { -- vchiq_log_error(vchiq_arm_log_level, "%s: failed to register " -- "irq=%d err=%d", __func__, -- VCHIQ_DOORBELL_IRQ, err); -- goto failed_request_irq; -+ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, -+ "VCHIQ doorbell", state); -+ if (err) { -+ dev_err(dev, "failed to register irq=%d\n", irq); -+ return err; - } - - /* Send the base address of the slots to VideoCore */ - - dsb(); /* Ensure all writes have completed */ - -- bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys); -+ err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); -+ if (err) { -+ dev_err(dev, "mailbox write failed\n"); -+ return err; -+ } - - vchiq_log_info(vchiq_arm_log_level, -- "vchiq_init - done (slots %x, phys %x)", -- (unsigned int)vchiq_slot_zero, g_slot_phys); -+ "vchiq_init - done (slots %x, phys %pad)", -+ (unsigned int)vchiq_slot_zero, &slot_phys); - -- vchiq_call_connected_callbacks(); -+ vchiq_call_connected_callbacks(); - - return 0; -- --failed_request_irq: --failed_vchiq_init: --failed_init_slots: -- dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys); -- --failed_alloc: -- return err; --} -- --void __exit --vchiq_platform_exit(VCHIQ_STATE_T *state) --{ -- free_irq(VCHIQ_DOORBELL_IRQ, state); -- dma_free_coherent(NULL, g_slot_mem_size, -- g_slot_mem, g_slot_phys); - } - -- - VCHIQ_STATUS_T - vchiq_platform_init_state(VCHIQ_STATE_T *state) - { -@@ -213,11 +198,8 @@ remote_event_signal(REMOTE_EVENT_T *event) - - dsb(); /* data barrier operation */ - -- if (event->armed) { -- /* trigger vc interrupt */ -- -- writel(0, __io_address(ARM_0_BELL2)); -- } -+ if (event->armed) -+ writel(0, g_regs + BELL2); /* trigger vc interrupt */ - } - - int -@@ -341,7 +323,7 @@ vchiq_doorbell_irq(int irq, void *dev_id) - unsigned int status; - - /* Read (and clear) the doorbell */ -- status = readl(__io_address(ARM_0_BELL0)); -+ status = readl(g_regs + BELL0); - - if (status & 0x4) { /* Was the doorbell rung? */ - remote_event_pollall(state); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 0ad9656..31e2cba 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - #include "vchiq_core.h" - #include "vchiq_ioctl.h" -@@ -2790,15 +2791,7 @@ void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, - } - } - -- --/**************************************************************************** --* --* vchiq_init - called when the module is loaded. --* --***************************************************************************/ -- --static int __init --vchiq_init(void) -+static int vchiq_probe(struct platform_device *pdev) - { - int err; - void *ptr_err; -@@ -2835,7 +2828,7 @@ vchiq_init(void) - if (IS_ERR(ptr_err)) - goto failed_device_create; - -- err = vchiq_platform_init(&g_state); -+ err = vchiq_platform_init(pdev, &g_state); - if (err != 0) - goto failed_platform_init; - -@@ -2862,23 +2855,32 @@ vchiq_init(void) - return err; - } - --/**************************************************************************** --* --* vchiq_exit - called when the module is unloaded. --* --***************************************************************************/ -- --static void __exit --vchiq_exit(void) -+static int vchiq_remove(struct platform_device *pdev) - { -- vchiq_platform_exit(&g_state); - device_destroy(vchiq_class, vchiq_devid); - class_destroy(vchiq_class); - cdev_del(&vchiq_cdev); - unregister_chrdev_region(vchiq_devid, 1); -+ -+ return 0; - } - --module_init(vchiq_init); --module_exit(vchiq_exit); -+static const struct of_device_id vchiq_of_match[] = { -+ { .compatible = "brcm,bcm2835-vchiq", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, vchiq_of_match); -+ -+static struct platform_driver vchiq_driver = { -+ .driver = { -+ .name = "bcm2835_vchiq", -+ .owner = THIS_MODULE, -+ .of_match_table = vchiq_of_match, -+ }, -+ .probe = vchiq_probe, -+ .remove = vchiq_remove, -+}; -+module_platform_driver(vchiq_driver); -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Broadcom Corporation"); -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -index d1e2741..9740e1a 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h -@@ -36,6 +36,7 @@ - #define VCHIQ_ARM_H - - #include -+#include - #include - #include - #include "vchiq_core.h" -@@ -128,11 +129,7 @@ typedef struct vchiq_arm_state_struct { - extern int vchiq_arm_log_level; - extern int vchiq_susp_log_level; - --extern int __init --vchiq_platform_init(VCHIQ_STATE_T *state); -- --extern void __exit --vchiq_platform_exit(VCHIQ_STATE_T *state); -+int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); - - extern VCHIQ_STATE_T * - vchiq_get_state(void); - -From a368d9389c5c346a4e5b6ee63a5b28c45184aa20 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 19 May 2015 13:32:50 +0200 -Subject: [PATCH 172/216] bcm2835: Add bcm2835-vchiq to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add vchiq to Device Tree. There are no kernel users yet, -but it's available to userspace (vcgencmd). - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index f3ab9b3..72d0354 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -164,6 +164,12 @@ - compatible = "brcm,bcm2708-fb"; - status = "disabled"; - }; -+ -+ vchiq: vchiq { -+ compatible = "brcm,bcm2835-vchiq"; -+ reg = <0x7e00b840 0xf>; -+ interrupts = <0 2>; -+ }; - }; - - clocks { - -From 0bf6760b3d81238fcfac05e88f66252192c5745d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 20 May 2015 09:29:46 +0100 -Subject: [PATCH 173/216] i2c-bcm2708: When using DT, leave the GPIO setup to - pinctrl - ---- - drivers/i2c/busses/i2c-bcm2708.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c -index 81e9374..8773203 100644 ---- a/drivers/i2c/busses/i2c-bcm2708.c -+++ b/drivers/i2c/busses/i2c-bcm2708.c -@@ -382,7 +382,8 @@ static int bcm2708_i2c_probe(struct platform_device *pdev) - goto out_clk_put; - } - -- bcm2708_i2c_init_pinmode(pdev->id); -+ if (!pdev->dev.of_node) -+ bcm2708_i2c_init_pinmode(pdev->id); - - bi = kzalloc(sizeof(*bi), GFP_KERNEL); - if (!bi) - -From aa0aca81361683205b07ecc895256795ea771528 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 May 2015 11:36:31 +0100 -Subject: [PATCH 174/216] vchiq: Change logging level for inbound data - ---- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -index 835688b..2c98da4 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -1782,7 +1782,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) - service->remoteport); - break; - case VCHIQ_MSG_DATA: -- vchiq_log_trace(vchiq_core_log_level, -+ vchiq_log_info(vchiq_core_log_level, - "%d: prs DATA@%x,%x (%d->%d)", - state->id, (unsigned int)header, size, - remoteport, localport); - -From 32477cf579fd64092395855bfacf907c7da8e3d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 21 May 2015 13:24:35 +0200 -Subject: [PATCH 175/216] BCM270x: Add onboard sound device to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to alsa driver. -Add device to Device Tree. -Don't add platform devices when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 4 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 7 +++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - sound/arm/Kconfig | 3 +- - sound/arm/bcm2835.c | 91 ++++++++++++++++++++++++++++++++ - 9 files changed, 118 insertions(+), 3 deletions(-) - mode change 100755 => 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dtsi - mode change 100755 => 100644 sound/arm/bcm2835.c - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 9a8fed0..6323c5b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index cf67ec9..e1fe6a4 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -old mode 100755 -new mode 100644 -index 815a3a4..1c2cfcf ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -34,6 +34,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - / { - __overrides__ { - act_led_gpio = <&act_led>,"gpios:4"; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 2d9bcd8..4bf6960 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -3,6 +3,13 @@ - / { - interrupt-parent = <&intc>; - -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ - soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 1c865de..921add1 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -53,6 +53,10 @@ - status = "okay"; - }; - -+&audio { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 81cc988..e451187 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -964,7 +964,7 @@ void __init bcm2708_init(void) - #endif - bcm2708_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -- bcm_register_device(&bcm2708_alsa_devices[i]); -+ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 528bf6e..06c2c74 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -987,7 +987,7 @@ void __init bcm2709_init(void) - #endif - bcm2709_init_led(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) -- bcm_register_device(&bcm2708_alsa_devices[i]); -+ bcm_register_device_dt(&bcm2708_alsa_devices[i]); - - bcm_register_device_dt(&bcm2708_spi_device); - -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index ada7ba2..fcbe9d7 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -41,7 +41,8 @@ config SND_PXA2XX_AC97 - - config SND_BCM2835 - tristate "BCM2835 ALSA driver" -- depends on (ARCH_BCM2708 || ARCH_BCM2709) && BCM2708_VCHIQ && SND -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) \ -+ && BCM2708_VCHIQ && SND - select SND_PCM - help - Say Y or M if you want to support BCM2835 Alsa pcm card driver -diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c -old mode 100755 -new mode 100644 -index 7ed5079..6b545e7 ---- a/sound/arm/bcm2835.c -+++ b/sound/arm/bcm2835.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "bcm2835.h" - -@@ -81,6 +82,86 @@ static int snd_bcm2835_create(struct snd_card *card, - return 0; - } - -+static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ bcm2835_chip_t *chip; -+ struct snd_card *card; -+ u32 numchans; -+ int err, i; -+ -+ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", -+ &numchans); -+ if (err) { -+ dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); -+ return err; -+ } -+ -+ if (numchans == 0 || numchans > MAX_SUBSTREAMS) { -+ numchans = MAX_SUBSTREAMS; -+ dev_warn(dev, "Illegal 'brcm,pwm-channels' value, will use %u\n", -+ numchans); -+ } -+ -+ err = snd_card_new(NULL, -1, NULL, THIS_MODULE, 0, &card); -+ if (err) { -+ dev_err(dev, "Failed to create soundcard structure\n"); -+ return err; -+ } -+ -+ snd_card_set_dev(card, dev); -+ strcpy(card->driver, "bcm2835"); -+ strcpy(card->shortname, "bcm2835 ALSA"); -+ sprintf(card->longname, "%s", card->shortname); -+ -+ err = snd_bcm2835_create(card, pdev, &chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create bcm2835 chip\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_spdif_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 spdif pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_ctl(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 ctl\n"); -+ goto err_free; -+ } -+ -+ for (i = 0; i < numchans; i++) { -+ chip->avail_substreams |= (1 << i); -+ chip->pdev[i] = pdev; -+ } -+ -+ err = snd_card_register(card); -+ if (err) { -+ dev_err(dev, "Failed to register bcm2835 ALSA card \n"); -+ goto err_free; -+ } -+ -+ g_card = card; -+ g_chip = chip; -+ platform_set_drvdata(pdev, card); -+ audio_info("bcm2835 ALSA card created with %u channels\n", numchans); -+ -+ return 0; -+ -+err_free: -+ snd_card_free(card); -+ -+ return err; -+} -+ - static int snd_bcm2835_alsa_probe(struct platform_device *pdev) - { - static int dev; -@@ -88,6 +169,9 @@ static int snd_bcm2835_alsa_probe(struct platform_device *pdev) - struct snd_card *card; - int err; - -+ if (pdev->dev.of_node) -+ return snd_bcm2835_alsa_probe_dt(pdev); -+ - if (dev >= MAX_SUBSTREAMS) - return -ENODEV; - -@@ -224,6 +308,12 @@ static int snd_bcm2835_alsa_resume(struct platform_device *pdev) - - #endif - -+static const struct of_device_id snd_bcm2835_of_match_table[] = { -+ { .compatible = "brcm,bcm2835-audio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); -+ - static struct platform_driver bcm2835_alsa0_driver = { - .probe = snd_bcm2835_alsa_probe, - .remove = snd_bcm2835_alsa_remove, -@@ -234,6 +324,7 @@ static struct platform_driver bcm2835_alsa0_driver = { - .driver = { - .name = "bcm2835_AUD0", - .owner = THIS_MODULE, -+ .of_match_table = snd_bcm2835_of_match_table, - }, - }; - - -From a8d9f167700bc9fd113a303b4944272519fc40f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 21 May 2015 13:25:32 +0200 -Subject: [PATCH 176/216] bcm2835: Add bcm2835-audio to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add onboard sound device to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index f2ce803..f23835e 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -14,6 +14,12 @@ - linux,default-trigger = "heartbeat"; - }; - }; -+ -+ /* Onboard audio */ -+ audio: audio { -+ compatible = "brcm,bcm2835-audio"; -+ brcm,pwm-channels = <8>; -+ }; - }; - - &gpio { - -From ead779a26fcab730a6d4be4c7b48c62b22afd8a5 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 18 May 2015 16:59:02 +0100 -Subject: [PATCH 177/216] config: Add CONFIG_CIFS_UPCALL - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index ff87581..6fdd9bb 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1118,6 +1118,7 @@ CONFIG_NFSD_V3_ACL=y - CONFIG_NFSD_V4=y - CONFIG_CIFS=m - CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y - CONFIG_CIFS_XATTR=y - CONFIG_CIFS_POSIX=y - CONFIG_9P_FS=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e339979..93b3de1 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1111,6 +1111,7 @@ CONFIG_NFSD_V3_ACL=y - CONFIG_NFSD_V4=y - CONFIG_CIFS=m - CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y - CONFIG_CIFS_XATTR=y - CONFIG_CIFS_POSIX=y - CONFIG_9P_FS=m - -From 2728618d457e238f4f95d96ad9303a1d816109a9 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 18 May 2015 16:59:13 +0100 -Subject: [PATCH 178/216] config: Add CONFIG_FB_SSD1307=m - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 6fdd9bb..9daaeb7 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -769,6 +769,7 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m - # CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 93b3de1..dc27aeb 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -762,6 +762,7 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m - # CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y - -From 25b5c8e286f3a2b1779c63754b8993107bb416b0 Mon Sep 17 00:00:00 2001 +From f794a0549b3a54cbe6dcfef3b37c421dda92d13a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 179/216] Improve __copy_to_user and __copy_from_user - performance +Subject: [PATCH 71/77] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use optimised memcpy/memmove/memcmp/memset implementations. @@ -143076,7 +132661,7 @@ index cf4f3aa..9fe7780 100644 #define memset(p,v,n) \ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index ce0786e..b85b93d 100644 +index 74b17d0..f4ad0a1 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -475,6 +475,7 @@ do { \ @@ -144557,356 +134142,28 @@ index 3e58d71..0622891 100644 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From ee5567b6efdbf9cbdf4cacaabc7623c5f6d45064 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 19 May 2015 18:49:06 +0100 -Subject: [PATCH 180/216] vcsm: Add ioctl for custom cache flushing - ---- - arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h | 15 +++++++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 49 ++++++++++++++++++++++ - 2 files changed, 64 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -index 42d0eb0..334f36d 100644 ---- a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -+++ b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h -@@ -61,6 +61,8 @@ enum vmcs_sm_cmd_e { - VMCS_SM_CMD_HOST_WALK_PID_ALLOC, - VMCS_SM_CMD_HOST_WALK_PID_MAP, - -+ VMCS_SM_CMD_CLEAN_INVALID, -+ - VMCS_SM_CMD_LAST /* Do no delete */ - }; - -@@ -163,6 +165,16 @@ struct vmcs_sm_ioctl_cache { - unsigned int size; - }; - -+struct vmcs_sm_ioctl_clean_invalid { -+ /* user -> kernel */ -+ struct { -+ unsigned int cmd; -+ unsigned int handle; -+ unsigned int addr; -+ unsigned int size; -+ } s[8]; -+}; -+ - /* IOCTL numbers */ - #define VMCS_SM_IOCTL_MEM_ALLOC\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\ -@@ -191,6 +203,9 @@ struct vmcs_sm_ioctl_cache { - #define VMCS_SM_IOCTL_MEM_INVALID\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\ - struct vmcs_sm_ioctl_cache) -+#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\ -+ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\ -+ struct vmcs_sm_ioctl_clean_invalid) - - #define VMCS_SM_IOCTL_SIZE_USR_HDL\ - _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\ -diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c -index da1c523..39a8971 100644 ---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c -+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -2732,6 +2732,55 @@ static long vc_sm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - } - break; - -+ /* Flush/Invalidate the cache for a given mapping. */ -+ case VMCS_SM_CMD_CLEAN_INVALID: -+ { -+ int i; -+ struct vmcs_sm_ioctl_clean_invalid ioparam; -+ -+ /* Get parameter data. */ -+ if (copy_from_user(&ioparam, -+ (void *)arg, sizeof(ioparam)) != 0) { -+ pr_err("[%s]: failed to copy-from-user for cmd %x\n", -+ __func__, cmdnr); -+ ret = -EFAULT; -+ goto out; -+ } -+ for (i=0; ires_cached) { -+ unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1); -+ unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1); -+ resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++; -+ -+ /* L1/L2 cache flush */ -+ down_read(¤t->mm->mmap_sem); -+ vcsm_vma_cache_clean_page_range(base, end); -+ up_read(¤t->mm->mmap_sem); -+ } else if (resource == NULL) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (resource) -+ vmcs_sm_release_resource(resource, 0); -+ } -+ break; -+ } -+ } -+ } -+ break; -+ - default: - { - ret = -EINVAL; - -From 6f9e2f739661f49e2375be580025549b367444b2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 17 Mar 2015 16:07:48 +0100 -Subject: [PATCH 181/216] dts: overlay: add generic support for ads7846 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add generic support for the ADS7846 touch controller. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/ads7846-overlay.dts | 83 +++++++++++++++++++++++++++++++++++ - 2 files changed, 84 insertions(+) - create mode 100644 arch/arm/boot/dts/ads7846-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index f3558df..0e77296 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -13,6 +13,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - -+dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb -diff --git a/arch/arm/boot/dts/ads7846-overlay.dts b/arch/arm/boot/dts/ads7846-overlay.dts -new file mode 100644 -index 0000000..6a92cd1 ---- /dev/null -+++ b/arch/arm/boot/dts/ads7846-overlay.dts -@@ -0,0 +1,83 @@ -+/* -+ * Generic Device Tree overlay for the ADS7846 touch controller -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ ads7846_pins: ads7846_pins { -+ brcm,pins = <255>; /* illegal default value */ -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ads7846: ads7846@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ads7846_pins>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <255 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 255 0>; -+ -+ /* driver defaults */ -+ ti,x-min = /bits/ 16 <0>; -+ ti,y-min = /bits/ 16 <0>; -+ ti,x-max = /bits/ 16 <0x0FFF>; -+ ti,y-max = /bits/ 16 <0x0FFF>; -+ ti,pressure-min = /bits/ 16 <0>; -+ ti,pressure-max = /bits/ 16 <0xFFFF>; -+ ti,x-plate-ohms = /bits/ 16 <400>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ cs = <&ads7846>,"reg:0"; -+ speed = <&ads7846>,"spi-max-frequency:0"; -+ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -+ <&ads7846>,"interrupts:0", -+ <&ads7846>,"pendown-gpio:4"; -+ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -+ swapxy = <&ads7846>,"ti,swap-xy?"; -+ xmin = <&ads7846>,"ti,x-min;0"; -+ ymin = <&ads7846>,"ti,y-min;0"; -+ xmax = <&ads7846>,"ti,x-max;0"; -+ ymax = <&ads7846>,"ti,y-max;0"; -+ pmin = <&ads7846>,"ti,pressure-min;0"; -+ pmax = <&ads7846>,"ti,pressure-max;0"; -+ xohms = <&ads7846>,"ti,x-plate-ohms;0"; -+ }; -+}; - -From beda21eb0afb05805e46419c37f1127bf35fa775 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 24 May 2015 19:12:01 +0200 -Subject: [PATCH 182/216] bcm270x: add dtparam for audio node - -The audio node is enabled by default and can be disabled -with dtparam=audio=off in config.txt ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 3 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 6323c5b..609d004 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -126,5 +126,7 @@ - pwr_led_gpio = <&pwr_led>,"gpios:4"; - pwr_led_activelow = <&pwr_led>,"gpios:8"; - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e1fe6a4..e601194 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -116,5 +116,7 @@ - act_led_gpio = <&act_led>,"gpios:4"; - act_led_activelow = <&act_led>,"gpios:8"; - act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 921add1..fe282e4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -126,5 +126,7 @@ - pwr_led_gpio = <&pwr_led>,"gpios:4"; - pwr_led_activelow = <&pwr_led>,"gpios:8"; - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; - }; - }; - -From c40ce86818e2ccd1521b5072cfa0bc102893ca7a Mon Sep 17 00:00:00 2001 +From 5787d557e062cdac5f3e19ccd60394dc6df38aab Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 27 May 2015 17:22:15 +0100 -Subject: [PATCH 183/216] bcm2835-audio: Create the platform device if the DT +Subject: [PATCH 72/77] bcm2835-audio: Create the platform device if the DT node is disabled For backwards compatibility, allow the built-in ALSA driver to be enabled either by loading the module from /etc/modules or by enabling the "/audio" node in DT. --- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 4 ---- - arch/arm/boot/dts/bcm2708-rpi-b.dts | 4 ---- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 4 ---- - arch/arm/mach-bcm2708/bcm2708.c | 10 ++++++++-- - arch/arm/mach-bcm2709/bcm2709.c | 10 ++++++++-- - 5 files changed, 16 insertions(+), 16 deletions(-) + arch/arm/mach-bcm2708/bcm2708.c | 10 ++++++++-- + arch/arm/mach-bcm2709/bcm2709.c | 10 ++++++++-- + 2 files changed, 16 insertions(+), 4 deletions(-) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 609d004..75df21c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e601194..df12b7d 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index fe282e4..78bc756 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -53,10 +53,6 @@ - status = "okay"; - }; - --&audio { -- status = "okay"; --}; -- - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e451187..06438df 100644 +index de2f93a..cfc4f13 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -963,8 +963,14 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2835_emmc_device); +@@ -898,8 +898,14 @@ void __init bcm2708_init(void) #endif bcm2708_init_led(); + bcm2708_init_uart1(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device_dt(&bcm2708_alsa_devices[i]); + @@ -144921,13 +134178,13 @@ index e451187..06438df 100644 bcm_register_device_dt(&bcm2708_spi_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 06c2c74..ce06b7d 100644 +index 350647a..507ff52 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -986,8 +986,14 @@ void __init bcm2709_init(void) - bcm_register_device_dt(&bcm2835_emmc_device); +@@ -918,8 +918,14 @@ void __init bcm2709_init(void) #endif bcm2709_init_led(); + bcm2709_init_uart1(); - for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) - bcm_register_device_dt(&bcm2708_alsa_devices[i]); + @@ -144942,8640 +134199,10 @@ index 06c2c74..ce06b7d 100644 bcm_register_device_dt(&bcm2708_spi_device); -From 9f10489e52092f350c72745c2ac3d0afbbf4cd44 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 27 May 2015 14:39:55 +0000 -Subject: [PATCH 184/216] device-tree: spi: make spi-bcm2835 the default spi - driver and prepare for dma - -* make spi-bcm2835 the default driver for spi -* add a fallback spi-bcm2708 overlay -* add dma entries to device tree for future updates -* add default cs-gpios entry showing how to extend the number of chip-selects. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 10 +++++++++- - arch/arm/boot/dts/spi-bcm2708-overlay.dts | 18 ++++++++++++++++++ - 3 files changed, 28 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/spi-bcm2708-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0e77296..9124dfb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -41,6 +41,7 @@ dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 4bf6960..3f8af85 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -84,13 +84,21 @@ - }; - - spi0: spi@7e204000 { -- compatible = "brcm,bcm2708-spi"; -+ compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; - interrupts = <2 22>; - clocks = <&clk_spi>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -+ /* the dma channels */ -+ dmas = <&dma 6>, <&dma 7>; -+ dma-names = "tx", "rx"; -+ /* the chipselects used - <0> means native GPIO -+ * add more gpios if necessary as <&gpio 6 1> -+ * (but do not forget to make them output!) -+ */ -+ cs-gpios = <0>, <0>; - }; - - i2c0: i2c@7e205000 { -diff --git a/arch/arm/boot/dts/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -new file mode 100644 -index 0000000..e378ef1 ---- /dev/null -+++ b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2708-spi"; -+ }; -+ }; -+}; - -From 8c5dd3fb2ef21f3dc20a7c999fd2659354afa975 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 23 May 2015 23:30:36 +0200 -Subject: [PATCH 185/216] BCM270x: Move power module -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the power module available on ARCH_BCM2835 by moving it. -The module turns on USB power making it possible to boot -ARCH_BCM2835 directly with the VC bootloader. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Makefile | 2 +- - arch/arm/mach-bcm2708/include/mach/arm_power.h | 62 -------- - arch/arm/mach-bcm2708/include/mach/power.h | 26 ---- - arch/arm/mach-bcm2708/power.c | 201 ------------------------- - arch/arm/mach-bcm2709/Makefile | 2 +- - arch/arm/mach-bcm2709/include/mach/arm_power.h | 62 -------- - arch/arm/mach-bcm2709/include/mach/power.h | 26 ---- - arch/arm/mach-bcm2709/power.c | 199 ------------------------ - drivers/soc/Kconfig | 1 + - drivers/soc/Makefile | 1 + - drivers/soc/bcm2835/Kconfig | 9 ++ - drivers/soc/bcm2835/Makefile | 1 + - drivers/soc/bcm2835/bcm2708-power.c | 200 ++++++++++++++++++++++++ - include/soc/bcm2835/power.h | 61 ++++++++ - 14 files changed, 275 insertions(+), 578 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h - delete mode 100644 arch/arm/mach-bcm2708/include/mach/power.h - delete mode 100644 arch/arm/mach-bcm2708/power.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/arm_power.h - delete mode 100644 arch/arm/mach-bcm2709/include/mach/power.h - delete mode 100644 arch/arm/mach-bcm2709/power.c - create mode 100644 drivers/soc/bcm2835/Kconfig - create mode 100644 drivers/soc/bcm2835/Makefile - create mode 100644 drivers/soc/bcm2835/bcm2708-power.c - create mode 100644 include/soc/bcm2835/power.h - -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index c1e7d41..5552ae8 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o power.o -+obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h -deleted file mode 100644 -index d3bf245..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/arm_power.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _ARM_POWER_H --#define _ARM_POWER_H -- --/* Use meaningful names on each side */ --#ifdef __VIDEOCORE__ --#define PREFIX(x) ARM_##x --#else --#define PREFIX(x) BCM_##x --#endif -- --enum { -- PREFIX(POWER_SDCARD_BIT), -- PREFIX(POWER_UART_BIT), -- PREFIX(POWER_MINIUART_BIT), -- PREFIX(POWER_USB_BIT), -- PREFIX(POWER_I2C0_BIT), -- PREFIX(POWER_I2C1_BIT), -- PREFIX(POWER_I2C2_BIT), -- PREFIX(POWER_SPI_BIT), -- PREFIX(POWER_CCP2TX_BIT), -- PREFIX(POWER_DSI_BIT), -- -- PREFIX(POWER_MAX) --}; -- --enum { -- PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -- PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -- PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -- PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -- PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -- PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -- PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -- PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -- PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -- PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -- -- PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -- PREFIX(POWER_NONE) = 0 --}; -- --#endif -diff --git a/arch/arm/mach-bcm2708/include/mach/power.h b/arch/arm/mach-bcm2708/include/mach/power.h -deleted file mode 100644 -index 52b3b02..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/power.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#ifndef _MACH_BCM2708_POWER_H --#define _MACH_BCM2708_POWER_H -- --#include --#include -- --typedef unsigned int BCM_POWER_HANDLE_T; -- --extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); --extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); --extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -- --#endif -diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c -deleted file mode 100644 -index 796837f..0000000 ---- a/arch/arm/mach-bcm2708/power.c -+++ /dev/null -@@ -1,201 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#include --#include --#include --#include --#include --#include -- --#define DRIVER_NAME "bcm2708_power" -- --#define BCM_POWER_MAXCLIENTS 4 --#define BCM_POWER_NOCLIENT (1<<31) -- --/* Some drivers expect there devices to be permanently powered */ -- --#ifdef CONFIG_USB --#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) --#endif -- --#if 1 --#define DPRINTK printk --#else --#define DPRINTK if (0) printk --#endif -- --struct state_struct { -- uint32_t global_request; -- uint32_t client_request[BCM_POWER_MAXCLIENTS]; -- struct semaphore client_mutex; -- struct semaphore mutex; --} g_state; -- --int bcm_power_open(BCM_POWER_HANDLE_T *handle) --{ -- BCM_POWER_HANDLE_T i; -- int ret = -EBUSY; -- -- down(&g_state.client_mutex); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -- g_state.client_request[i] = BCM_POWER_NONE; -- *handle = i; -- ret = 0; -- break; -- } -- } -- -- up(&g_state.client_mutex); -- -- DPRINTK("bcm_power_open() -> %d\n", *handle); -- -- return ret; --} --EXPORT_SYMBOL_GPL(bcm_power_open); -- --int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) --{ -- int rc = 0; -- -- DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -- -- if ((handle < BCM_POWER_MAXCLIENTS) && -- (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -- if (down_interruptible(&g_state.mutex) != 0) { -- DPRINTK("bcm_power_request -> interrupted\n"); -- return -EINTR; -- } -- -- if (request != g_state.client_request[handle]) { -- uint32_t others_request = 0; -- uint32_t global_request; -- BCM_POWER_HANDLE_T i; -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (i != handle) -- others_request |= -- g_state.client_request[i]; -- } -- others_request &= ~BCM_POWER_NOCLIENT; -- -- global_request = request | others_request; -- if (global_request != g_state.global_request) { -- uint32_t actual; -- -- /* Send a request to VideoCore */ -- bcm_mailbox_write(MBOX_CHAN_POWER, -- global_request << 4); -- -- /* Wait for a response during power-up */ -- if (global_request & ~g_state.global_request) { -- rc = bcm_mailbox_read(MBOX_CHAN_POWER, -- &actual); -- DPRINTK -- ("bcm_mailbox_read -> %08x, %d\n", -- actual, rc); -- actual >>= 4; -- } else { -- rc = 0; -- actual = global_request; -- } -- -- if (rc == 0) { -- if (actual != global_request) { -- printk(KERN_ERR -- "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -- __func__, -- g_state.global_request, -- global_request, actual, request, others_request); -- /* A failure */ -- BUG_ON((others_request & actual) -- != others_request); -- request &= actual; -- rc = -EIO; -- } -- -- g_state.global_request = actual; -- g_state.client_request[handle] = -- request; -- } -- } -- } -- up(&g_state.mutex); -- } else { -- rc = -EINVAL; -- } -- DPRINTK("bcm_power_request -> %d\n", rc); -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_request); -- --int bcm_power_close(BCM_POWER_HANDLE_T handle) --{ -- int rc; -- -- DPRINTK("bcm_power_close(%d)\n", handle); -- -- rc = bcm_power_request(handle, BCM_POWER_NONE); -- if (rc == 0) -- g_state.client_request[handle] = BCM_POWER_NOCLIENT; -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_close); -- --static int __init bcm_power_init(void) --{ --#if defined(BCM_POWER_ALWAYS_ON) -- BCM_POWER_HANDLE_T always_on_handle; --#endif -- int rc = 0; -- int i; -- -- printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -- g_state.client_request[i] = BCM_POWER_NOCLIENT; -- -- sema_init(&g_state.client_mutex, 1); -- sema_init(&g_state.mutex, 1); -- -- g_state.global_request = 0; -- --#if defined(BCM_POWER_ALWAYS_ON) -- if (BCM_POWER_ALWAYS_ON) { -- bcm_power_open(&always_on_handle); -- bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -- } --#endif -- -- return rc; --} -- --static void __exit bcm_power_exit(void) --{ -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); --} -- --/* -- * Load after the mailbox driver is initialized (arch_initcall), -- * but before depending drivers (module_init). -- */ --subsys_initcall(bcm_power_init); --module_exit(bcm_power_exit); -- --MODULE_AUTHOR("Phil Elwell"); --MODULE_DESCRIPTION("Interface to BCM2708 power management"); --MODULE_LICENSE("GPL"); -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 77b8429..706116f 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -2,6 +2,6 @@ - # Makefile for the linux kernel. - # - --obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o power.o -+obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/arm_power.h b/arch/arm/mach-bcm2709/include/mach/arm_power.h -deleted file mode 100644 -index d3bf245..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/arm_power.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ -- --#ifndef _ARM_POWER_H --#define _ARM_POWER_H -- --/* Use meaningful names on each side */ --#ifdef __VIDEOCORE__ --#define PREFIX(x) ARM_##x --#else --#define PREFIX(x) BCM_##x --#endif -- --enum { -- PREFIX(POWER_SDCARD_BIT), -- PREFIX(POWER_UART_BIT), -- PREFIX(POWER_MINIUART_BIT), -- PREFIX(POWER_USB_BIT), -- PREFIX(POWER_I2C0_BIT), -- PREFIX(POWER_I2C1_BIT), -- PREFIX(POWER_I2C2_BIT), -- PREFIX(POWER_SPI_BIT), -- PREFIX(POWER_CCP2TX_BIT), -- PREFIX(POWER_DSI_BIT), -- -- PREFIX(POWER_MAX) --}; -- --enum { -- PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -- PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -- PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -- PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -- PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -- PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -- PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -- PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -- PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -- PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -- -- PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -- PREFIX(POWER_NONE) = 0 --}; -- --#endif -diff --git a/arch/arm/mach-bcm2709/include/mach/power.h b/arch/arm/mach-bcm2709/include/mach/power.h -deleted file mode 100644 -index 52b3b02..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/power.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#ifndef _MACH_BCM2708_POWER_H --#define _MACH_BCM2708_POWER_H -- --#include --#include -- --typedef unsigned int BCM_POWER_HANDLE_T; -- --extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); --extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); --extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -- --#endif -diff --git a/arch/arm/mach-bcm2709/power.c b/arch/arm/mach-bcm2709/power.c -deleted file mode 100644 -index 960e472..0000000 ---- a/arch/arm/mach-bcm2709/power.c -+++ /dev/null -@@ -1,199 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/power.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This device provides a shared mechanism for controlling the power to -- * VideoCore subsystems. -- */ -- --#include --#include --#include --#include --#include --#include -- --#define DRIVER_NAME "bcm2708_power" -- --#define BCM_POWER_MAXCLIENTS 4 --#define BCM_POWER_NOCLIENT (1<<31) -- --/* Some drivers expect there devices to be permanently powered */ --#ifdef CONFIG_USB --#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) --#endif -- --#if 1 --#define DPRINTK printk --#else --#define DPRINTK if (0) printk --#endif -- --struct state_struct { -- uint32_t global_request; -- uint32_t client_request[BCM_POWER_MAXCLIENTS]; -- struct semaphore client_mutex; -- struct semaphore mutex; --} g_state; -- --int bcm_power_open(BCM_POWER_HANDLE_T *handle) --{ -- BCM_POWER_HANDLE_T i; -- int ret = -EBUSY; -- -- down(&g_state.client_mutex); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -- g_state.client_request[i] = BCM_POWER_NONE; -- *handle = i; -- ret = 0; -- break; -- } -- } -- -- up(&g_state.client_mutex); -- -- DPRINTK("bcm_power_open() -> %d\n", *handle); -- -- return ret; --} --EXPORT_SYMBOL_GPL(bcm_power_open); -- --int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) --{ -- int rc = 0; -- -- DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -- -- if ((handle < BCM_POWER_MAXCLIENTS) && -- (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -- if (down_interruptible(&g_state.mutex) != 0) { -- DPRINTK("bcm_power_request -> interrupted\n"); -- return -EINTR; -- } -- -- if (request != g_state.client_request[handle]) { -- uint32_t others_request = 0; -- uint32_t global_request; -- BCM_POWER_HANDLE_T i; -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -- if (i != handle) -- others_request |= -- g_state.client_request[i]; -- } -- others_request &= ~BCM_POWER_NOCLIENT; -- -- global_request = request | others_request; -- if (global_request != g_state.global_request) { -- uint32_t actual; -- -- /* Send a request to VideoCore */ -- bcm_mailbox_write(MBOX_CHAN_POWER, -- global_request << 4); -- -- /* Wait for a response during power-up */ -- if (global_request & ~g_state.global_request) { -- rc = bcm_mailbox_read(MBOX_CHAN_POWER, -- &actual); -- DPRINTK -- ("bcm_mailbox_read -> %08x, %d\n", -- actual, rc); -- actual >>= 4; -- } else { -- rc = 0; -- actual = global_request; -- } -- -- if (rc == 0) { -- if (actual != global_request) { -- printk(KERN_ERR -- "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -- __func__, -- g_state.global_request, -- global_request, actual, request, others_request); -- /* A failure */ -- BUG_ON((others_request & actual) -- != others_request); -- request &= actual; -- rc = -EIO; -- } -- -- g_state.global_request = actual; -- g_state.client_request[handle] = -- request; -- } -- } -- } -- up(&g_state.mutex); -- } else { -- rc = -EINVAL; -- } -- DPRINTK("bcm_power_request -> %d\n", rc); -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_request); -- --int bcm_power_close(BCM_POWER_HANDLE_T handle) --{ -- int rc; -- -- DPRINTK("bcm_power_close(%d)\n", handle); -- -- rc = bcm_power_request(handle, BCM_POWER_NONE); -- if (rc == 0) -- g_state.client_request[handle] = BCM_POWER_NOCLIENT; -- -- return rc; --} --EXPORT_SYMBOL_GPL(bcm_power_close); -- --static int __init bcm_power_init(void) --{ --#if defined(BCM_POWER_ALWAYS_ON) -- BCM_POWER_HANDLE_T always_on_handle; --#endif -- int rc = 0; -- int i; -- -- printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); -- -- for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -- g_state.client_request[i] = BCM_POWER_NOCLIENT; -- -- sema_init(&g_state.client_mutex, 1); -- sema_init(&g_state.mutex, 1); -- -- g_state.global_request = 0; --#if defined(BCM_POWER_ALWAYS_ON) -- if (BCM_POWER_ALWAYS_ON) { -- bcm_power_open(&always_on_handle); -- bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -- } --#endif -- -- return rc; --} -- --static void __exit bcm_power_exit(void) --{ -- bcm_mailbox_write(MBOX_CHAN_POWER, 0); --} -- --/* -- * Load after the mailbox driver is initialized (arch_initcall), -- * but before depending drivers (module_init). -- */ --subsys_initcall(bcm_power_init); --module_exit(bcm_power_exit); -- --MODULE_AUTHOR("Phil Elwell"); --MODULE_DESCRIPTION("Interface to BCM2708 power management"); --MODULE_LICENSE("GPL"); -diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig -index 76d6bd4..aed58f4 100644 ---- a/drivers/soc/Kconfig -+++ b/drivers/soc/Kconfig -@@ -1,5 +1,6 @@ - menu "SOC (System On Chip) specific Drivers" - -+source "drivers/soc/bcm2835/Kconfig" - source "drivers/soc/qcom/Kconfig" - source "drivers/soc/ti/Kconfig" - source "drivers/soc/versatile/Kconfig" -diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile -index 063113d..897de0c5 100644 ---- a/drivers/soc/Makefile -+++ b/drivers/soc/Makefile -@@ -2,6 +2,7 @@ - # Makefile for the Linux Kernel SOC specific device drivers. - # - -+obj-y += bcm2835/ - obj-$(CONFIG_ARCH_QCOM) += qcom/ - obj-$(CONFIG_ARCH_TEGRA) += tegra/ - obj-$(CONFIG_SOC_TI) += ti/ -diff --git a/drivers/soc/bcm2835/Kconfig b/drivers/soc/bcm2835/Kconfig -new file mode 100644 -index 0000000..c2980f3 ---- /dev/null -+++ b/drivers/soc/bcm2835/Kconfig -@@ -0,0 +1,9 @@ -+# -+# BCM2835 Soc drivers -+# -+config BCM2708_POWER -+ tristate "BCM2708 legacy power driver" -+ depends on (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) && BCM2708_MBOX -+ default y -+ help -+ Turns on USB power and provides an API for controlling power. -diff --git a/drivers/soc/bcm2835/Makefile b/drivers/soc/bcm2835/Makefile -new file mode 100644 -index 0000000..3614ad9 ---- /dev/null -+++ b/drivers/soc/bcm2835/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_BCM2708_POWER) += bcm2708-power.o -diff --git a/drivers/soc/bcm2835/bcm2708-power.c b/drivers/soc/bcm2835/bcm2708-power.c -new file mode 100644 -index 0000000..e7931a9 ---- /dev/null -+++ b/drivers/soc/bcm2835/bcm2708-power.c -@@ -0,0 +1,200 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/power.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "bcm2708_power" -+ -+#define BCM_POWER_MAXCLIENTS 4 -+#define BCM_POWER_NOCLIENT (1<<31) -+ -+/* Some drivers expect there devices to be permanently powered */ -+ -+#ifdef CONFIG_USB -+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) -+#endif -+ -+#if 1 -+#define DPRINTK printk -+#else -+#define DPRINTK if (0) printk -+#endif -+ -+struct state_struct { -+ uint32_t global_request; -+ uint32_t client_request[BCM_POWER_MAXCLIENTS]; -+ struct semaphore client_mutex; -+ struct semaphore mutex; -+} g_state; -+ -+int bcm_power_open(BCM_POWER_HANDLE_T *handle) -+{ -+ BCM_POWER_HANDLE_T i; -+ int ret = -EBUSY; -+ -+ down(&g_state.client_mutex); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { -+ g_state.client_request[i] = BCM_POWER_NONE; -+ *handle = i; -+ ret = 0; -+ break; -+ } -+ } -+ -+ up(&g_state.client_mutex); -+ -+ DPRINTK("bcm_power_open() -> %d\n", *handle); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(bcm_power_open); -+ -+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) -+{ -+ int rc = 0; -+ -+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); -+ -+ if ((handle < BCM_POWER_MAXCLIENTS) && -+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { -+ if (down_interruptible(&g_state.mutex) != 0) { -+ DPRINTK("bcm_power_request -> interrupted\n"); -+ return -EINTR; -+ } -+ -+ if (request != g_state.client_request[handle]) { -+ uint32_t others_request = 0; -+ uint32_t global_request; -+ BCM_POWER_HANDLE_T i; -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { -+ if (i != handle) -+ others_request |= -+ g_state.client_request[i]; -+ } -+ others_request &= ~BCM_POWER_NOCLIENT; -+ -+ global_request = request | others_request; -+ if (global_request != g_state.global_request) { -+ uint32_t actual; -+ -+ /* Send a request to VideoCore */ -+ bcm_mailbox_write(MBOX_CHAN_POWER, -+ global_request << 4); -+ -+ /* Wait for a response during power-up */ -+ if (global_request & ~g_state.global_request) { -+ rc = bcm_mailbox_read(MBOX_CHAN_POWER, -+ &actual); -+ DPRINTK -+ ("bcm_mailbox_read -> %08x, %d\n", -+ actual, rc); -+ actual >>= 4; -+ } else { -+ rc = 0; -+ actual = global_request; -+ } -+ -+ if (rc == 0) { -+ if (actual != global_request) { -+ printk(KERN_ERR -+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", -+ __func__, -+ g_state.global_request, -+ global_request, actual, request, others_request); -+ /* A failure */ -+ BUG_ON((others_request & actual) -+ != others_request); -+ request &= actual; -+ rc = -EIO; -+ } -+ -+ g_state.global_request = actual; -+ g_state.client_request[handle] = -+ request; -+ } -+ } -+ } -+ up(&g_state.mutex); -+ } else { -+ rc = -EINVAL; -+ } -+ DPRINTK("bcm_power_request -> %d\n", rc); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_request); -+ -+int bcm_power_close(BCM_POWER_HANDLE_T handle) -+{ -+ int rc; -+ -+ DPRINTK("bcm_power_close(%d)\n", handle); -+ -+ rc = bcm_power_request(handle, BCM_POWER_NONE); -+ if (rc == 0) -+ g_state.client_request[handle] = BCM_POWER_NOCLIENT; -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(bcm_power_close); -+ -+static int __init bcm_power_init(void) -+{ -+#if defined(BCM_POWER_ALWAYS_ON) -+ BCM_POWER_HANDLE_T always_on_handle; -+#endif -+ int rc = 0; -+ int i; -+ -+ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+ -+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) -+ g_state.client_request[i] = BCM_POWER_NOCLIENT; -+ -+ sema_init(&g_state.client_mutex, 1); -+ sema_init(&g_state.mutex, 1); -+ -+ g_state.global_request = 0; -+ -+#if defined(BCM_POWER_ALWAYS_ON) -+ if (BCM_POWER_ALWAYS_ON) { -+ bcm_power_open(&always_on_handle); -+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); -+ } -+#endif -+ -+ return rc; -+} -+ -+static void __exit bcm_power_exit(void) -+{ -+ bcm_mailbox_write(MBOX_CHAN_POWER, 0); -+} -+ -+/* -+ * Load after the mailbox driver is initialized (arch_initcall), -+ * but before depending drivers (module_init). -+ */ -+subsys_initcall(bcm_power_init); -+module_exit(bcm_power_exit); -+ -+MODULE_AUTHOR("Phil Elwell"); -+MODULE_DESCRIPTION("Interface to BCM2708 power management"); -+MODULE_LICENSE("GPL"); -diff --git a/include/soc/bcm2835/power.h b/include/soc/bcm2835/power.h -new file mode 100644 -index 0000000..bf22b26 ---- /dev/null -+++ b/include/soc/bcm2835/power.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for controlling the power to -+ * VideoCore subsystems. -+ */ -+ -+#ifndef _BCM2708_POWER_H -+#define _BCM2708_POWER_H -+ -+#include -+ -+/* Use meaningful names on each side */ -+#ifdef __VIDEOCORE__ -+#define PREFIX(x) ARM_##x -+#else -+#define PREFIX(x) BCM_##x -+#endif -+ -+enum { -+ PREFIX(POWER_SDCARD_BIT), -+ PREFIX(POWER_UART_BIT), -+ PREFIX(POWER_MINIUART_BIT), -+ PREFIX(POWER_USB_BIT), -+ PREFIX(POWER_I2C0_BIT), -+ PREFIX(POWER_I2C1_BIT), -+ PREFIX(POWER_I2C2_BIT), -+ PREFIX(POWER_SPI_BIT), -+ PREFIX(POWER_CCP2TX_BIT), -+ PREFIX(POWER_DSI_BIT), -+ -+ PREFIX(POWER_MAX) -+}; -+ -+enum { -+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), -+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), -+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), -+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), -+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), -+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), -+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), -+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), -+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), -+ PREFIX(POWER_DSI) = (1 << PREFIX(POWER_DSI_BIT)), -+ -+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, -+ PREFIX(POWER_NONE) = 0 -+}; -+ -+typedef unsigned int BCM_POWER_HANDLE_T; -+ -+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); -+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); -+extern int bcm_power_close(BCM_POWER_HANDLE_T handle); -+ -+#endif - -From 7ea54e2541e0445c98c3b5bb4b0e80af76c5c197 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 23 May 2015 23:31:40 +0200 -Subject: [PATCH 186/216] bcm2835: Use empty bootargs in Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The VideoCore bootloader concatenates the bootargs property together -with /boot/cmdline.txt and includes it's own set of options. -Set bootargs to an empty string to behave like BCM270x. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 72d0354..40fc759 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -6,7 +6,7 @@ - interrupt-parent = <&intc>; - - chosen { -- bootargs = "earlyprintk console=ttyAMA0"; -+ bootargs = ""; - }; - - soc { - -From b340f9126d88eafd83e2ae6e0b593bea562f92f5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 187/216] scripts: Add mkknlimg and knlinfo scripts from tools - repo - -The Raspberry Pi firmware looks for a trailer on the kernel image to -determine whether it was compiled with Device Tree support enabled. -If the firmware finds a kernel without this trailer, or which has a -trailer indicating that it isn't DT-capable, it disables DT support -and reverts to using ATAGs. - -The mkknlimg utility adds that trailer, having first analysed the -image to look for signs of DT support and the kernel version string. - -knlinfo displays the contents of the trailer in the given kernel image. ---- - scripts/knlinfo | 167 +++++++++++++++++++++++++++++++++++ - scripts/mkknlimg | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 427 insertions(+) - create mode 100755 scripts/knlinfo - create mode 100755 scripts/mkknlimg - -diff --git a/scripts/knlinfo b/scripts/knlinfo -new file mode 100755 -index 0000000..9c9b42e3 ---- /dev/null -+++ b/scripts/knlinfo -@@ -0,0 +1,167 @@ -+#!/usr/bin/env perl -+# ---------------------------------------------------------------------- -+# knlinfo by Phil Elwell for Raspberry Pi -+# -+# (c) 2014,2015 Raspberry Pi (Trading) Limited -+# -+# Licensed under the terms of the GNU General Public License. -+# ---------------------------------------------------------------------- -+ -+use strict; -+use integer; -+ -+use Fcntl ":seek"; -+ -+my $trailer_magic = 'RPTL'; -+ -+my %atom_formats = -+( -+ 'DTOK' => \&format_bool, -+ 'KVer' => \&format_string, -+); -+ -+if (@ARGV != 1) -+{ -+ print ("Usage: knlinfo \n"); -+ exit(1); -+} -+ -+my $kernel_file = $ARGV[0]; -+ -+ -+my ($atoms, $pos) = read_trailer($kernel_file); -+ -+exit(1) if (!$atoms); -+ -+printf("Kernel trailer found at %d/0x%x:\n", $pos, $pos); -+ -+foreach my $atom (@$atoms) -+{ -+ printf(" %s: %s\n", $atom->[0], format_atom($atom)); -+} -+ -+exit(0); -+ -+sub read_trailer -+{ -+ my ($kernel_file) = @_; -+ my $fh; -+ -+ if (!open($fh, '<', $kernel_file)) -+ { -+ print ("* Failed to open '$kernel_file'\n"); -+ return undef; -+ } -+ -+ if (!seek($fh, -12, SEEK_END)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ my $last_bytes; -+ sysread($fh, $last_bytes, 12); -+ -+ my ($trailer_len, $data_len, $magic) = unpack('VVa4', $last_bytes); -+ -+ if (($magic ne $trailer_magic) || ($data_len != 4)) -+ { -+ print ("* no trailer\n"); -+ return undef; -+ } -+ if (!seek($fh, -12, SEEK_END)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ $trailer_len -= 12; -+ -+ while ($trailer_len > 0) -+ { -+ if ($trailer_len < 8) -+ { -+ print ("* truncated atom header in trailer\n"); -+ return undef; -+ } -+ if (!seek($fh, -8, SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ $trailer_len -= 8; -+ -+ my $atom_hdr; -+ sysread($fh, $atom_hdr, 8); -+ my ($atom_len, $atom_type) = unpack('Va4', $atom_hdr); -+ -+ if ($trailer_len < $atom_len) -+ { -+ print ("* truncated atom data in trailer\n"); -+ return undef; -+ } -+ -+ my $rounded_len = (($atom_len + 3) & ~3); -+ if (!seek($fh, -(8 + $rounded_len), SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ $trailer_len -= $rounded_len; -+ -+ my $atom_data; -+ sysread($fh, $atom_data, $atom_len); -+ -+ if (!seek($fh, -$atom_len, SEEK_CUR)) -+ { -+ print ("* seek error in '$kernel_file'\n"); -+ return undef; -+ } -+ -+ push @$atoms, [ $atom_type, $atom_data ]; -+ } -+ -+ if (($$atoms[-1][0] eq "\x00\x00\x00\x00") && -+ ($$atoms[-1][1] eq "")) -+ { -+ pop @$atoms; -+ } -+ else -+ { -+ print ("* end marker missing from trailer\n"); -+ } -+ -+ return ($atoms, tell($fh)); -+} -+ -+sub format_atom -+{ -+ my ($atom) = @_; -+ -+ my $format_func = $atom_formats{$atom->[0]} || \&format_hex; -+ return $format_func->($atom->[1]); -+} -+ -+sub format_bool -+{ -+ my ($data) = @_; -+ return unpack('V', $data) ? 'true' : 'false'; -+} -+ -+sub format_int -+{ -+ my ($data) = @_; -+ return unpack('V', $data); -+} -+ -+sub format_string -+{ -+ my ($data) = @_; -+ return '"'.$data.'"'; -+} -+ -+sub format_hex -+{ -+ my ($data) = @_; -+ return unpack('H*', $data); -+} -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -new file mode 100755 -index 0000000..ac829d0 ---- /dev/null -+++ b/scripts/mkknlimg -@@ -0,0 +1,260 @@ -+#!/usr/bin/env perl -+# ---------------------------------------------------------------------- -+# mkknlimg by Phil Elwell for Raspberry Pi -+# based on extract-ikconfig Dick Streefland -+# -+# (c) 2009,2010 Dick Streefland -+# (c) 2014,2015 Raspberry Pi (Trading) Limited -+# -+# Licensed under the terms of the GNU General Public License. -+# ---------------------------------------------------------------------- -+ -+use strict; -+use warnings; -+use integer; -+ -+my $trailer_magic = 'RPTL'; -+ -+my $tmpfile1 = "/tmp/mkknlimg_$$.1"; -+my $tmpfile2 = "/tmp/mkknlimg_$$.2"; -+ -+my $dtok = 0; -+ -+while (@ARGV && ($ARGV[0] =~ /^-/)) -+{ -+ my $arg = shift(@ARGV); -+ if ($arg eq '--dtok') -+ { -+ $dtok = 1; -+ } -+ else -+ { -+ print ("* Unknown option '$arg'\n"); -+ usage(); -+ } -+} -+ -+usage() if (@ARGV != 2); -+ -+my $kernel_file = $ARGV[0]; -+my $out_file = $ARGV[1]; -+ -+if (! -r $kernel_file) -+{ -+ print ("* File '$kernel_file' not found\n"); -+ usage(); -+} -+ -+my @wanted_config_lines = -+( -+ 'CONFIG_BCM2708_DT' -+); -+ -+my @wanted_strings = -+( -+ 'bcm2708_fb', -+ 'brcm,bcm2708-pinctrl', -+ 'brcm,bcm2835-gpio', -+ 'of_find_property' -+); -+ -+my $res = try_extract($kernel_file, $tmpfile1); -+$res = try_decompress('\037\213\010', 'xy', 'gunzip', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('BZh', 'xy', 'bunzip2', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\211\114\132', 'xy', 'lzop -d', 0, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+$res = try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1, -+ $kernel_file, $tmpfile1, $tmpfile2) if (!$res); -+ -+my $append_trailer; -+my $trailer; -+my $kver = '?'; -+ -+$append_trailer = $dtok; -+ -+if ($res) -+{ -+ $kver = $res->{''} || '?'; -+ print("Version: $kver\n"); -+ -+ $append_trailer = $dtok; -+ if (!$dtok) -+ { -+ if (config_bool($res, 'bcm2708_fb')) -+ { -+ $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); -+ $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); -+ $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); -+ $append_trailer = 1; -+ } -+ else -+ { -+ print ("* This doesn't look like a Raspberry Pi kernel. In pass-through mode.\n"); -+ } -+ } -+} -+elsif (!$dtok) -+{ -+ print ("* Is this a valid kernel? In pass-through mode.\n"); -+} -+ -+if ($append_trailer) -+{ -+ printf("DT: %s\n", $dtok ? "y" : "n"); -+ -+ my @atoms; -+ -+ push @atoms, [ $trailer_magic, pack('V', 0) ]; -+ push @atoms, [ 'KVer', $kver ]; -+ push @atoms, [ 'DTOK', pack('V', $dtok) ]; -+ -+ $trailer = pack_trailer(\@atoms); -+ $atoms[0]->[1] = pack('V', length($trailer)); -+ -+ $trailer = pack_trailer(\@atoms); -+} -+ -+my $ofh; -+my $total_len = 0; -+ -+if ($out_file eq $kernel_file) -+{ -+ die "* Failed to open '$out_file' for append\n" -+ if (!open($ofh, '>>', $out_file)); -+ $total_len = tell($ofh); -+} -+else -+{ -+ die "* Failed to open '$kernel_file'\n" -+ if (!open(my $ifh, '<', $kernel_file)); -+ die "* Failed to create '$out_file'\n" -+ if (!open($ofh, '>', $out_file)); -+ -+ my $copybuf; -+ while (1) -+ { -+ my $bytes = sysread($ifh, $copybuf, 64*1024); -+ last if (!$bytes); -+ syswrite($ofh, $copybuf, $bytes); -+ $total_len += $bytes; -+ } -+ close($ifh); -+} -+ -+if ($trailer) -+{ -+ # Pad to word-alignment -+ syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3)); -+ syswrite($ofh, $trailer); -+} -+ -+close($ofh); -+ -+exit($trailer ? 0 : 1); -+ -+END { -+ unlink($tmpfile1) if ($tmpfile1); -+ unlink($tmpfile2) if ($tmpfile2); -+} -+ -+ -+sub usage -+{ -+ print ("Usage: mkknlimg [--dtok] \n"); -+ exit(1); -+} -+ -+sub try_extract -+{ -+ my ($knl, $tmp) = @_; -+ -+ my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`; -+ -+ return undef if (!$ver); -+ -+ chomp($ver); -+ -+ my $res = { ''=>$ver }; -+ my $string_pattern = '^('.join('|', @wanted_strings).')$'; -+ -+ my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`; -+ foreach my $match (@matches) -+ { -+ chomp($match); -+ $res->{$match} = 1; -+ } -+ -+ my $config_pattern = '^('.join('|', @wanted_config_lines).')=(.*)$'; -+ my $cf1 = 'IKCFG_ST\037\213\010'; -+ my $cf2 = '0123456789'; -+ -+ my $pos = `tr "$cf1\n$cf2" "\n$cf2=" < "$knl" | grep -abo "^$cf2"`; -+ if ($pos) -+ { -+ $pos =~ s/:.*[\r\n]*$//s; -+ $pos += 8; -+ my $err = (system("tail -c+$pos \"$knl\" | zcat > $tmp 2> /dev/null") >> 8); -+ if (($err == 0) || ($err == 2)) -+ { -+ if (open(my $fh, '<', $tmp)) -+ { -+ while (my $line = <$fh>) -+ { -+ chomp($line); -+ $res->{$1} = $2 if ($line =~ /$config_pattern/); -+ } -+ -+ close($fh); -+ } -+ } -+ } -+ -+ return $res; -+} -+ -+ -+sub try_decompress -+{ -+ my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_; -+ -+ my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`; -+ if ($pos) -+ { -+ chomp($pos); -+ $pos = (split(/[\r\n]+/, $pos))[$idx]; -+ return undef if (!defined($pos)); -+ $pos =~ s/:.*[\r\n]*$//s; -+ my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null"; -+ my $err = (system($cmd) >> 8); -+ return undef if (($err != 0) && ($err != 2)); -+ -+ return try_extract($tmp2, $tmp1); -+ } -+ -+ return undef; -+} -+ -+sub pack_trailer -+{ -+ my ($atoms) = @_; -+ my $trailer = pack('VV', 0, 0); -+ for (my $i = $#$atoms; $i>=0; $i--) -+ { -+ my $atom = $atoms->[$i]; -+ $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]); -+ } -+ return $trailer; -+} -+ -+sub config_bool -+{ -+ my ($configs, $wanted) = @_; -+ my $val = $configs->{$wanted} || 'n'; -+ return (($val eq 'y') || ($val eq '1')); -+} - -From 2ab7f22fc98a7e6f66c3924d0eff9a721b159029 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 18:35:44 +0100 -Subject: [PATCH 188/216] scripts/mkknlimg: Add support for ARCH_BCM2835 - -Add a new trailer field indicating whether this is an ARCH_BCM2835 -build, as opposed to MACH_BCM2708/9. If the loader finds this flag -is set it changes the default base dtb file name from bcm270x... -to bcm283y... - -Also update knlinfo to show the status of the field. ---- - scripts/knlinfo | 1 + - scripts/mkknlimg | 25 ++++++++++++++++++++----- - 2 files changed, 21 insertions(+), 5 deletions(-) - -diff --git a/scripts/knlinfo b/scripts/knlinfo -index 9c9b42e3..a0e8663 100755 ---- a/scripts/knlinfo -+++ b/scripts/knlinfo -@@ -18,6 +18,7 @@ my %atom_formats = - ( - 'DTOK' => \&format_bool, - 'KVer' => \&format_string, -+ '283x' => \&format_bool, - ); - - if (@ARGV != 1) -diff --git a/scripts/mkknlimg b/scripts/mkknlimg -index ac829d0..3dff948 100755 ---- a/scripts/mkknlimg -+++ b/scripts/mkknlimg -@@ -1,7 +1,7 @@ - #!/usr/bin/env perl - # ---------------------------------------------------------------------- - # mkknlimg by Phil Elwell for Raspberry Pi --# based on extract-ikconfig Dick Streefland -+# based on extract-ikconfig by Dick Streefland - # - # (c) 2009,2010 Dick Streefland - # (c) 2014,2015 Raspberry Pi (Trading) Limited -@@ -19,6 +19,7 @@ my $tmpfile1 = "/tmp/mkknlimg_$$.1"; - my $tmpfile2 = "/tmp/mkknlimg_$$.2"; - - my $dtok = 0; -+my $is_283x = 0; - - while (@ARGV && ($ARGV[0] =~ /^-/)) - { -@@ -27,6 +28,10 @@ while (@ARGV && ($ARGV[0] =~ /^-/)) - { - $dtok = 1; - } -+ elsif ($arg eq '--283x') -+ { -+ $is_283x = 1; -+ } - else - { - print ("* Unknown option '$arg'\n"); -@@ -47,15 +52,18 @@ if (! -r $kernel_file) - - my @wanted_config_lines = - ( -- 'CONFIG_BCM2708_DT' -+ 'CONFIG_BCM2708_DT', -+ 'CONFIG_ARCH_BCM2835' - ); - - my @wanted_strings = - ( - 'bcm2708_fb', -+ 'brcm,bcm2835-mmc', -+ 'brcm,bcm2835-sdhost', - 'brcm,bcm2708-pinctrl', - 'brcm,bcm2835-gpio', -- 'of_find_property' -+ 'brcm,bcm2835-pm-wdt' - ); - - my $res = try_extract($kernel_file, $tmpfile1); -@@ -86,11 +94,16 @@ if ($res) - $append_trailer = $dtok; - if (!$dtok) - { -- if (config_bool($res, 'bcm2708_fb')) -+ if (config_bool($res, 'bcm2708_fb') || -+ config_bool($res, 'brcm,bcm2835-mmc') || -+ config_bool($res, 'brcm,bcm2835-sdhost')) - { - $dtok ||= config_bool($res, 'CONFIG_BCM2708_DT'); -+ $dtok ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); - $dtok ||= config_bool($res, 'brcm,bcm2708-pinctrl'); - $dtok ||= config_bool($res, 'brcm,bcm2835-gpio'); -+ $is_283x ||= config_bool($res, 'CONFIG_ARCH_BCM2835'); -+ $is_283x ||= config_bool($res, 'brcm,bcm2835-pm-wdt'); - $append_trailer = 1; - } - else -@@ -107,12 +120,14 @@ elsif (!$dtok) - if ($append_trailer) - { - printf("DT: %s\n", $dtok ? "y" : "n"); -+ printf("283x: %s\n", $is_283x ? "y" : "n"); - - my @atoms; - - push @atoms, [ $trailer_magic, pack('V', 0) ]; - push @atoms, [ 'KVer', $kver ]; - push @atoms, [ 'DTOK', pack('V', $dtok) ]; -+ push @atoms, [ '283x', pack('V', $is_283x) ]; - - $trailer = pack_trailer(\@atoms); - $atoms[0]->[1] = pack('V', length($trailer)); -@@ -166,7 +181,7 @@ END { - - sub usage - { -- print ("Usage: mkknlimg [--dtok] \n"); -+ print ("Usage: mkknlimg [--dtok] [--283x] \n"); - exit(1); - } - - -From 73bb23f8980890aad84dc6b852f0aac91ab71981 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 10 Mar 2015 18:35:18 +0100 -Subject: [PATCH 189/216] config: add KEYBOARD_GPIO - ---- - arch/arm/configs/bcm2709_defconfig | 3 ++- - arch/arm/configs/bcmrpi_defconfig | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 9daaeb7..5ce9a01 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -520,7 +520,8 @@ CONFIG_INPUT_POLLDEV=m - # CONFIG_INPUT_MOUSEDEV_PSAUX is not set - CONFIG_INPUT_JOYDEV=m - CONFIG_INPUT_EVDEV=m --# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y - CONFIG_JOYSTICK_IFORCE=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index dc27aeb..da443da 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -513,7 +513,8 @@ CONFIG_INPUT_POLLDEV=m - # CONFIG_INPUT_MOUSEDEV_PSAUX is not set - CONFIG_INPUT_JOYDEV=m - CONFIG_INPUT_EVDEV=m --# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y - CONFIG_JOYSTICK_IFORCE=m - -From d7d347201d595ccc495da617ab583fdb3e282829 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 10 Mar 2015 18:35:59 +0100 -Subject: [PATCH 190/216] dts: overlay: add support for tinylcd.com 3.5" - display -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree overlay for 3.5" display by tinylcd.com - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/tinylcd35-overlay.dts | 216 ++++++++++++++++++++++++++++++++ - 2 files changed, 217 insertions(+) - create mode 100644 arch/arm/boot/dts/tinylcd35-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 9124dfb..25ea8eb 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -38,6 +38,7 @@ dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -diff --git a/arch/arm/boot/dts/tinylcd35-overlay.dts b/arch/arm/boot/dts/tinylcd35-overlay.dts -new file mode 100644 -index 0000000..f7102c8 ---- /dev/null -+++ b/arch/arm/boot/dts/tinylcd35-overlay.dts -@@ -0,0 +1,216 @@ -+/* -+ * tinylcd35-overlay.dts -+ * -+ * ------------------------------------------------- -+ * www.tinlylcd.com -+ * ------------------------------------------------- -+ * Device---Driver-----BUS GPIO's -+ * display tinylcd35 spi0.0 25 24 18 -+ * touch ads7846 spi0.1 5 -+ * rtc ds1307 i2c1-0068 -+ * rtc pcf8563 i2c1-0051 -+ * keypad gpio-keys --------- 17 22 27 23 28 -+ * -+ * -+ * TinyLCD.com 3.5 inch TFT -+ * -+ * Version 001 -+ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -+ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ tinylcd35_pins: tinylcd35_pins { -+ brcm,pins = <25 24 18>; -+ brcm,function = <1>; /* out */ -+ }; -+ tinylcd35_ts_pins: tinylcd35_ts_pins { -+ brcm,pins = <5>; -+ brcm,function = <0>; /* in */ -+ }; -+ keypad_pins: keypad_pins { -+ brcm,pins = <4 17 22 23 27>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <1>; /* down */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ tinylcd35: tinylcd35@0{ -+ compatible = "neosec,tinylcd"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&tinylcd35_pins>, -+ <&tinylcd35_ts_pins>; -+ -+ spi-max-frequency = <48000000>; -+ rotate = <270>; -+ fps = <20>; -+ bgr; -+ buswidth = <8>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ -+ init = <0x10000B0 0x80 -+ 0x10000C0 0x0A 0x0A -+ 0x10000C1 0x01 0x01 -+ 0x10000C2 0x33 -+ 0x10000C5 0x00 0x42 0x80 -+ 0x10000B1 0xD0 0x11 -+ 0x10000B4 0x02 -+ 0x10000B6 0x00 0x22 0x3B -+ 0x10000B7 0x07 -+ 0x1000036 0x58 -+ 0x10000F0 0x36 0xA5 0xD3 -+ 0x10000E5 0x80 -+ 0x10000E5 0x01 -+ 0x10000B3 0x00 -+ 0x10000E5 0x00 -+ 0x10000F0 0x36 0xA5 0x53 -+ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -+ 0x100003A 0x55 -+ 0x1000011 -+ 0x2000001 -+ 0x1000029>; -+ }; -+ -+ tinylcd35_ts: tinylcd35_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ status = "disabled"; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <5 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 5 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ -+ /* RTC */ -+ -+ fragment@3 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* -+ * Values for input event code is found under the -+ * 'Keys and buttons' heading in include/uapi/linux/input.h -+ */ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ keypad: keypad { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&keypad_pins>; -+ status = "disabled"; -+ autorepeat; -+ -+ button@17 { -+ label = "GPIO KEY_UP"; -+ linux,code = <103>; -+ gpios = <&gpio 17 0>; -+ }; -+ button@22 { -+ label = "GPIO KEY_DOWN"; -+ linux,code = <108>; -+ gpios = <&gpio 22 0>; -+ }; -+ button@27 { -+ label = "GPIO KEY_LEFT"; -+ linux,code = <105>; -+ gpios = <&gpio 27 0>; -+ }; -+ button@23 { -+ label = "GPIO KEY_RIGHT"; -+ linux,code = <106>; -+ gpios = <&gpio 23 0>; -+ }; -+ button@4 { -+ label = "GPIO KEY_ENTER"; -+ linux,code = <28>; -+ gpios = <&gpio 4 0>; -+ }; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&tinylcd35>,"spi-max-frequency:0"; -+ rotate = <&tinylcd35>,"rotate:0"; -+ fps = <&tinylcd35>,"fps:0"; -+ debug = <&tinylcd35>,"debug:0"; -+ touch = <&tinylcd35_ts>,"status"; -+ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -+ <&tinylcd35_ts>,"interrupts:0", -+ <&tinylcd35_ts>,"pendown-gpio:4"; -+ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -+ rtc-pcf = <&i2c1>,"status", -+ <&pcf8563>,"status"; -+ rtc-ds = <&i2c1>,"status", -+ <&ds1307>,"status"; -+ keypad = <&keypad>,"status"; -+ }; -+}; - -From 4b843d5be018d8d392a4be34a7fdfe3640e3c2a7 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 29 May 2015 14:16:47 +0100 -Subject: [PATCH 191/216] BCM270X_DT: Move the overlays into a subdirectory, - adding the README - ---- - arch/arm/boot/dts/Makefile | 31 +- - arch/arm/boot/dts/ads7846-overlay.dts | 83 ---- - arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts | 23 - - arch/arm/boot/dts/ds1307-rtc-overlay.dts | 22 - - arch/arm/boot/dts/enc28j60-overlay.dts | 29 -- - arch/arm/boot/dts/hifiberry-amp-overlay.dts | 39 -- - arch/arm/boot/dts/hifiberry-dac-overlay.dts | 34 -- - arch/arm/boot/dts/hifiberry-dacplus-overlay.dts | 39 -- - arch/arm/boot/dts/hifiberry-digi-overlay.dts | 39 -- - arch/arm/boot/dts/hy28a-overlay.dts | 87 ---- - arch/arm/boot/dts/hy28b-overlay.dts | 142 ------- - arch/arm/boot/dts/i2c-rtc-overlay.dts | 43 -- - arch/arm/boot/dts/iqaudio-dac-overlay.dts | 39 -- - arch/arm/boot/dts/iqaudio-dacplus-overlay.dts | 39 -- - arch/arm/boot/dts/lirc-rpi-overlay.dts | 57 --- - arch/arm/boot/dts/mmc-overlay.dts | 19 - - arch/arm/boot/dts/mz61581-overlay.dts | 109 ----- - arch/arm/boot/dts/overlays/Makefile | 51 +++ - arch/arm/boot/dts/overlays/README | 470 +++++++++++++++++++++ - arch/arm/boot/dts/overlays/ads7846-overlay.dts | 83 ++++ - .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + - arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 29 ++ - .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 ++ - .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 ++ - .../dts/overlays/hifiberry-dacplus-overlay.dts | 39 ++ - .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/hy28a-overlay.dts | 87 ++++ - arch/arm/boot/dts/overlays/hy28b-overlay.dts | 142 +++++++ - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 49 +++ - arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 39 ++ - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 +++ - arch/arm/boot/dts/overlays/mmc-overlay.dts | 19 + - arch/arm/boot/dts/overlays/mz61581-overlay.dts | 109 +++++ - arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts | 22 + - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 94 +++++ - .../dts/overlays/pitft28-resistive-overlay.dts | 115 +++++ - arch/arm/boot/dts/overlays/pps-gpio-overlay.dts | 34 ++ - arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 34 ++ - arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 82 ++++ - arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 ++ - arch/arm/boot/dts/overlays/sdhost-overlay.dts | 75 ++++ - arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts | 18 + - arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts | 18 + - arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 216 ++++++++++ - arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 ++ - .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 ++ - arch/arm/boot/dts/pcf2127-rtc-overlay.dts | 22 - - arch/arm/boot/dts/pcf8523-rtc-overlay.dts | 22 - - arch/arm/boot/dts/piscreen-overlay.dts | 94 ----- - arch/arm/boot/dts/pitft28-resistive-overlay.dts | 115 ----- - arch/arm/boot/dts/pps-gpio-overlay.dts | 34 -- - arch/arm/boot/dts/rpi-dac-overlay.dts | 34 -- - arch/arm/boot/dts/rpi-display-overlay.dts | 82 ---- - arch/arm/boot/dts/rpi-proto-overlay.dts | 39 -- - arch/arm/boot/dts/sdhost-overlay.dts | 75 ---- - arch/arm/boot/dts/spi-bcm2708-overlay.dts | 18 - - arch/arm/boot/dts/spi-bcm2835-overlay.dts | 18 - - arch/arm/boot/dts/tinylcd35-overlay.dts | 216 ---------- - arch/arm/boot/dts/w1-gpio-overlay.dts | 39 -- - arch/arm/boot/dts/w1-gpio-pullup-overlay.dts | 41 -- - 63 files changed, 2220 insertions(+), 1722 deletions(-) - delete mode 100644 arch/arm/boot/dts/ads7846-overlay.dts - delete mode 100644 arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts - delete mode 100644 arch/arm/boot/dts/ds1307-rtc-overlay.dts - delete mode 100755 arch/arm/boot/dts/enc28j60-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-amp-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-dacplus-overlay.dts - delete mode 100644 arch/arm/boot/dts/hifiberry-digi-overlay.dts - delete mode 100644 arch/arm/boot/dts/hy28a-overlay.dts - delete mode 100644 arch/arm/boot/dts/hy28b-overlay.dts - delete mode 100644 arch/arm/boot/dts/i2c-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/iqaudio-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/iqaudio-dacplus-overlay.dts - delete mode 100644 arch/arm/boot/dts/lirc-rpi-overlay.dts - delete mode 100644 arch/arm/boot/dts/mmc-overlay.dts - delete mode 100644 arch/arm/boot/dts/mz61581-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/Makefile - create mode 100644 arch/arm/boot/dts/overlays/README - create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hy28a-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/hy28b-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/pps-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-dac-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-display-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/tinylcd35-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts - delete mode 100644 arch/arm/boot/dts/pcf2127-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/pcf8523-rtc-overlay.dts - delete mode 100644 arch/arm/boot/dts/piscreen-overlay.dts - delete mode 100644 arch/arm/boot/dts/pitft28-resistive-overlay.dts - delete mode 100644 arch/arm/boot/dts/pps-gpio-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-dac-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-display-overlay.dts - delete mode 100644 arch/arm/boot/dts/rpi-proto-overlay.dts - delete mode 100644 arch/arm/boot/dts/sdhost-overlay.dts - delete mode 100644 arch/arm/boot/dts/spi-bcm2708-overlay.dts - delete mode 100644 arch/arm/boot/dts/spi-bcm2835-overlay.dts - delete mode 100644 arch/arm/boot/dts/tinylcd35-overlay.dts - delete mode 100644 arch/arm/boot/dts/w1-gpio-overlay.dts - delete mode 100644 arch/arm/boot/dts/w1-gpio-pullup-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 25ea8eb..ea93e1d 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -13,36 +13,7 @@ ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif - --dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += ds1307-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pcf2127-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pcf8523-rtc-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb --dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb -+subdir-$(RPI_DT_OVERLAYS) += overlays - - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -diff --git a/arch/arm/boot/dts/ads7846-overlay.dts b/arch/arm/boot/dts/ads7846-overlay.dts -deleted file mode 100644 -index 6a92cd1..0000000 ---- a/arch/arm/boot/dts/ads7846-overlay.dts -+++ /dev/null -@@ -1,83 +0,0 @@ --/* -- * Generic Device Tree overlay for the ADS7846 touch controller -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- ads7846_pins: ads7846_pins { -- brcm,pins = <255>; /* illegal default value */ -- brcm,function = <0>; /* in */ -- brcm,pull = <0>; /* none */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- ads7846: ads7846@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- pinctrl-names = "default"; -- pinctrl-0 = <&ads7846_pins>; -- -- spi-max-frequency = <2000000>; -- interrupts = <255 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 255 0>; -- -- /* driver defaults */ -- ti,x-min = /bits/ 16 <0>; -- ti,y-min = /bits/ 16 <0>; -- ti,x-max = /bits/ 16 <0x0FFF>; -- ti,y-max = /bits/ 16 <0x0FFF>; -- ti,pressure-min = /bits/ 16 <0>; -- ti,pressure-max = /bits/ 16 <0xFFFF>; -- ti,x-plate-ohms = /bits/ 16 <400>; -- }; -- }; -- }; -- __overrides__ { -- cs = <&ads7846>,"reg:0"; -- speed = <&ads7846>,"spi-max-frequency:0"; -- penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -- <&ads7846>,"interrupts:0", -- <&ads7846>,"pendown-gpio:4"; -- penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -- swapxy = <&ads7846>,"ti,swap-xy?"; -- xmin = <&ads7846>,"ti,x-min;0"; -- ymin = <&ads7846>,"ti,y-min;0"; -- xmax = <&ads7846>,"ti,x-max;0"; -- ymax = <&ads7846>,"ti,y-max;0"; -- pmin = <&ads7846>,"ti,pressure-min;0"; -- pmax = <&ads7846>,"ti,pressure-max;0"; -- xohms = <&ads7846>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -deleted file mode 100644 -index b830bf2..0000000 ---- a/arch/arm/boot/dts/bmp085_i2c-sensor-overlay.dts -+++ /dev/null -@@ -1,23 +0,0 @@ --// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- bmp085@77 { -- compatible = "bosch,bmp085"; -- reg = <0x77>; -- default-oversampling = <3>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/ds1307-rtc-overlay.dts -deleted file mode 100644 -index 7d27044..0000000 ---- a/arch/arm/boot/dts/ds1307-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for DS1307 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/enc28j60-overlay.dts b/arch/arm/boot/dts/enc28j60-overlay.dts -deleted file mode 100755 -index aa9b645..0000000 ---- a/arch/arm/boot/dts/enc28j60-overlay.dts -+++ /dev/null -@@ -1,29 +0,0 @@ --// Overlay for the Microchip ENC28J60 Ethernet Controller --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- enc28j60@0{ -- compatible = "microchip,enc28j60"; -- reg = <0>; /* CE0 */ -- spi-max-frequency = <12000000>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/hifiberry-amp-overlay.dts -deleted file mode 100644 -index 2c81448..0000000 ---- a/arch/arm/boot/dts/hifiberry-amp-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry Amp/Amp+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-amp"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- tas5713@1b { -- #sound-dai-cells = <0>; -- compatible = "ti,tas5713"; -- reg = <0x1b>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/hifiberry-dac-overlay.dts -deleted file mode 100644 -index 5e7633a..0000000 ---- a/arch/arm/boot/dts/hifiberry-dac-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --// Definitions for HiFiBerry DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target-path = "/"; -- __overlay__ { -- pcm5102a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5102a"; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -deleted file mode 100644 -index deb9c625..0000000 ---- a/arch/arm/boot/dts/hifiberry-dacplus-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry DAC+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-dacplus"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4d { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4d>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/hifiberry-digi-overlay.dts -deleted file mode 100644 -index d0e0d8a..0000000 ---- a/arch/arm/boot/dts/hifiberry-digi-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for HiFiBerry Digi --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "hifiberry,hifiberry-digi"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- wm8804@3b { -- #sound-dai-cells = <0>; -- compatible = "wlf,wm8804"; -- reg = <0x3b>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/hy28a-overlay.dts b/arch/arm/boot/dts/hy28a-overlay.dts -deleted file mode 100644 -index 3cd3083..0000000 ---- a/arch/arm/boot/dts/hy28a-overlay.dts -+++ /dev/null -@@ -1,87 +0,0 @@ --/* -- * Device Tree overlay for HY28A display -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- hy28a_pins: hy28a_pins { -- brcm,pins = <17 25 18>; -- brcm,function = <0 1 1>; /* in out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- hy28a: hy28a@0{ -- compatible = "ilitek,ili9320"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&hy28a_pins>; -- -- spi-max-frequency = <32000000>; -- spi-cpol; -- spi-cpha; -- rotate = <270>; -- bgr; -- fps = <50>; -- buswidth = <8>; -- startbyte = <0x70>; -- reset-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- }; -- -- hy28a_ts: hy28a-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&hy28a>,"spi-max-frequency:0"; -- rotate = <&hy28a>,"rotate:0"; -- fps = <&hy28a>,"fps:0"; -- debug = <&hy28a>,"debug:0"; -- xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -- resetgpio = <&hy28a>,"reset-gpios:4", -- <&hy28a_pins>, "brcm,pins:1"; -- ledgpio = <&hy28a>,"led-gpios:4", -- <&hy28a_pins>, "brcm,pins:2"; -- }; --}; -diff --git a/arch/arm/boot/dts/hy28b-overlay.dts b/arch/arm/boot/dts/hy28b-overlay.dts -deleted file mode 100644 -index f774c4a..0000000 ---- a/arch/arm/boot/dts/hy28b-overlay.dts -+++ /dev/null -@@ -1,142 +0,0 @@ --/* -- * Device Tree overlay for HY28b display shield by Texy -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- hy28b_pins: hy28b_pins { -- brcm,pins = <17 25 18>; -- brcm,function = <0 1 1>; /* in out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- hy28b: hy28b@0{ -- compatible = "ilitek,ili9325"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&hy28b_pins>; -- -- spi-max-frequency = <48000000>; -- spi-cpol; -- spi-cpha; -- rotate = <270>; -- bgr; -- fps = <50>; -- buswidth = <8>; -- startbyte = <0x70>; -- reset-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 1>; -- -- gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -- -- init = <0x10000e7 0x0010 -- 0x1000000 0x0001 -- 0x1000001 0x0100 -- 0x1000002 0x0700 -- 0x1000003 0x1030 -- 0x1000004 0x0000 -- 0x1000008 0x0207 -- 0x1000009 0x0000 -- 0x100000a 0x0000 -- 0x100000c 0x0001 -- 0x100000d 0x0000 -- 0x100000f 0x0000 -- 0x1000010 0x0000 -- 0x1000011 0x0007 -- 0x1000012 0x0000 -- 0x1000013 0x0000 -- 0x2000032 -- 0x1000010 0x1590 -- 0x1000011 0x0227 -- 0x2000032 -- 0x1000012 0x009c -- 0x2000032 -- 0x1000013 0x1900 -- 0x1000029 0x0023 -- 0x100002b 0x000e -- 0x2000032 -- 0x1000020 0x0000 -- 0x1000021 0x0000 -- 0x2000032 -- 0x1000050 0x0000 -- 0x1000051 0x00ef -- 0x1000052 0x0000 -- 0x1000053 0x013f -- 0x1000060 0xa700 -- 0x1000061 0x0001 -- 0x100006a 0x0000 -- 0x1000080 0x0000 -- 0x1000081 0x0000 -- 0x1000082 0x0000 -- 0x1000083 0x0000 -- 0x1000084 0x0000 -- 0x1000085 0x0000 -- 0x1000090 0x0010 -- 0x1000092 0x0000 -- 0x1000093 0x0003 -- 0x1000095 0x0110 -- 0x1000097 0x0000 -- 0x1000098 0x0000 -- 0x1000007 0x0133 -- 0x1000020 0x0000 -- 0x1000021 0x0000 -- 0x2000064>; -- debug = <0>; -- }; -- -- hy28b_ts: hy28b-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&hy28b>,"spi-max-frequency:0"; -- rotate = <&hy28b>,"rotate:0"; -- fps = <&hy28b>,"fps:0"; -- debug = <&hy28b>,"debug:0"; -- xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -- resetgpio = <&hy28b>,"reset-gpios:4", -- <&hy28b_pins>, "brcm,pins:1"; -- ledgpio = <&hy28b>,"led-gpios:4", -- <&hy28b_pins>, "brcm,pins:2"; -- }; --}; -diff --git a/arch/arm/boot/dts/i2c-rtc-overlay.dts b/arch/arm/boot/dts/i2c-rtc-overlay.dts -deleted file mode 100644 -index 5d5abb1..0000000 ---- a/arch/arm/boot/dts/i2c-rtc-overlay.dts -+++ /dev/null -@@ -1,43 +0,0 @@ --// Definitions for several I2C based Real Time Clocks --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- ds1307: ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "disable"; -- }; -- ds3231: ds3231@68 { -- compatible = "maxim,ds3231"; -- reg = <0x68>; -- status = "disable"; -- }; -- pcf2127: pcf2127@51 { -- compatible = "nxp,pcf2127"; -- reg = <0x51>; -- status = "disable"; -- }; -- pcf8523: pcf8523@68 { -- compatible = "nxp,pcf8523"; -- reg = <0x68>; -- status = "disable"; -- }; -- }; -- }; -- __overrides__ { -- ds1307 = <&ds1307>,"status"; -- ds3231 = <&ds3231>,"status"; -- pcf2127 = <&pcf2127>,"status"; -- pcf8523 = <&pcf8523>,"status"; -- }; --}; -diff --git a/arch/arm/boot/dts/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/iqaudio-dac-overlay.dts -deleted file mode 100644 -index ea8173e..0000000 ---- a/arch/arm/boot/dts/iqaudio-dac-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for IQaudIO DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "iqaudio,iqaudio-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4c { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4c>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -deleted file mode 100644 -index 735d8ab..0000000 ---- a/arch/arm/boot/dts/iqaudio-dacplus-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for IQaudIO DAC+ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "iqaudio,iqaudio-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcm5122@4c { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5122"; -- reg = <0x4c>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/lirc-rpi-overlay.dts b/arch/arm/boot/dts/lirc-rpi-overlay.dts -deleted file mode 100644 -index 7d5d82b..0000000 ---- a/arch/arm/boot/dts/lirc-rpi-overlay.dts -+++ /dev/null -@@ -1,57 +0,0 @@ --// Definitions for lirc-rpi module --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- lirc_rpi: lirc_rpi { -- compatible = "rpi,lirc-rpi"; -- pinctrl-names = "default"; -- pinctrl-0 = <&lirc_pins>; -- status = "okay"; -- -- // Override autodetection of IR receiver circuit -- // (0 = active high, 1 = active low, -1 = no override ) -- rpi,sense = <0xffffffff>; -- -- // Software carrier -- // (0 = off, 1 = on) -- rpi,softcarrier = <1>; -- -- // Invert output -- // (0 = off, 1 = on) -- rpi,invert = <0>; -- -- // Enable debugging messages -- // (0 = off, 1 = on) -- rpi,debug = <0>; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- lirc_pins: lirc_pins { -- brcm,pins = <17 18>; -- brcm,function = <1 0>; // out in -- brcm,pull = <0 1>; // off down -- }; -- }; -- }; -- -- __overrides__ { -- gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -- gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -- gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -- -- sense = <&lirc_rpi>,"rpi,sense:0"; -- softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -- invert = <&lirc_rpi>,"rpi,invert:0"; -- debug = <&lirc_rpi>,"rpi,debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/mmc-overlay.dts b/arch/arm/boot/dts/mmc-overlay.dts -deleted file mode 100644 -index 0a37cf4..0000000 ---- a/arch/arm/boot/dts/mmc-overlay.dts -+++ /dev/null -@@ -1,19 +0,0 @@ --/dts-v1/; --/plugin/; -- --/{ -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&mmc>; -- -- __overlay__ { -- brcm,overclock-50 = <0>; -- }; -- }; -- -- __overrides__ { -- overclock_50 = <&mmc>,"brcm,overclock-50:0"; -- force_pio = <&mmc>,"brcm,force-pio?"; -- }; --}; -diff --git a/arch/arm/boot/dts/mz61581-overlay.dts b/arch/arm/boot/dts/mz61581-overlay.dts -deleted file mode 100644 -index c06fe12..0000000 ---- a/arch/arm/boot/dts/mz61581-overlay.dts -+++ /dev/null -@@ -1,109 +0,0 @@ --/* -- * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- mz61581_pins: mz61581_pins { -- brcm,pins = <4 15 18 25>; -- brcm,function = <0 1 1 1>; /* in out out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- mz61581: mz61581@0{ -- compatible = "samsung,s6d02a1"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&mz61581_pins>; -- -- spi-max-frequency = <128000000>; -- spi-cpol; -- spi-cpha; -- -- width = <320>; -- height = <480>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- -- reset-gpios = <&gpio 15 0>; -- dc-gpios = <&gpio 25 0>; -- led-gpios = <&gpio 18 0>; -- -- init = <0x10000b0 00 -- 0x1000011 -- 0x20000ff -- 0x10000b3 0x02 0x00 0x00 0x00 -- 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -- 0x10000c1 0x08 0x16 0x08 0x08 -- 0x10000c4 0x11 0x07 0x03 0x03 -- 0x10000c6 0x00 -- 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -- 0x1000035 0x00 -- 0x1000036 0xa0 -- 0x100003a 0x55 -- 0x1000044 0x00 0x01 -- 0x10000d0 0x07 0x07 0x1d 0x03 -- 0x10000d1 0x03 0x30 0x10 -- 0x10000d2 0x03 0x14 0x04 -- 0x1000029 -- 0x100002c>; -- -- /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -- debug = <3>; -- }; -- -- mz61581_ts: mz61581_ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <4 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 4 0>; -- -- ti,x-plate-ohms = /bits/ 16 <60>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&mz61581>, "spi-max-frequency:0"; -- rotate = <&mz61581>, "rotate:0"; -- fps = <&mz61581>, "fps:0"; -- debug = <&mz61581>, "debug:0"; -- xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -new file mode 100644 -index 0000000..d64e6b4 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,51 @@ -+ifeq ($(CONFIG_OF),y) -+ -+# Overlays for the Raspberry Pi platform -+ -+ifeq ($(CONFIG_BCM2708_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ifeq ($(CONFIG_BCM2709_DT),y) -+ RPI_DT_OVERLAYS=y -+endif -+ -+dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb -+ -+targets += dtbs dtbs_install -+targets += $(dtb-y) -+ -+endif -+ -+always := $(dtb-y) -+clean-files := *.dtb -+ -+# Enable fixups to support overlays on BCM2708 platforms -+ifeq ($(RPI_DT_OVERLAYS),y) -+ DTC_FLAGS ?= -@ -+endif -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -new file mode 100644 -index 0000000..c260612 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,470 @@ -+Introduction -+============ -+ -+This directory contains Device Tree overlays. Device Tree makes it possible -+to support many hardware configurations with a single kernel and without the -+need to explicitly load or blacklist kernel modules. Note that this isn't a -+"pure" Device Tree configuration (c.f. MACH_BCM2835) - some on-board devices -+are still configured by the board support code, but the intention is to -+eventually reach that goal. -+ -+On Raspberry Pi, Device Tree usage is controlled from /boot/config.txt. By -+default, the Raspberry Pi kernel boots with device tree enabled. You can -+completely disable DT usage (for now) by adding: -+ -+ device_tree= -+ -+to your config.txt, which should cause your Pi to revert to the old way of -+doing things after a reboot. -+ -+In /boot you will find a .dtb for each base platform. This describes the -+hardware that is part of the Raspberry Pi board. The loader (start.elf and its -+siblings) selects the .dtb file appropriate for the platform by name, and reads -+it into memory. At this point, all of the optional interfaces (i2c, i2s, spi) -+are disabled, but they can be enabled using Device Tree parameters: -+ -+ dtparam=i2c=on,i2s=on,spi=on -+ -+However, this shouldn't be necessary in many use cases because loading an -+overlay that requires one of those interfaces will cause it to be enabled -+automatically, and it is advisable to only enable interfaces if they are -+needed. -+ -+Configuring additional, optional hardware is done using Device Tree overlays -+(see below). -+ -+raspi-config -+============ -+ -+The Advanced Options section of the raspi-config utility can enable and disable -+Device Tree use, as well as toggling the I2C and SPI interfaces. Note that it -+is possible to both enable an interface and blacklist the driver, if for some -+reason you should want to defer the loading. -+ -+Modules -+======= -+ -+As well as describing the hardware, Device Tree also gives enough information -+to allow suitable driver modules to be located and loaded, with the corollary -+that unneeded modules are not loaded. As a result it should be possible to -+remove lines from /etc/modules, and /etc/modprobe.d/raspi-blacklist.conf can -+have its contents deleted (or commented out). -+ -+Using Overlays -+============== -+ -+Overlays are loaded using the "dtoverlay" directive. As an example, consider the -+popular lirc-rpi module, the Linux Infrared Remote Control driver. In the -+pre-DT world this would be loaded from /etc/modules, with an explicit -+"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled, -+this becomes a line in config.txt: -+ -+ dtoverlay=lirc-rpi -+ -+This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By -+default it will use GPIOs 17 (out) and 18 (in), but this can be modified using -+DT parameters: -+ -+ dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13 -+ -+Parameters always have default values, although in some cases (e.g. "w1-gpio") -+it is necessary to provided multiple overlays in order to get the desired -+behaviour. See the list of overlays below for a description of the parameters and their defaults. -+ -+The Overlay and Parameter Reference -+=================================== -+ -+Name: -+Info: Configures the base Raspberry Pi hardware -+Load: -+Params: -+ i2c_arm Set to "on" to enable the ARM's i2c interface -+ (default "off") -+ -+ i2c_vc Set to "on" to enable the i2c interface -+ usually reserved for the VideoCore processor -+ (default "off") -+ -+ i2c An alias for i2c_arm -+ -+ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface -+ (default "100000") -+ -+ i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface -+ (default "100000") -+ -+ i2c_baudrate An alias for i2c_arm_baudrate -+ -+ i2s Set to "on" to enable the i2s interface -+ (default "off") -+ -+ spi Set to "on" to enable the spi interfaces -+ (default "off") -+ -+ act_led_trigger Choose which activity the LED tracks. -+ Use "heartbeat" for a nice load indicator. -+ (default "mmc") -+ -+ act_led_activelow Set to "on" to invert the sense of the LED -+ (default "off") -+ -+ act_led_gpio Set which GPIO to use for the activity LED -+ (in case you want to connect it to an external -+ device) -+ (default "16" on a non-Plus board, "47" on a -+ Plus or Pi 2) -+ -+ pwr_led_trigger -+ pwr_led_activelow -+ pwr_led_gpio -+ As for act_led_*, but using the PWR LED. -+ Not available on Model A/B boards. -+ -+ N.B. It is recommended to only enable those interfaces that are needed. -+ Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc -+ interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.) -+ Note also that i2c, i2c_arm and i2c_vc are aliases for the physical -+ interfaces i2c0 and i2c1. Use of the numeric variants is still possible -+ but deprecated because the ARM/VC assignments differ between board -+ revisions. The same board-specific mapping applies to i2c_baudrate, -+ and the other i2c baudrate parameters. -+ -+ -+Name: ads7846 -+Info: ADS7846 Touch controller -+Load: dtoverlay=ads7846,= -+Params: cs SPI bus Chip Select (default 1) -+ speed SPI bus speed (default 2Mhz, max 3.25MHz) -+ penirq GPIO used for PENIRQ. REQUIRED -+ penirq_pull Set GPIO pull (default 0=none, 2=pullup) -+ swapxy Swap x and y axis -+ xmin Minimum value on the X axis (default 0) -+ ymin Minimum value on the Y axis (default 0) -+ xmax Maximum value on the X axis (default 4095) -+ ymax Maximum value on the Y axis (default 4095) -+ pmin Minimum reported pressure value (default 0) -+ pmax Maximum reported pressure value (default 65535) -+ xohms Touchpanel sensitivity (X-plate resistance) -+ (default 400) -+ -+ penirq is required and usually xohms (60-100) has to be set as well. -+ Apart from that, pmax (255) and swapxy are also common. -+ The rest of the calibration can be done with xinput-calibrator. -+ See: github.com/notro/fbtft/wiki/FBTFT-on-Raspian -+ Device Tree binding document: -+ www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt -+ -+ -+Name: bmp085_i2c-sensor -+Info: Configures the BMP085/BMP180 digital barometric pressure and temperature -+ sensors from Bosch Sensortec -+Load: dtoverlay=bmp085_i2c-sensor -+Params: -+ -+ -+[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+Name: enc28j60 -+Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) -+Load: dtoverlay=enc28j60,= -+Params: int_pin GPIO used for INT (default 25) -+ -+ speed SPI bus speed (default 12000000) -+ -+ -+Name: hifiberry-amp -+Info: Configures the HifiBerry Amp and Amp+ audio cards -+Load: dtoverlay=hifiberry-amp -+Params: -+ -+ -+Name: hifiberry-dac -+Info: Configures the HifiBerry DAC audio card -+Load: dtoverlay=hifiberry-dac -+Params: -+ -+ -+Name: hifiberry-dacplus -+Info: Configures the HifiBerry DAC+ audio card -+Load: dtoverlay=hifiberry-dacplus -+Params: -+ -+ -+Name: hifiberry-digi -+Info: Configures the HifiBerry Digi audio card -+Load: dtoverlay=hifiberry-digi -+Params: -+ -+ -+Name: hy28a -+Info: HY28A - 2.8" TFT LCD Display Module by HAOYU Electronics -+ Default values match Texy's display shield -+Load: dtoverlay=hy28a,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ resetgpio GPIO used to reset controller -+ -+ ledgpio GPIO used to control backlight -+ -+ -+Name: hy28b -+Info: HY28B - 2.8" TFT LCD Display Module by HAOYU Electronics -+ Default values match Texy's display shield -+Load: dtoverlay=hy28b,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ resetgpio GPIO used to reset controller -+ -+ ledgpio GPIO used to control backlight -+ -+ -+Name: i2c-rtc -+Info: Adds support for a number of I2C Real Time Clock devices -+Load: dtoverlay=i2c-rtc, -+Params: ds1307 Select the DS1307 device -+ -+ ds3231 Select the DS3231 device -+ -+ pcf2127 Select the PCF2127 device -+ -+ pcf8523 Select the PCF8523 device -+ -+ pcf8563 Select the PCF8563 device -+ -+ -+Name: iqaudio-dac -+Info: Configures the IQaudio DAC audio card -+Load: dtoverlay=iqaudio-dac -+Params: -+ -+ -+Name: iqaudio-dacplus -+Info: Configures the IQaudio DAC+ audio card -+Load: dtoverlay=iqaudio-dacplus -+Params: -+ -+ -+Name: lirc-rpi -+Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi) -+ Consult the module documentation for more details. -+Load: dtoverlay=lirc-rpi,=,... -+Params: gpio_out_pin GPIO for output (default "17") -+ -+ gpio_in_pin GPIO for input (default "18") -+ -+ gpio_in_pull Pull up/down/off on the input pin -+ (default "down") -+ -+ sense Override the IR receive auto-detection logic: -+ "1" = force active high -+ "0" = force active low -+ "-1" = use auto-detection -+ (default "-1") -+ -+ softcarrier Turn the software carrier "on" or "off" -+ (default "on") -+ -+ invert "on" = invert the output pin (default "off") -+ -+ debug "on" = enable additional debug messages -+ (default "off") -+ -+ -+Name: mmc -+Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock -+Load: dtoverlay=mmc,= -+Params: overclock_50 Clock (in MHz) to use when the MMC framework -+ requests 50MHz -+ force_pio Disable DMA support -+ -+ -+Name: mz61581 -+Info: MZ61581 display by Tontec -+Load: dtoverlay=mz61581,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ -+[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+[ The pcf8523-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+[ The pcf8563-rtc overlay has been deleted. See i2c-rtc. ] -+ -+ -+Name: piscreen -+Info: PiScreen display by OzzMaker.com -+Load: dtoverlay=piscreen,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ -+Name: pitft28-resistive -+Info: Adafruit PiTFT 2.8" resistive touch screen -+Load: dtoverlay=pitft28-resistive,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ -+Name: pps-gpio -+Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). -+Load: dtoverlay=pps-gpio,= -+Params: gpiopin Input GPIO (default "18") -+ -+ -+Name: rpi-dac -+Info: Configures the RPi DAC audio card -+Load: dtoverlay=rpi-dac -+Params: -+ -+ -+Name: rpi-display -+Info: RPi-Display - 2.8" Touch Display by Watterott -+Load: dtoverlay=rpi-display,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ xohms Touchpanel sensitivity (X-plate resistance) -+ -+ -+Name: rpi-proto -+Info: Configures the RPi Proto audio card -+Load: dtoverlay=rpi-proto -+Params: -+ -+ -+Name: sdhost -+Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock -+Load: dtoverlay=sdhost,= -+Params: overclock_50 Clock (in MHz) to use when the MMC framework -+ requests 50MHz -+ force_pio Disable DMA support -+ -+ -+Name: spi-bcm2708 -+Info: Selects the bcm2708-spi SPI driver -+Load: dtoverlay=spi-bcm2708 -+Params: -+ -+ -+Name: spi-bcm2835 -+Info: Selects the bcm2835-spi SPI driver -+Load: dtoverlay=spi-bcm2835 -+Params: -+ -+ -+Name: tinylcd35 -+Info: 3.5" Color TFT Display by www.tinlylcd.com -+ Options: Touch, RTC, keypad -+Load: dtoverlay=tinylcd35,= -+Params: speed Display SPI bus speed -+ -+ rotate Display rotation {0,90,180,270} -+ -+ fps Delay between frame updates -+ -+ debug Debug output level {0-7} -+ -+ touch Enable touch panel -+ -+ touchgpio Touch controller IRQ GPIO -+ -+ xohms Touchpanel: Resistance of X-plate in ohms -+ -+ rtc-pcf PCF8563 Real Time Clock -+ -+ rtc-ds DS1307 Real Time Clock -+ -+ keypad Enable keypad -+ -+ Examples: -+ Display with touchpanel, PCF8563 RTC and keypad: -+ dtoverlay=tinylcd35,touch,rtc-pcf,keypad -+ Old touch display: -+ dtoverlay=tinylcd35,touch,touchgpio=3 -+ -+ -+Name: w1-gpio -+Info: Configures the w1-gpio Onewire interface module. -+ Use this overlay if you *don't* need a GPIO to drive an external pullup. -+Load: dtoverlay=w1-gpio,= -+Params: gpiopin GPIO for I/O (default "4") -+ -+ pullup Non-zero, "on", or "y" to enable the parasitic -+ power (2-wire, power-on-data) feature -+ -+ -+Name: w1-gpio-pullup -+Info: Configures the w1-gpio Onewire interface module. -+ Use this overlay if you *do* need a GPIO to drive an external pullup. -+Load: dtoverlay=w1-gpio-pullup,=,... -+Params: gpiopin GPIO for I/O (default "4") -+ -+ pullup Non-zero, "on", or "y" to enable the parasitic -+ power (2-wire, power-on-data) feature -+ -+ extpullup GPIO for external pullup (default "5") -+ -+ -+Troubleshooting -+=============== -+ -+If you are experiencing problems that you think are DT-related, enable DT -+diagnostic output by adding this to /boot/config.txt: -+ -+ dtdebug=on -+ -+and rebooting. Then run: -+ -+ sudo vcdbg log msg -+ -+and look for relevant messages. -+ -+Further reading -+=============== -+ -+This is only meant to be a quick introduction to the subject of Device Tree on -+Raspberry Pi. There is a more complete explanation here: -+ -+http://www.raspberrypi.org/documentation/configuration/device-tree.md -diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts -new file mode 100644 -index 0000000..6a92cd1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/ads7846-overlay.dts -@@ -0,0 +1,83 @@ -+/* -+ * Generic Device Tree overlay for the ADS7846 touch controller -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ ads7846_pins: ads7846_pins { -+ brcm,pins = <255>; /* illegal default value */ -+ brcm,function = <0>; /* in */ -+ brcm,pull = <0>; /* none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ads7846: ads7846@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ads7846_pins>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <255 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 255 0>; -+ -+ /* driver defaults */ -+ ti,x-min = /bits/ 16 <0>; -+ ti,y-min = /bits/ 16 <0>; -+ ti,x-max = /bits/ 16 <0x0FFF>; -+ ti,y-max = /bits/ 16 <0x0FFF>; -+ ti,pressure-min = /bits/ 16 <0>; -+ ti,pressure-max = /bits/ 16 <0xFFFF>; -+ ti,x-plate-ohms = /bits/ 16 <400>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ cs = <&ads7846>,"reg:0"; -+ speed = <&ads7846>,"spi-max-frequency:0"; -+ penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ -+ <&ads7846>,"interrupts:0", -+ <&ads7846>,"pendown-gpio:4"; -+ penirq_pull = <&ads7846_pins>,"brcm,pull:0"; -+ swapxy = <&ads7846>,"ti,swap-xy?"; -+ xmin = <&ads7846>,"ti,x-min;0"; -+ ymin = <&ads7846>,"ti,y-min;0"; -+ xmax = <&ads7846>,"ti,x-max;0"; -+ ymax = <&ads7846>,"ti,y-max;0"; -+ pmin = <&ads7846>,"ti,pressure-min;0"; -+ pmax = <&ads7846>,"ti,pressure-max;0"; -+ xohms = <&ads7846>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts -new file mode 100644 -index 0000000..b830bf2 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts -@@ -0,0 +1,23 @@ -+// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts b/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts -new file mode 100644 -index 0000000..7d27044 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/ds1307-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for DS1307 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/enc28j60-overlay.dts b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts -new file mode 100644 -index 0000000..aa9b645 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/enc28j60-overlay.dts -@@ -0,0 +1,29 @@ -+// Overlay for the Microchip ENC28J60 Ethernet Controller -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ enc28j60@0{ -+ compatible = "microchip,enc28j60"; -+ reg = <0>; /* CE0 */ -+ spi-max-frequency = <12000000>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts -new file mode 100644 -index 0000000..2c81448 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Amp/Amp+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-amp"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ tas5713@1b { -+ #sound-dai-cells = <0>; -+ compatible = "ti,tas5713"; -+ reg = <0x1b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts -new file mode 100644 -index 0000000..5e7633a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for HiFiBerry DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -new file mode 100644 -index 0000000..deb9c625 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-dacplus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4d { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4d>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -new file mode 100644 -index 0000000..d0e0d8a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for HiFiBerry Digi -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "hifiberry,hifiberry-digi"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8804@3b { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hy28a-overlay.dts b/arch/arm/boot/dts/overlays/hy28a-overlay.dts -new file mode 100644 -index 0000000..3cd3083 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts -@@ -0,0 +1,87 @@ -+/* -+ * Device Tree overlay for HY28A display -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28a_pins: hy28a_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28a: hy28a@0{ -+ compatible = "ilitek,ili9320"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28a_pins>; -+ -+ spi-max-frequency = <32000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ hy28a_ts: hy28a-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28a>,"spi-max-frequency:0"; -+ rotate = <&hy28a>,"rotate:0"; -+ fps = <&hy28a>,"fps:0"; -+ debug = <&hy28a>,"debug:0"; -+ xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28a>,"reset-gpios:4", -+ <&hy28a_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28a>,"led-gpios:4", -+ <&hy28a_pins>, "brcm,pins:2"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/hy28b-overlay.dts b/arch/arm/boot/dts/overlays/hy28b-overlay.dts -new file mode 100644 -index 0000000..f774c4a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts -@@ -0,0 +1,142 @@ -+/* -+ * Device Tree overlay for HY28b display shield by Texy -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ hy28b_pins: hy28b_pins { -+ brcm,pins = <17 25 18>; -+ brcm,function = <0 1 1>; /* in out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hy28b: hy28b@0{ -+ compatible = "ilitek,ili9325"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hy28b_pins>; -+ -+ spi-max-frequency = <48000000>; -+ spi-cpol; -+ spi-cpha; -+ rotate = <270>; -+ bgr; -+ fps = <50>; -+ buswidth = <8>; -+ startbyte = <0x70>; -+ reset-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 1>; -+ -+ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; -+ -+ init = <0x10000e7 0x0010 -+ 0x1000000 0x0001 -+ 0x1000001 0x0100 -+ 0x1000002 0x0700 -+ 0x1000003 0x1030 -+ 0x1000004 0x0000 -+ 0x1000008 0x0207 -+ 0x1000009 0x0000 -+ 0x100000a 0x0000 -+ 0x100000c 0x0001 -+ 0x100000d 0x0000 -+ 0x100000f 0x0000 -+ 0x1000010 0x0000 -+ 0x1000011 0x0007 -+ 0x1000012 0x0000 -+ 0x1000013 0x0000 -+ 0x2000032 -+ 0x1000010 0x1590 -+ 0x1000011 0x0227 -+ 0x2000032 -+ 0x1000012 0x009c -+ 0x2000032 -+ 0x1000013 0x1900 -+ 0x1000029 0x0023 -+ 0x100002b 0x000e -+ 0x2000032 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000032 -+ 0x1000050 0x0000 -+ 0x1000051 0x00ef -+ 0x1000052 0x0000 -+ 0x1000053 0x013f -+ 0x1000060 0xa700 -+ 0x1000061 0x0001 -+ 0x100006a 0x0000 -+ 0x1000080 0x0000 -+ 0x1000081 0x0000 -+ 0x1000082 0x0000 -+ 0x1000083 0x0000 -+ 0x1000084 0x0000 -+ 0x1000085 0x0000 -+ 0x1000090 0x0010 -+ 0x1000092 0x0000 -+ 0x1000093 0x0003 -+ 0x1000095 0x0110 -+ 0x1000097 0x0000 -+ 0x1000098 0x0000 -+ 0x1000007 0x0133 -+ 0x1000020 0x0000 -+ 0x1000021 0x0000 -+ 0x2000064>; -+ debug = <0>; -+ }; -+ -+ hy28b_ts: hy28b-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&hy28b>,"spi-max-frequency:0"; -+ rotate = <&hy28b>,"rotate:0"; -+ fps = <&hy28b>,"fps:0"; -+ debug = <&hy28b>,"debug:0"; -+ xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; -+ resetgpio = <&hy28b>,"reset-gpios:4", -+ <&hy28b_pins>, "brcm,pins:1"; -+ ledgpio = <&hy28b>,"led-gpios:4", -+ <&hy28b_pins>, "brcm,pins:2"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -new file mode 100644 -index 0000000..6bccfdc ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,49 @@ -+// Definitions for several I2C based Real Time Clocks -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ ds3231: ds3231@68 { -+ compatible = "maxim,ds3231"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf2127: pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ pcf8523: pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "disable"; -+ }; -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disable"; -+ }; -+ }; -+ }; -+ __overrides__ { -+ ds1307 = <&ds1307>,"status"; -+ ds3231 = <&ds3231>,"status"; -+ pcf2127 = <&pcf2127>,"status"; -+ pcf8523 = <&pcf8523>,"status"; -+ pcf8563 = <&pcf8563>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -new file mode 100644 -index 0000000..ea8173e ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -new file mode 100644 -index 0000000..735d8ab ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for IQaudIO DAC+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "iqaudio,iqaudio-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4c>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts -new file mode 100644 -index 0000000..7d5d82b ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts -@@ -0,0 +1,57 @@ -+// Definitions for lirc-rpi module -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ lirc_rpi: lirc_rpi { -+ compatible = "rpi,lirc-rpi"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lirc_pins>; -+ status = "okay"; -+ -+ // Override autodetection of IR receiver circuit -+ // (0 = active high, 1 = active low, -1 = no override ) -+ rpi,sense = <0xffffffff>; -+ -+ // Software carrier -+ // (0 = off, 1 = on) -+ rpi,softcarrier = <1>; -+ -+ // Invert output -+ // (0 = off, 1 = on) -+ rpi,invert = <0>; -+ -+ // Enable debugging messages -+ // (0 = off, 1 = on) -+ rpi,debug = <0>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ lirc_pins: lirc_pins { -+ brcm,pins = <17 18>; -+ brcm,function = <1 0>; // out in -+ brcm,pull = <0 1>; // off down -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; -+ gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; -+ gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; -+ -+ sense = <&lirc_rpi>,"rpi,sense:0"; -+ softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; -+ invert = <&lirc_rpi>,"rpi,invert:0"; -+ debug = <&lirc_rpi>,"rpi,debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/mmc-overlay.dts b/arch/arm/boot/dts/overlays/mmc-overlay.dts -new file mode 100644 -index 0000000..0a37cf4 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mmc-overlay.dts -@@ -0,0 +1,19 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ -+ __overlay__ { -+ brcm,overclock-50 = <0>; -+ }; -+ }; -+ -+ __overrides__ { -+ overclock_50 = <&mmc>,"brcm,overclock-50:0"; -+ force_pio = <&mmc>,"brcm,force-pio?"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/mz61581-overlay.dts b/arch/arm/boot/dts/overlays/mz61581-overlay.dts -new file mode 100644 -index 0000000..c06fe12 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts -@@ -0,0 +1,109 @@ -+/* -+ * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ mz61581_pins: mz61581_pins { -+ brcm,pins = <4 15 18 25>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mz61581: mz61581@0{ -+ compatible = "samsung,s6d02a1"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mz61581_pins>; -+ -+ spi-max-frequency = <128000000>; -+ spi-cpol; -+ spi-cpha; -+ -+ width = <320>; -+ height = <480>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ -+ reset-gpios = <&gpio 15 0>; -+ dc-gpios = <&gpio 25 0>; -+ led-gpios = <&gpio 18 0>; -+ -+ init = <0x10000b0 00 -+ 0x1000011 -+ 0x20000ff -+ 0x10000b3 0x02 0x00 0x00 0x00 -+ 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 -+ 0x10000c1 0x08 0x16 0x08 0x08 -+ 0x10000c4 0x11 0x07 0x03 0x03 -+ 0x10000c6 0x00 -+ 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 -+ 0x1000035 0x00 -+ 0x1000036 0xa0 -+ 0x100003a 0x55 -+ 0x1000044 0x00 0x01 -+ 0x10000d0 0x07 0x07 0x1d 0x03 -+ 0x10000d1 0x03 0x30 0x10 -+ 0x10000d2 0x03 0x14 0x04 -+ 0x1000029 -+ 0x100002c>; -+ -+ /* This is a workaround to make sure the init sequence slows down and doesn't fail */ -+ debug = <3>; -+ }; -+ -+ mz61581_ts: mz61581_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <4 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 4 0>; -+ -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&mz61581>, "spi-max-frequency:0"; -+ rotate = <&mz61581>, "rotate:0"; -+ fps = <&mz61581>, "fps:0"; -+ debug = <&mz61581>, "debug:0"; -+ xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts -new file mode 100644 -index 0000000..01fc81d ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pcf2127-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF2127 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf2127@51 { -+ compatible = "nxp,pcf2127"; -+ reg = <0x51>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts -new file mode 100644 -index 0000000..0071f62 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pcf8523-rtc-overlay.dts -@@ -0,0 +1,22 @@ -+// Definitions for PCF8523 Real Time Clock -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -new file mode 100644 -index 0000000..b7fd7ea ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -0,0 +1,94 @@ -+/* -+ * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ piscreen_pins: piscreen_pins { -+ brcm,pins = <17 25 24 22>; -+ brcm,function = <0 1 1 1>; /* in out out out */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ piscreen: piscreen@0{ -+ compatible = "ilitek,ili9486"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&piscreen_pins>; -+ -+ spi-max-frequency = <24000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ regwidth = <16>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 22 1>; -+ debug = <0>; -+ -+ init = <0x10000b0 0x00 -+ 0x1000011 -+ 0x20000ff -+ 0x100003a 0x55 -+ 0x1000036 0x28 -+ 0x10000c2 0x44 -+ 0x10000c5 0x00 0x00 0x00 0x00 -+ 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -+ 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -+ 0x1000011 -+ 0x1000029>; -+ }; -+ -+ piscreen-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <17 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 17 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&piscreen>,"spi-max-frequency:0"; -+ rotate = <&piscreen>,"rotate:0"; -+ fps = <&piscreen>,"fps:0"; -+ debug = <&piscreen>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts -new file mode 100644 -index 0000000..d506eae ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts -@@ -0,0 +1,115 @@ -+/* -+ * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pitft_pins: pitft_pins { -+ brcm,pins = <24 25>; -+ brcm,function = <0 1>; /* in out */ -+ brcm,pull = <2 0>; /* pullup none */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pitft: pitft@0{ -+ compatible = "ilitek,ili9340"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pitft_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <90>; -+ fps = <25>; -+ bgr; -+ buswidth = <8>; -+ dc-gpios = <&gpio 25 0>; -+ debug = <0>; -+ }; -+ -+ pitft_ts@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "st,stmpe610"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -+ interrupts = <24 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ interrupt-controller; -+ -+ stmpe_touchscreen { -+ compatible = "st,stmpe-ts"; -+ st,sample-time = <4>; -+ st,mod-12b = <1>; -+ st,ref-sel = <0>; -+ st,adc-freq = <2>; -+ st,ave-ctrl = <3>; -+ st,touch-det-delay = <4>; -+ st,settling = <2>; -+ st,fraction-z = <7>; -+ st,i-drive = <0>; -+ }; -+ -+ stmpe_gpio: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ /* -+ * only GPIO2 is wired/available -+ * and it is wired to the backlight -+ */ -+ st,norequest-mask = <0x7b>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/soc"; -+ __overlay__ { -+ backlight { -+ compatible = "gpio-backlight"; -+ gpios = <&stmpe_gpio 2 0>; -+ default-on; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&pitft>,"spi-max-frequency:0"; -+ rotate = <&pitft>,"rotate:0"; -+ fps = <&pitft>,"fps:0"; -+ debug = <&pitft>,"debug:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts -new file mode 100644 -index 0000000..40bf0e1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts -@@ -0,0 +1,34 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ pps: pps { -+ compatible = "pps-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pps_pins>; -+ gpios = <&gpio 18 0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ pps_pins: pps_pins { -+ brcm,pins = <18>; -+ brcm,function = <0>; // in -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&pps>,"gpios:4", -+ <&pps_pins>,"brcm,pins:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -new file mode 100644 -index 0000000..7fc6ac9 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for RPi DAC -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-dac"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ pcm1794a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm1794a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts -new file mode 100644 -index 0000000..a8fa974 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts -@@ -0,0 +1,82 @@ -+/* -+ * Device Tree overlay for rpi-display by Watterott -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ rpi_display_pins: rpi_display_pins { -+ brcm,pins = <18 23 24 25>; -+ brcm,function = <1 1 1 0>; /* out out out in */ -+ brcm,pull = <0 0 0 2>; /* - - - up */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rpidisplay: rpi-display@0{ -+ compatible = "ilitek,ili9341"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rpi_display_pins>; -+ -+ spi-max-frequency = <32000000>; -+ rotate = <270>; -+ bgr; -+ fps = <30>; -+ buswidth = <8>; -+ reset-gpios = <&gpio 23 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ }; -+ -+ rpidisplay_ts: rpi-display-ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <25 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 25 0>; -+ ti,x-plate-ohms = /bits/ 16 <60>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ speed = <&rpidisplay>,"spi-max-frequency:0"; -+ rotate = <&rpidisplay>,"rotate:0"; -+ fps = <&rpidisplay>,"fps:0"; -+ debug = <&rpidisplay>,"debug:0"; -+ xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts -new file mode 100644 -index 0000000..2029930 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for Rpi-Proto -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "rpi,rpi-proto"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ wm8731@1a { -+ #sound-dai-cells = <0>; -+ compatible = "wlf,wm8731"; -+ reg = <0x1a>; -+ status = "okay"; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -new file mode 100644 -index 0000000..b2653e9 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -@@ -0,0 +1,75 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&soc>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ sdhost: sdhost@7e202000 { -+ compatible = "brcm,bcm2835-sdhost"; -+ reg = <0x7e202000 0x100>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; -+ interrupts = <2 24>; -+ clocks = <&clk_sdhost>; -+ dmas = <&dma 13>, -+ <&dma 13>; -+ dma-names = "tx", "rx"; -+ brcm,delay-after-stop = <0>; -+ brcm,overclock-50 = <0>; -+ status = "okay"; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ clk_sdhost: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ sdhost_pins: sdhost_pins { -+ brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&mmc>; -+ __overlay__ { -+ /* Find a way to disable the other driver */ -+ compatible = ""; -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "/__overrides__"; -+ __overlay__ { -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+ }; -+ -+ __overrides__ { -+ delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -+ overclock_50 = <&sdhost>,"brcm,overclock-50:0"; -+ force_pio = <&sdhost>,"brcm,force-pio?"; -+ sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts -new file mode 100644 -index 0000000..e378ef1 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2708-spi"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts -new file mode 100644 -index 0000000..fc1e39b ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts -@@ -0,0 +1,18 @@ -+/* -+ * Device tree overlay for spi-bcm2835 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ compatible = "brcm,bcm2835-spi"; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts -new file mode 100644 -index 0000000..f7102c8 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts -@@ -0,0 +1,216 @@ -+/* -+ * tinylcd35-overlay.dts -+ * -+ * ------------------------------------------------- -+ * www.tinlylcd.com -+ * ------------------------------------------------- -+ * Device---Driver-----BUS GPIO's -+ * display tinylcd35 spi0.0 25 24 18 -+ * touch ads7846 spi0.1 5 -+ * rtc ds1307 i2c1-0068 -+ * rtc pcf8563 i2c1-0051 -+ * keypad gpio-keys --------- 17 22 27 23 28 -+ * -+ * -+ * TinyLCD.com 3.5 inch TFT -+ * -+ * Version 001 -+ * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -+ * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -+ * -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ tinylcd35_pins: tinylcd35_pins { -+ brcm,pins = <25 24 18>; -+ brcm,function = <1>; /* out */ -+ }; -+ tinylcd35_ts_pins: tinylcd35_ts_pins { -+ brcm,pins = <5>; -+ brcm,function = <0>; /* in */ -+ }; -+ keypad_pins: keypad_pins { -+ brcm,pins = <4 17 22 23 27>; -+ brcm,function = <0>; /* in */ -+ brcm,pull = <1>; /* down */ -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ tinylcd35: tinylcd35@0{ -+ compatible = "neosec,tinylcd"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&tinylcd35_pins>, -+ <&tinylcd35_ts_pins>; -+ -+ spi-max-frequency = <48000000>; -+ rotate = <270>; -+ fps = <20>; -+ bgr; -+ buswidth = <8>; -+ reset-gpios = <&gpio 25 0>; -+ dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 1>; -+ debug = <0>; -+ -+ init = <0x10000B0 0x80 -+ 0x10000C0 0x0A 0x0A -+ 0x10000C1 0x01 0x01 -+ 0x10000C2 0x33 -+ 0x10000C5 0x00 0x42 0x80 -+ 0x10000B1 0xD0 0x11 -+ 0x10000B4 0x02 -+ 0x10000B6 0x00 0x22 0x3B -+ 0x10000B7 0x07 -+ 0x1000036 0x58 -+ 0x10000F0 0x36 0xA5 0xD3 -+ 0x10000E5 0x80 -+ 0x10000E5 0x01 -+ 0x10000B3 0x00 -+ 0x10000E5 0x00 -+ 0x10000F0 0x36 0xA5 0x53 -+ 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -+ 0x100003A 0x55 -+ 0x1000011 -+ 0x2000001 -+ 0x1000029>; -+ }; -+ -+ tinylcd35_ts: tinylcd35_ts@1 { -+ compatible = "ti,ads7846"; -+ reg = <1>; -+ status = "disabled"; -+ -+ spi-max-frequency = <2000000>; -+ interrupts = <5 2>; /* high-to-low edge triggered */ -+ interrupt-parent = <&gpio>; -+ pendown-gpio = <&gpio 5 0>; -+ ti,x-plate-ohms = /bits/ 16 <100>; -+ ti,pressure-max = /bits/ 16 <255>; -+ }; -+ }; -+ }; -+ -+ /* RTC */ -+ -+ fragment@3 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pcf8563: pcf8563@51 { -+ compatible = "nxp,pcf8563"; -+ reg = <0x51>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ds1307: ds1307@68 { -+ compatible = "maxim,ds1307"; -+ reg = <0x68>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* -+ * Values for input event code is found under the -+ * 'Keys and buttons' heading in include/uapi/linux/input.h -+ */ -+ fragment@5 { -+ target-path = "/soc"; -+ __overlay__ { -+ keypad: keypad { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&keypad_pins>; -+ status = "disabled"; -+ autorepeat; -+ -+ button@17 { -+ label = "GPIO KEY_UP"; -+ linux,code = <103>; -+ gpios = <&gpio 17 0>; -+ }; -+ button@22 { -+ label = "GPIO KEY_DOWN"; -+ linux,code = <108>; -+ gpios = <&gpio 22 0>; -+ }; -+ button@27 { -+ label = "GPIO KEY_LEFT"; -+ linux,code = <105>; -+ gpios = <&gpio 27 0>; -+ }; -+ button@23 { -+ label = "GPIO KEY_RIGHT"; -+ linux,code = <106>; -+ gpios = <&gpio 23 0>; -+ }; -+ button@4 { -+ label = "GPIO KEY_ENTER"; -+ linux,code = <28>; -+ gpios = <&gpio 4 0>; -+ }; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ speed = <&tinylcd35>,"spi-max-frequency:0"; -+ rotate = <&tinylcd35>,"rotate:0"; -+ fps = <&tinylcd35>,"fps:0"; -+ debug = <&tinylcd35>,"debug:0"; -+ touch = <&tinylcd35_ts>,"status"; -+ touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -+ <&tinylcd35_ts>,"interrupts:0", -+ <&tinylcd35_ts>,"pendown-gpio:4"; -+ xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -+ rtc-pcf = <&i2c1>,"status", -+ <&pcf8563>,"status"; -+ rtc-ds = <&i2c1>,"status", -+ <&ds1307>,"status"; -+ keypad = <&keypad>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts -new file mode 100644 -index 0000000..29a3b48 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts -@@ -0,0 +1,39 @@ -+// Definitions for w1-gpio module (without external pullup) -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>; -+ rpi,parasitic-power = <0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4>; -+ brcm,function = <0>; // in (initially) -+ brcm,pull = <0>; // off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts -new file mode 100644 -index 0000000..66a98f6 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts -@@ -0,0 +1,41 @@ -+// Definitions for w1-gpio module (with external pullup) -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ -+ w1: onewire@0 { -+ compatible = "w1-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&w1_pins>; -+ gpios = <&gpio 4 0>, <&gpio 5 1>; -+ rpi,parasitic-power = <0>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ w1_pins: w1_pins { -+ brcm,pins = <4 5>; -+ brcm,function = <0 1>; // in out -+ brcm,pull = <0 0>; // off off -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ gpiopin = <&w1>,"gpios:4", -+ <&w1_pins>,"brcm,pins:0"; -+ extpullup = <&w1>,"gpios:16", -+ <&w1_pins>,"brcm,pins:4"; -+ pullup = <&w1>,"rpi,parasitic-power:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts b/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -deleted file mode 100644 -index 01fc81d..0000000 ---- a/arch/arm/boot/dts/pcf2127-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for PCF2127 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcf2127@51 { -- compatible = "nxp,pcf2127"; -- reg = <0x51>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts b/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -deleted file mode 100644 -index 0071f62..0000000 ---- a/arch/arm/boot/dts/pcf8523-rtc-overlay.dts -+++ /dev/null -@@ -1,22 +0,0 @@ --// Definitions for PCF8523 Real Time Clock --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- pcf8523@68 { -- compatible = "nxp,pcf8523"; -- reg = <0x68>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/piscreen-overlay.dts b/arch/arm/boot/dts/piscreen-overlay.dts -deleted file mode 100644 -index b7fd7ea..0000000 ---- a/arch/arm/boot/dts/piscreen-overlay.dts -+++ /dev/null -@@ -1,94 +0,0 @@ --/* -- * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- piscreen_pins: piscreen_pins { -- brcm,pins = <17 25 24 22>; -- brcm,function = <0 1 1 1>; /* in out out out */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- piscreen: piscreen@0{ -- compatible = "ilitek,ili9486"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&piscreen_pins>; -- -- spi-max-frequency = <24000000>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- regwidth = <16>; -- reset-gpios = <&gpio 25 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 22 1>; -- debug = <0>; -- -- init = <0x10000b0 0x00 -- 0x1000011 -- 0x20000ff -- 0x100003a 0x55 -- 0x1000036 0x28 -- 0x10000c2 0x44 -- 0x10000c5 0x00 0x00 0x00 0x00 -- 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 -- 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -- 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 -- 0x1000011 -- 0x1000029>; -- }; -- -- piscreen-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <17 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 17 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&piscreen>,"spi-max-frequency:0"; -- rotate = <&piscreen>,"rotate:0"; -- fps = <&piscreen>,"fps:0"; -- debug = <&piscreen>,"debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/pitft28-resistive-overlay.dts b/arch/arm/boot/dts/pitft28-resistive-overlay.dts -deleted file mode 100644 -index d506eae..0000000 ---- a/arch/arm/boot/dts/pitft28-resistive-overlay.dts -+++ /dev/null -@@ -1,115 +0,0 @@ --/* -- * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- pitft_pins: pitft_pins { -- brcm,pins = <24 25>; -- brcm,function = <0 1>; /* in out */ -- brcm,pull = <2 0>; /* pullup none */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- pitft: pitft@0{ -- compatible = "ilitek,ili9340"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pitft_pins>; -- -- spi-max-frequency = <32000000>; -- rotate = <90>; -- fps = <25>; -- bgr; -- buswidth = <8>; -- dc-gpios = <&gpio 25 0>; -- debug = <0>; -- }; -- -- pitft_ts@1 { -- #address-cells = <1>; -- #size-cells = <0>; -- compatible = "st,stmpe610"; -- reg = <1>; -- -- spi-max-frequency = <500000>; -- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ -- interrupts = <24 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- interrupt-controller; -- -- stmpe_touchscreen { -- compatible = "st,stmpe-ts"; -- st,sample-time = <4>; -- st,mod-12b = <1>; -- st,ref-sel = <0>; -- st,adc-freq = <2>; -- st,ave-ctrl = <3>; -- st,touch-det-delay = <4>; -- st,settling = <2>; -- st,fraction-z = <7>; -- st,i-drive = <0>; -- }; -- -- stmpe_gpio: stmpe_gpio { -- #gpio-cells = <2>; -- compatible = "st,stmpe-gpio"; -- /* -- * only GPIO2 is wired/available -- * and it is wired to the backlight -- */ -- st,norequest-mask = <0x7b>; -- }; -- }; -- }; -- }; -- -- fragment@3 { -- target-path = "/soc"; -- __overlay__ { -- backlight { -- compatible = "gpio-backlight"; -- gpios = <&stmpe_gpio 2 0>; -- default-on; -- }; -- }; -- }; -- -- __overrides__ { -- speed = <&pitft>,"spi-max-frequency:0"; -- rotate = <&pitft>,"rotate:0"; -- fps = <&pitft>,"fps:0"; -- debug = <&pitft>,"debug:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/pps-gpio-overlay.dts b/arch/arm/boot/dts/pps-gpio-overlay.dts -deleted file mode 100644 -index 40bf0e1..0000000 ---- a/arch/arm/boot/dts/pps-gpio-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- pps: pps { -- compatible = "pps-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pps_pins>; -- gpios = <&gpio 18 0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- pps_pins: pps_pins { -- brcm,pins = <18>; -- brcm,function = <0>; // in -- brcm,pull = <0>; // off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&pps>,"gpios:4", -- <&pps_pins>,"brcm,pins:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-dac-overlay.dts b/arch/arm/boot/dts/rpi-dac-overlay.dts -deleted file mode 100644 -index 7fc6ac9..0000000 ---- a/arch/arm/boot/dts/rpi-dac-overlay.dts -+++ /dev/null -@@ -1,34 +0,0 @@ --// Definitions for RPi DAC --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "rpi,rpi-dac"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target-path = "/"; -- __overlay__ { -- pcm1794a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm1794a"; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-display-overlay.dts b/arch/arm/boot/dts/rpi-display-overlay.dts -deleted file mode 100644 -index a8fa974..0000000 ---- a/arch/arm/boot/dts/rpi-display-overlay.dts -+++ /dev/null -@@ -1,82 +0,0 @@ --/* -- * Device Tree overlay for rpi-display by Watterott -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- rpi_display_pins: rpi_display_pins { -- brcm,pins = <18 23 24 25>; -- brcm,function = <1 1 1 0>; /* out out out in */ -- brcm,pull = <0 0 0 2>; /* - - - up */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- rpidisplay: rpi-display@0{ -- compatible = "ilitek,ili9341"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&rpi_display_pins>; -- -- spi-max-frequency = <32000000>; -- rotate = <270>; -- bgr; -- fps = <30>; -- buswidth = <8>; -- reset-gpios = <&gpio 23 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- }; -- -- rpidisplay_ts: rpi-display-ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- -- spi-max-frequency = <2000000>; -- interrupts = <25 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 25 0>; -- ti,x-plate-ohms = /bits/ 16 <60>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- __overrides__ { -- speed = <&rpidisplay>,"spi-max-frequency:0"; -- rotate = <&rpidisplay>,"rotate:0"; -- fps = <&rpidisplay>,"fps:0"; -- debug = <&rpidisplay>,"debug:0"; -- xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; -- }; --}; -diff --git a/arch/arm/boot/dts/rpi-proto-overlay.dts b/arch/arm/boot/dts/rpi-proto-overlay.dts -deleted file mode 100644 -index 2029930..0000000 ---- a/arch/arm/boot/dts/rpi-proto-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for Rpi-Proto --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&sound>; -- __overlay__ { -- compatible = "rpi,rpi-proto"; -- i2s-controller = <&i2s>; -- status = "okay"; -- }; -- }; -- -- fragment@1 { -- target = <&i2s>; -- __overlay__ { -- status = "okay"; -- }; -- }; -- -- fragment@2 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -- -- wm8731@1a { -- #sound-dai-cells = <0>; -- compatible = "wlf,wm8731"; -- reg = <0x1a>; -- status = "okay"; -- }; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts -deleted file mode 100644 -index b2653e9..0000000 ---- a/arch/arm/boot/dts/sdhost-overlay.dts -+++ /dev/null -@@ -1,75 +0,0 @@ --/dts-v1/; --/plugin/; -- --/{ -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target = <&soc>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <1>; -- -- sdhost: sdhost@7e202000 { -- compatible = "brcm,bcm2835-sdhost"; -- reg = <0x7e202000 0x100>; -- pinctrl-names = "default"; -- pinctrl-0 = <&sdhost_pins>; -- interrupts = <2 24>; -- clocks = <&clk_sdhost>; -- dmas = <&dma 13>, -- <&dma 13>; -- dma-names = "tx", "rx"; -- brcm,delay-after-stop = <0>; -- brcm,overclock-50 = <0>; -- status = "okay"; -- }; -- -- clocks { -- #address-cells = <1>; -- #size-cells = <0>; -- -- clk_sdhost: clock@3 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "sdhost"; -- clock-frequency = <250000000>; -- }; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- sdhost_pins: sdhost_pins { -- brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <4>; /* alt0 */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&mmc>; -- __overlay__ { -- /* Find a way to disable the other driver */ -- compatible = ""; -- status = "disabled"; -- }; -- }; -- -- fragment@3 { -- target-path = "/__overrides__"; -- __overlay__ { -- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -- }; -- }; -- -- __overrides__ { -- delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; -- overclock_50 = <&sdhost>,"brcm,overclock-50:0"; -- force_pio = <&sdhost>,"brcm,force-pio?"; -- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/spi-bcm2708-overlay.dts b/arch/arm/boot/dts/spi-bcm2708-overlay.dts -deleted file mode 100644 -index e378ef1..0000000 ---- a/arch/arm/boot/dts/spi-bcm2708-overlay.dts -+++ /dev/null -@@ -1,18 +0,0 @@ --/* -- * Device tree overlay for spi-bcm2835 -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -- /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- compatible = "brcm,bcm2708-spi"; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/spi-bcm2835-overlay.dts b/arch/arm/boot/dts/spi-bcm2835-overlay.dts -deleted file mode 100644 -index fc1e39b..0000000 ---- a/arch/arm/boot/dts/spi-bcm2835-overlay.dts -+++ /dev/null -@@ -1,18 +0,0 @@ --/* -- * Device tree overlay for spi-bcm2835 -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -- /* setting up compatiblity to allow loading the spi-bcm2835 driver */ -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- compatible = "brcm,bcm2835-spi"; -- }; -- }; --}; -diff --git a/arch/arm/boot/dts/tinylcd35-overlay.dts b/arch/arm/boot/dts/tinylcd35-overlay.dts -deleted file mode 100644 -index f7102c8..0000000 ---- a/arch/arm/boot/dts/tinylcd35-overlay.dts -+++ /dev/null -@@ -1,216 +0,0 @@ --/* -- * tinylcd35-overlay.dts -- * -- * ------------------------------------------------- -- * www.tinlylcd.com -- * ------------------------------------------------- -- * Device---Driver-----BUS GPIO's -- * display tinylcd35 spi0.0 25 24 18 -- * touch ads7846 spi0.1 5 -- * rtc ds1307 i2c1-0068 -- * rtc pcf8563 i2c1-0051 -- * keypad gpio-keys --------- 17 22 27 23 28 -- * -- * -- * TinyLCD.com 3.5 inch TFT -- * -- * Version 001 -- * 5/3/2015 -- Noralf Trønnes Initial Device tree framework -- * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. -- * -- */ -- --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -- -- fragment@0 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- tinylcd35_pins: tinylcd35_pins { -- brcm,pins = <25 24 18>; -- brcm,function = <1>; /* out */ -- }; -- tinylcd35_ts_pins: tinylcd35_ts_pins { -- brcm,pins = <5>; -- brcm,function = <0>; /* in */ -- }; -- keypad_pins: keypad_pins { -- brcm,pins = <4 17 22 23 27>; -- brcm,function = <0>; /* in */ -- brcm,pull = <1>; /* down */ -- }; -- }; -- }; -- -- fragment@2 { -- target = <&spi0>; -- __overlay__ { -- /* needed to avoid dtc warning */ -- #address-cells = <1>; -- #size-cells = <0>; -- -- tinylcd35: tinylcd35@0{ -- compatible = "neosec,tinylcd"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&tinylcd35_pins>, -- <&tinylcd35_ts_pins>; -- -- spi-max-frequency = <48000000>; -- rotate = <270>; -- fps = <20>; -- bgr; -- buswidth = <8>; -- reset-gpios = <&gpio 25 0>; -- dc-gpios = <&gpio 24 0>; -- led-gpios = <&gpio 18 1>; -- debug = <0>; -- -- init = <0x10000B0 0x80 -- 0x10000C0 0x0A 0x0A -- 0x10000C1 0x01 0x01 -- 0x10000C2 0x33 -- 0x10000C5 0x00 0x42 0x80 -- 0x10000B1 0xD0 0x11 -- 0x10000B4 0x02 -- 0x10000B6 0x00 0x22 0x3B -- 0x10000B7 0x07 -- 0x1000036 0x58 -- 0x10000F0 0x36 0xA5 0xD3 -- 0x10000E5 0x80 -- 0x10000E5 0x01 -- 0x10000B3 0x00 -- 0x10000E5 0x00 -- 0x10000F0 0x36 0xA5 0x53 -- 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 -- 0x100003A 0x55 -- 0x1000011 -- 0x2000001 -- 0x1000029>; -- }; -- -- tinylcd35_ts: tinylcd35_ts@1 { -- compatible = "ti,ads7846"; -- reg = <1>; -- status = "disabled"; -- -- spi-max-frequency = <2000000>; -- interrupts = <5 2>; /* high-to-low edge triggered */ -- interrupt-parent = <&gpio>; -- pendown-gpio = <&gpio 5 0>; -- ti,x-plate-ohms = /bits/ 16 <100>; -- ti,pressure-max = /bits/ 16 <255>; -- }; -- }; -- }; -- -- /* RTC */ -- -- fragment@3 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- pcf8563: pcf8563@51 { -- compatible = "nxp,pcf8563"; -- reg = <0x51>; -- status = "disabled"; -- }; -- }; -- }; -- -- fragment@4 { -- target = <&i2c1>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- ds1307: ds1307@68 { -- compatible = "maxim,ds1307"; -- reg = <0x68>; -- status = "disabled"; -- }; -- }; -- }; -- -- /* -- * Values for input event code is found under the -- * 'Keys and buttons' heading in include/uapi/linux/input.h -- */ -- fragment@5 { -- target-path = "/soc"; -- __overlay__ { -- keypad: keypad { -- compatible = "gpio-keys"; -- #address-cells = <1>; -- #size-cells = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&keypad_pins>; -- status = "disabled"; -- autorepeat; -- -- button@17 { -- label = "GPIO KEY_UP"; -- linux,code = <103>; -- gpios = <&gpio 17 0>; -- }; -- button@22 { -- label = "GPIO KEY_DOWN"; -- linux,code = <108>; -- gpios = <&gpio 22 0>; -- }; -- button@27 { -- label = "GPIO KEY_LEFT"; -- linux,code = <105>; -- gpios = <&gpio 27 0>; -- }; -- button@23 { -- label = "GPIO KEY_RIGHT"; -- linux,code = <106>; -- gpios = <&gpio 23 0>; -- }; -- button@4 { -- label = "GPIO KEY_ENTER"; -- linux,code = <28>; -- gpios = <&gpio 4 0>; -- }; -- }; -- }; -- }; -- -- __overrides__ { -- speed = <&tinylcd35>,"spi-max-frequency:0"; -- rotate = <&tinylcd35>,"rotate:0"; -- fps = <&tinylcd35>,"fps:0"; -- debug = <&tinylcd35>,"debug:0"; -- touch = <&tinylcd35_ts>,"status"; -- touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", -- <&tinylcd35_ts>,"interrupts:0", -- <&tinylcd35_ts>,"pendown-gpio:4"; -- xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; -- rtc-pcf = <&i2c1>,"status", -- <&pcf8563>,"status"; -- rtc-ds = <&i2c1>,"status", -- <&ds1307>,"status"; -- keypad = <&keypad>,"status"; -- }; --}; -diff --git a/arch/arm/boot/dts/w1-gpio-overlay.dts b/arch/arm/boot/dts/w1-gpio-overlay.dts -deleted file mode 100644 -index 29a3b48..0000000 ---- a/arch/arm/boot/dts/w1-gpio-overlay.dts -+++ /dev/null -@@ -1,39 +0,0 @@ --// Definitions for w1-gpio module (without external pullup) --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- -- w1: onewire@0 { -- compatible = "w1-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&w1_pins>; -- gpios = <&gpio 4 0>; -- rpi,parasitic-power = <0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- w1_pins: w1_pins { -- brcm,pins = <4>; -- brcm,function = <0>; // in (initially) -- brcm,pull = <0>; // off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&w1>,"gpios:4", -- <&w1_pins>,"brcm,pins:0"; -- pullup = <&w1>,"rpi,parasitic-power:0"; -- }; --}; -diff --git a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts b/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -deleted file mode 100644 -index 66a98f6..0000000 ---- a/arch/arm/boot/dts/w1-gpio-pullup-overlay.dts -+++ /dev/null -@@ -1,41 +0,0 @@ --// Definitions for w1-gpio module (with external pullup) --/dts-v1/; --/plugin/; -- --/ { -- compatible = "brcm,bcm2708"; -- -- fragment@0 { -- target-path = "/"; -- __overlay__ { -- -- w1: onewire@0 { -- compatible = "w1-gpio"; -- pinctrl-names = "default"; -- pinctrl-0 = <&w1_pins>; -- gpios = <&gpio 4 0>, <&gpio 5 1>; -- rpi,parasitic-power = <0>; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@1 { -- target = <&gpio>; -- __overlay__ { -- w1_pins: w1_pins { -- brcm,pins = <4 5>; -- brcm,function = <0 1>; // in out -- brcm,pull = <0 0>; // off off -- }; -- }; -- }; -- -- __overrides__ { -- gpiopin = <&w1>,"gpios:4", -- <&w1_pins>,"brcm,pins:0"; -- extpullup = <&w1>,"gpios:16", -- <&w1_pins>,"brcm,pins:4"; -- pullup = <&w1>,"rpi,parasitic-power:0"; -- }; --}; - -From 9c2920928cae9f7d35cb3c0e4f677b7f266a7ae3 Mon Sep 17 00:00:00 2001 -From: mwilliams03 -Date: Fri, 3 Apr 2015 12:40:10 +0000 -Subject: [PATCH 192/216] Swap X Y axis of ads7846 touchscreen controller for - PiScreen TFT - ---- - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -index b7fd7ea..be1e2ec 100644 ---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -80,6 +80,7 @@ - interrupts = <17 2>; /* high-to-low edge triggered */ - interrupt-parent = <&gpio>; - pendown-gpio = <&gpio 17 0>; -+ ti,swap-xy; - ti,x-plate-ohms = /bits/ 16 <100>; - ti,pressure-max = /bits/ 16 <255>; - }; - -From a4d119709c817d2bf6caea401b8266f55ad861c2 Mon Sep 17 00:00:00 2001 -From: mwilliams03 -Date: Wed, 8 Apr 2015 01:13:47 +0000 -Subject: [PATCH 193/216] Added optional parameter to set resistance of touch - plate(x-plate-ohms) - ---- - arch/arm/boot/dts/overlays/README | 2 ++ - arch/arm/boot/dts/overlays/piscreen-overlay.dts | 3 ++- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c260612..9d4f283 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -329,6 +329,8 @@ Params: speed Display SPI bus speed - - debug Debug output level {0-7} - -+ xohms Touchpanel sensitivity (X-plate resistance) -+ - - Name: pitft28-resistive - Info: Adafruit PiTFT 2.8" resistive touch screen -diff --git a/arch/arm/boot/dts/overlays/piscreen-overlay.dts b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -index be1e2ec..ba4ad33 100644 ---- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts -+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts -@@ -72,7 +72,7 @@ - 0x1000029>; - }; - -- piscreen-ts@1 { -+ piscreen_ts: piscreen-ts@1 { - compatible = "ti,ads7846"; - reg = <1>; - -@@ -91,5 +91,6 @@ - rotate = <&piscreen>,"rotate:0"; - fps = <&piscreen>,"fps:0"; - debug = <&piscreen>,"debug:0"; -+ xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; - }; - }; - -From df11ad948112ccee4eae40b6f4810946a8dc5019 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 28 May 2015 18:50:21 +0200 -Subject: [PATCH 194/216] BCM270x: Move vc_mem -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the vc_mem module available for ARCH_BCM2835 by moving it. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/Kconfig | 7 - - arch/arm/mach-bcm2708/Makefile | 1 - - arch/arm/mach-bcm2708/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2708/vc_mem.c | 431 ---------------------------- - arch/arm/mach-bcm2709/Kconfig | 7 - - arch/arm/mach-bcm2709/Makefile | 1 - - arch/arm/mach-bcm2709/include/mach/vc_mem.h | 35 --- - arch/arm/mach-bcm2709/vc_mem.c | 431 ---------------------------- - drivers/char/broadcom/Kconfig | 13 +- - drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_mem.c | 423 +++++++++++++++++++++++++++ - drivers/char/broadcom/vc_sm/vmcs_sm.c | 3 +- - include/linux/broadcom/vc_mem.h | 35 +++ - 13 files changed, 472 insertions(+), 951 deletions(-) - delete mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2708/vc_mem.c - delete mode 100644 arch/arm/mach-bcm2709/include/mach/vc_mem.h - delete mode 100644 arch/arm/mach-bcm2709/vc_mem.c - create mode 100644 drivers/char/broadcom/vc_mem.c - create mode 100644 include/linux/broadcom/vc_mem.h - -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index 4cfae55..68e3706 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -28,13 +28,6 @@ config BCM2708_GPIO - help - Include support for the Broadcom(R) BCM2708 gpio. - --config BCM2708_VCMEM -- bool "Videocore Memory" -- depends on MACH_BCM2708 -- default y -- help -- Helper for videocore memory access and total size allocation. -- - config BCM2708_NOL2CACHE - bool "Videocore L2 cache disable" - depends on MACH_BCM2708 -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index 5552ae8..5120994 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o --obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a338..0000000 ---- a/arch/arm/mach-bcm2708/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -deleted file mode 100644 -index 226b737..0000000 ---- a/arch/arm/mach-bcm2708/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif CONFIG_ARCH_BCM2708 --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); -diff --git a/arch/arm/mach-bcm2709/Kconfig b/arch/arm/mach-bcm2709/Kconfig -index 4fb6e1b..d61ade0 100644 ---- a/arch/arm/mach-bcm2709/Kconfig -+++ b/arch/arm/mach-bcm2709/Kconfig -@@ -25,13 +25,6 @@ config BCM2708_GPIO - help - Include support for the Broadcom(R) BCM2709 gpio. - --config BCM2708_VCMEM -- bool "Videocore Memory" -- depends on MACH_BCM2709 -- default y -- help -- Helper for videocore memory access and total size allocation. -- - config BCM2708_NOL2CACHE - bool "Videocore L2 cache disable" - depends on MACH_BCM2709 -diff --git a/arch/arm/mach-bcm2709/Makefile b/arch/arm/mach-bcm2709/Makefile -index 706116f..1ae8b80 100644 ---- a/arch/arm/mach-bcm2709/Makefile -+++ b/arch/arm/mach-bcm2709/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o --obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/arch/arm/mach-bcm2709/include/mach/vc_mem.h b/arch/arm/mach-bcm2709/include/mach/vc_mem.h -deleted file mode 100644 -index 4a4a338..0000000 ---- a/arch/arm/mach-bcm2709/include/mach/vc_mem.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#if !defined( VC_MEM_H ) --#define VC_MEM_H -- --#include -- --#define VC_MEM_IOC_MAGIC 'v' -- --#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) --#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) --#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) --#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -- --#if defined( __KERNEL__ ) --#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -- --extern unsigned long mm_vc_mem_phys_addr; --extern unsigned int mm_vc_mem_size; --extern int vc_mem_get_current_size( void ); --#endif -- --#endif /* VC_MEM_H */ -diff --git a/arch/arm/mach-bcm2709/vc_mem.c b/arch/arm/mach-bcm2709/vc_mem.c -deleted file mode 100644 -index d2adfd1..0000000 ---- a/arch/arm/mach-bcm2709/vc_mem.c -+++ /dev/null -@@ -1,431 +0,0 @@ --/***************************************************************************** --* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_KONA --#include --#elif defined(CONFIG_ARCH_BCM2708) || defined(CONFIG_ARCH_BCM2709) --#else --#include --#endif -- --#include "mach/vc_mem.h" -- --#define DRIVER_NAME "vc-mem" -- --// Device (/dev) related variables --static dev_t vc_mem_devnum = 0; --static struct class *vc_mem_class = NULL; --static struct cdev vc_mem_cdev; --static int vc_mem_inited = 0; -- --#ifdef CONFIG_DEBUG_FS --static struct dentry *vc_mem_debugfs_entry; --#endif -- --/* -- * Videocore memory addresses and size -- * -- * Drivers that wish to know the videocore memory addresses and sizes should -- * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -- * headers. This allows the other drivers to not be tied down to a a certain -- * address/size at compile time. -- * -- * In the future, the goal is to have the videocore memory virtual address and -- * size be calculated at boot time rather than at compile time. The decision of -- * where the videocore memory resides and its size would be in the hands of the -- * bootloader (and/or kernel). When that happens, the values of these variables -- * would be calculated and assigned in the init function. -- */ --// in the 2835 VC in mapped above ARM, but ARM has full access to VC space --unsigned long mm_vc_mem_phys_addr = 0x00000000; --unsigned int mm_vc_mem_size = 0; --unsigned int mm_vc_mem_base = 0; -- --EXPORT_SYMBOL(mm_vc_mem_phys_addr); --EXPORT_SYMBOL(mm_vc_mem_size); --EXPORT_SYMBOL(mm_vc_mem_base); -- --static uint phys_addr = 0; --static uint mem_size = 0; --static uint mem_base = 0; -- -- --/**************************************************************************** --* --* vc_mem_open --* --***************************************************************************/ -- --static int --vc_mem_open(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_release --* --***************************************************************************/ -- --static int --vc_mem_release(struct inode *inode, struct file *file) --{ -- (void) inode; -- (void) file; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- return 0; --} -- --/**************************************************************************** --* --* vc_mem_get_size --* --***************************************************************************/ -- --static void --vc_mem_get_size(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_base --* --***************************************************************************/ -- --static void --vc_mem_get_base(void) --{ --} -- --/**************************************************************************** --* --* vc_mem_get_current_size --* --***************************************************************************/ -- --int --vc_mem_get_current_size(void) --{ -- return mm_vc_mem_size; --} -- --EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -- --/**************************************************************************** --* --* vc_mem_ioctl --* --***************************************************************************/ -- --static long --vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) --{ -- int rc = 0; -- -- (void) cmd; -- (void) arg; -- -- pr_debug("%s: called file = 0x%p\n", __func__, file); -- -- switch (cmd) { -- case VC_MEM_IOC_MEM_PHYS_ADDR: -- { -- pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -- __func__, (void *) mm_vc_mem_phys_addr); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -- sizeof (mm_vc_mem_phys_addr)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_SIZE: -- { -- // Get the videocore memory size first -- vc_mem_get_size(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -- mm_vc_mem_size); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_size, -- sizeof (mm_vc_mem_size)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_BASE: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- case VC_MEM_IOC_MEM_LOAD: -- { -- // Get the videocore memory base -- vc_mem_get_base(); -- -- pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -- mm_vc_mem_base); -- -- if (copy_to_user((void *) arg, &mm_vc_mem_base, -- sizeof (mm_vc_mem_base)) != 0) { -- rc = -EFAULT; -- } -- break; -- } -- default: -- { -- return -ENOTTY; -- } -- } -- pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -- -- return rc; --} -- --/**************************************************************************** --* --* vc_mem_mmap --* --***************************************************************************/ -- --static int --vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) --{ -- int rc = 0; -- unsigned long length = vma->vm_end - vma->vm_start; -- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -- -- pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -- __func__, (long) vma->vm_start, (long) vma->vm_end, -- (long) vma->vm_pgoff); -- -- if (offset + length > mm_vc_mem_size) { -- pr_err("%s: length %ld is too big\n", __func__, length); -- return -EINVAL; -- } -- // Do not cache the memory map -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -- -- rc = remap_pfn_range(vma, vma->vm_start, -- (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -- vma->vm_pgoff, length, vma->vm_page_prot); -- if (rc != 0) { -- pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -- } -- -- return rc; --} -- --/**************************************************************************** --* --* File Operations for the driver. --* --***************************************************************************/ -- --static const struct file_operations vc_mem_fops = { -- .owner = THIS_MODULE, -- .open = vc_mem_open, -- .release = vc_mem_release, -- .unlocked_ioctl = vc_mem_ioctl, -- .mmap = vc_mem_mmap, --}; -- --#ifdef CONFIG_DEBUG_FS --static void vc_mem_debugfs_deinit(void) --{ -- debugfs_remove_recursive(vc_mem_debugfs_entry); -- vc_mem_debugfs_entry = NULL; --} -- -- --static int vc_mem_debugfs_init( -- struct device *dev) --{ -- vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -- if (!vc_mem_debugfs_entry) { -- dev_warn(dev, "could not create debugfs entry\n"); -- return -EFAULT; -- } -- -- if (!debugfs_create_x32("vc_mem_phys_addr", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_phys_addr)) { -- dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_size", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_size)) { -- dev_warn(dev, "%s:could not create vc_mem_size entry\n", -- __func__); -- goto fail; -- } -- -- if (!debugfs_create_x32("vc_mem_base", -- 0444, -- vc_mem_debugfs_entry, -- (u32 *)&mm_vc_mem_base)) { -- dev_warn(dev, "%s:could not create vc_mem_base entry\n", -- __func__); -- goto fail; -- } -- -- return 0; -- --fail: -- vc_mem_debugfs_deinit(); -- return -EFAULT; --} -- --#endif /* CONFIG_DEBUG_FS */ -- -- --/**************************************************************************** --* --* vc_mem_init --* --***************************************************************************/ -- --static int __init --vc_mem_init(void) --{ -- int rc = -EFAULT; -- struct device *dev; -- -- pr_debug("%s: called\n", __func__); -- -- mm_vc_mem_phys_addr = phys_addr; -- mm_vc_mem_size = mem_size; -- mm_vc_mem_base = mem_base; -- -- vc_mem_get_size(); -- -- pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -- mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -- -- if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -- pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -- __func__, rc); -- goto out_err; -- } -- -- cdev_init(&vc_mem_cdev, &vc_mem_fops); -- if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -- pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -- goto out_unregister; -- } -- -- vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -- if (IS_ERR(vc_mem_class)) { -- rc = PTR_ERR(vc_mem_class); -- pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -- goto out_cdev_del; -- } -- -- dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -- DRIVER_NAME); -- if (IS_ERR(dev)) { -- rc = PTR_ERR(dev); -- pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -- goto out_class_destroy; -- } -- --#ifdef CONFIG_DEBUG_FS -- /* don't fail if the debug entries cannot be created */ -- vc_mem_debugfs_init(dev); --#endif -- -- vc_mem_inited = 1; -- return 0; -- -- device_destroy(vc_mem_class, vc_mem_devnum); -- -- out_class_destroy: -- class_destroy(vc_mem_class); -- vc_mem_class = NULL; -- -- out_cdev_del: -- cdev_del(&vc_mem_cdev); -- -- out_unregister: -- unregister_chrdev_region(vc_mem_devnum, 1); -- -- out_err: -- return -1; --} -- --/**************************************************************************** --* --* vc_mem_exit --* --***************************************************************************/ -- --static void __exit --vc_mem_exit(void) --{ -- pr_debug("%s: called\n", __func__); -- -- if (vc_mem_inited) { --#if CONFIG_DEBUG_FS -- vc_mem_debugfs_deinit(); --#endif -- device_destroy(vc_mem_class, vc_mem_devnum); -- class_destroy(vc_mem_class); -- cdev_del(&vc_mem_cdev); -- unregister_chrdev_region(vc_mem_devnum, 1); -- } --} -- --module_init(vc_mem_init); --module_exit(vc_mem_exit); --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Broadcom Corporation"); -- --module_param(phys_addr, uint, 0644); --module_param(mem_size, uint, 0644); --module_param(mem_base, uint, 0644); -diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index fd23e00..c310d9d 100644 ---- a/drivers/char/broadcom/Kconfig -+++ b/drivers/char/broadcom/Kconfig -@@ -7,16 +7,27 @@ menuconfig BRCM_CHAR_DRIVERS - help - Broadcom's char drivers - -+if BRCM_CHAR_DRIVERS -+ - config BCM_VC_CMA - bool "Videocore CMA" -- depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ -+ depends on CMA && BCM2708_VCHIQ - default n - help - Helper for videocore CMA access. - - config BCM_VC_SM - bool "VMCS Shared Memory" -+ select BCM2708_VCMEM - default n - help - Support for the VC shared memory on the Broadcom reference - design. Uses the VCHIQ stack. -+ -+config BCM2708_VCMEM -+ bool "Videocore Memory" -+ default y -+ help -+ Helper for videocore memory access and total size allocation. -+ -+endif -diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 0bf7fdf..b4f8e39d 100644 ---- a/drivers/char/broadcom/Makefile -+++ b/drivers/char/broadcom/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ - obj-$(CONFIG_BCM_VC_SM) += vc_sm/ -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -diff --git a/drivers/char/broadcom/vc_mem.c b/drivers/char/broadcom/vc_mem.c -new file mode 100644 -index 0000000..fcde6b1 ---- /dev/null -+++ b/drivers/char/broadcom/vc_mem.c -@@ -0,0 +1,423 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "vc-mem" -+ -+// Device (/dev) related variables -+static dev_t vc_mem_devnum = 0; -+static struct class *vc_mem_class = NULL; -+static struct cdev vc_mem_cdev; -+static int vc_mem_inited = 0; -+ -+#ifdef CONFIG_DEBUG_FS -+static struct dentry *vc_mem_debugfs_entry; -+#endif -+ -+/* -+ * Videocore memory addresses and size -+ * -+ * Drivers that wish to know the videocore memory addresses and sizes should -+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in -+ * headers. This allows the other drivers to not be tied down to a a certain -+ * address/size at compile time. -+ * -+ * In the future, the goal is to have the videocore memory virtual address and -+ * size be calculated at boot time rather than at compile time. The decision of -+ * where the videocore memory resides and its size would be in the hands of the -+ * bootloader (and/or kernel). When that happens, the values of these variables -+ * would be calculated and assigned in the init function. -+ */ -+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space -+unsigned long mm_vc_mem_phys_addr = 0x00000000; -+unsigned int mm_vc_mem_size = 0; -+unsigned int mm_vc_mem_base = 0; -+ -+EXPORT_SYMBOL(mm_vc_mem_phys_addr); -+EXPORT_SYMBOL(mm_vc_mem_size); -+EXPORT_SYMBOL(mm_vc_mem_base); -+ -+static uint phys_addr = 0; -+static uint mem_size = 0; -+static uint mem_base = 0; -+ -+ -+/**************************************************************************** -+* -+* vc_mem_open -+* -+***************************************************************************/ -+ -+static int -+vc_mem_open(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_release -+* -+***************************************************************************/ -+ -+static int -+vc_mem_release(struct inode *inode, struct file *file) -+{ -+ (void) inode; -+ (void) file; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_size -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_size(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_base -+* -+***************************************************************************/ -+ -+static void -+vc_mem_get_base(void) -+{ -+} -+ -+/**************************************************************************** -+* -+* vc_mem_get_current_size -+* -+***************************************************************************/ -+ -+int -+vc_mem_get_current_size(void) -+{ -+ return mm_vc_mem_size; -+} -+ -+EXPORT_SYMBOL_GPL(vc_mem_get_current_size); -+ -+/**************************************************************************** -+* -+* vc_mem_ioctl -+* -+***************************************************************************/ -+ -+static long -+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void) cmd; -+ (void) arg; -+ -+ pr_debug("%s: called file = 0x%p\n", __func__, file); -+ -+ switch (cmd) { -+ case VC_MEM_IOC_MEM_PHYS_ADDR: -+ { -+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", -+ __func__, (void *) mm_vc_mem_phys_addr); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, -+ sizeof (mm_vc_mem_phys_addr)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_SIZE: -+ { -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, -+ mm_vc_mem_size); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_size, -+ sizeof (mm_vc_mem_size)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_BASE: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ case VC_MEM_IOC_MEM_LOAD: -+ { -+ // Get the videocore memory base -+ vc_mem_get_base(); -+ -+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, -+ mm_vc_mem_base); -+ -+ if (copy_to_user((void *) arg, &mm_vc_mem_base, -+ sizeof (mm_vc_mem_base)) != 0) { -+ rc = -EFAULT; -+ } -+ break; -+ } -+ default: -+ { -+ return -ENOTTY; -+ } -+ } -+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_mmap -+* -+***************************************************************************/ -+ -+static int -+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int rc = 0; -+ unsigned long length = vma->vm_end - vma->vm_start; -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", -+ __func__, (long) vma->vm_start, (long) vma->vm_end, -+ (long) vma->vm_pgoff); -+ -+ if (offset + length > mm_vc_mem_size) { -+ pr_err("%s: length %ld is too big\n", __func__, length); -+ return -EINVAL; -+ } -+ // Do not cache the memory map -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ rc = remap_pfn_range(vma, vma->vm_start, -+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + -+ vma->vm_pgoff, length, vma->vm_page_prot); -+ if (rc != 0) { -+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_mem_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_mem_open, -+ .release = vc_mem_release, -+ .unlocked_ioctl = vc_mem_ioctl, -+ .mmap = vc_mem_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void vc_mem_debugfs_deinit(void) -+{ -+ debugfs_remove_recursive(vc_mem_debugfs_entry); -+ vc_mem_debugfs_entry = NULL; -+} -+ -+ -+static int vc_mem_debugfs_init( -+ struct device *dev) -+{ -+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); -+ if (!vc_mem_debugfs_entry) { -+ dev_warn(dev, "could not create debugfs entry\n"); -+ return -EFAULT; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_phys_addr", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_phys_addr)) { -+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_size", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_size)) { -+ dev_warn(dev, "%s:could not create vc_mem_size entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ if (!debugfs_create_x32("vc_mem_base", -+ 0444, -+ vc_mem_debugfs_entry, -+ (u32 *)&mm_vc_mem_base)) { -+ dev_warn(dev, "%s:could not create vc_mem_base entry\n", -+ __func__); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ vc_mem_debugfs_deinit(); -+ return -EFAULT; -+} -+ -+#endif /* CONFIG_DEBUG_FS */ -+ -+ -+/**************************************************************************** -+* -+* vc_mem_init -+* -+***************************************************************************/ -+ -+static int __init -+vc_mem_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ pr_debug("%s: called\n", __func__); -+ -+ mm_vc_mem_phys_addr = phys_addr; -+ mm_vc_mem_size = mem_size; -+ mm_vc_mem_base = mem_base; -+ -+ vc_mem_get_size(); -+ -+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", -+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); -+ -+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", -+ __func__, rc); -+ goto out_err; -+ } -+ -+ cdev_init(&vc_mem_cdev, &vc_mem_fops); -+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_mem_class)) { -+ rc = PTR_ERR(vc_mem_class); -+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+#ifdef CONFIG_DEBUG_FS -+ /* don't fail if the debug entries cannot be created */ -+ vc_mem_debugfs_init(dev); -+#endif -+ -+ vc_mem_inited = 1; -+ return 0; -+ -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ -+ out_class_destroy: -+ class_destroy(vc_mem_class); -+ vc_mem_class = NULL; -+ -+ out_cdev_del: -+ cdev_del(&vc_mem_cdev); -+ -+ out_unregister: -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ -+ out_err: -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_mem_exit -+* -+***************************************************************************/ -+ -+static void __exit -+vc_mem_exit(void) -+{ -+ pr_debug("%s: called\n", __func__); -+ -+ if (vc_mem_inited) { -+#if CONFIG_DEBUG_FS -+ vc_mem_debugfs_deinit(); -+#endif -+ device_destroy(vc_mem_class, vc_mem_devnum); -+ class_destroy(vc_mem_class); -+ cdev_del(&vc_mem_cdev); -+ unregister_chrdev_region(vc_mem_devnum, 1); -+ } -+} -+ -+module_init(vc_mem_init); -+module_exit(vc_mem_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -+ -+module_param(phys_addr, uint, 0644); -+module_param(mem_size, uint, 0644); -+module_param(mem_base, uint, 0644); -diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c -index 39a8971..0bfb42e 100644 ---- a/drivers/char/broadcom/vc_sm/vmcs_sm.c -+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -15,6 +15,7 @@ - /* ---- Include Files ----------------------------------------------------- */ - - #include -+#include - #include - #include - #include -@@ -35,8 +36,6 @@ - #include - #include - --#include -- - #include "vchiq_connected.h" - #include "vc_vchi_sm.h" - -diff --git a/include/linux/broadcom/vc_mem.h b/include/linux/broadcom/vc_mem.h -new file mode 100644 -index 0000000..20a4753 ---- /dev/null -+++ b/include/linux/broadcom/vc_mem.h -@@ -0,0 +1,35 @@ -+/***************************************************************************** -+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#ifndef _VC_MEM_H -+#define _VC_MEM_H -+ -+#include -+ -+#define VC_MEM_IOC_MAGIC 'v' -+ -+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) -+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) -+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) -+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) -+ -+#if defined( __KERNEL__ ) -+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF -+ -+extern unsigned long mm_vc_mem_phys_addr; -+extern unsigned int mm_vc_mem_size; -+extern int vc_mem_get_current_size( void ); -+#endif -+ -+#endif /* _VC_MEM_H */ - -From 7495f032da212d310393adf5c4d1694190e6f309 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Mon, 1 Jun 2015 20:40:11 +0200 -Subject: [PATCH 195/216] BCM270x: Add USB controller to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to dwc_otg driver. -Add device to Device Tree. -Don't add platform devices when booting in DT mode. - -Tested on Pi1 and Pi2 with and without DT. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 8 ++++++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 7 +++++++ - 4 files changed, 17 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 3f8af85..dc7df47 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -121,6 +121,14 @@ - status = "disabled"; - }; - -+ usb: usb@7e980000 { -+ compatible = "brcm,bcm2708-usb"; -+ reg = <0x7e980000 0x10000>, -+ <0x7e006000 0x1000>; -+ interrupts = <2 0>, -+ <1 9>; -+ }; -+ - leds: leds { - compatible = "gpio-leds"; - }; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 06438df..6298309 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -955,7 +955,7 @@ void __init bcm2708_init(void) - #endif - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); -- bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device_dt(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ce06b7d..d8c2336 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -978,7 +978,7 @@ void __init bcm2709_init(void) - bcm_register_device(&bcm2708_systemtimer_device); - #endif - bcm_register_device_dt(&bcm2708_fb_device); -- bcm_register_device(&bcm2708_usb_device); -+ bcm_register_device_dt(&bcm2708_usb_device); - bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index dc7cd32..53307f0 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -1043,9 +1043,16 @@ static struct platform_device_id platform_ids[] = { - }; - MODULE_DEVICE_TABLE(platform, platform_ids); - -+static const struct of_device_id dwc_otg_of_match_table[] = { -+ { .compatible = "brcm,bcm2708-usb", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, dwc_otg_of_match_table); -+ - static struct platform_driver dwc_otg_driver = { - .driver = { - .name = (char *)dwc_driver_name, -+ .of_match_table = dwc_otg_of_match_table, - }, - .id_table = platform_ids, - - -From da5345649e7ad4deb51692d4d969ba4a2f86974b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 2 Mar 2015 17:57:30 +0000 -Subject: [PATCH 196/216] added mcp251x module to list of modules to get - compiled as well as the corresponding overlay - ---- - arch/arm/boot/dts/Makefile | 2 +- - arch/arm/boot/dts/overlays/Makefile | 1 + - .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 69 ++++++++++++++++++++++ - arch/arm/configs/bcm2709_defconfig | 5 ++ - arch/arm/configs/bcmrpi_defconfig | 8 +++ - 5 files changed, 84 insertions(+), 1 deletion(-) - create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ea93e1d..d5b6a82 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -1,9 +1,9 @@ - ifeq ($(CONFIG_OF),y) - - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb --dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb - dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb -+dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb - - # Raspberry Pi - ifeq ($(CONFIG_BCM2708_DT),y) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index d64e6b4..d18a1f2 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -22,6 +22,7 @@ dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb -+dtb-$(RPI_DT_OVERLAYS) += mcp2515-can0-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb -diff --git a/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts -new file mode 100755 -index 0000000..398d59c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts -@@ -0,0 +1,69 @@ -+/* -+ * Device tree overlay for mcp251x/can0 on spi0.0 -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; -+ /* disable spi-dev for spi0.0 */ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ spidev@0{ -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ /* the interrupt pin of the can-controller */ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ can0_pins: can0_pins { -+ brcm,pins = <25>; -+ brcm,function = <0>; /* input */ -+ }; -+ }; -+ }; -+ -+ /* the clock/oscillator of the can-controller */ -+ fragment@2 { -+ target-path = "/clocks"; -+ __overlay__ { -+ /* external oscillator of mcp2515 on SPI0.0 */ -+ can0_osc: can0_osc { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <16000000>; -+ }; -+ }; -+ }; -+ -+ /* the spi config of the can-controller itself binding everything together */ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ can0: mcp2515@0 { -+ reg = <0>; -+ compatible = "microchip,mcp2515"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&can0_pins>; -+ spi-max-frequency = <10000000>; -+ interrupt-parent = <&gpio>; -+ interrupts = <25 0x2>; -+ clocks = <&can0_osc>; -+ }; -+ }; -+ }; -+ __overrides__ { -+ oscillator = <&can0_osc>,"clock-frequency:0"; -+ spimaxfrequency = <&can0>,"spi-max-frequency:0"; -+ interrupt = <&can0_pins>,"brcm,pins:0",<&can0>,"interrupts:0"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 5ce9a01..2a1a15a 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -344,7 +344,12 @@ CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m -+CONFIG_CAN_RAW=m -+CONFIG_CAN_BCM=m -+CONFIG_CAN_GW=m - CONFIG_CAN_VCAN=m -+CONFIG_CAN_DEV=m -+CONFIG_CAN_CALC_BITTIMING=y - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index da443da..a2d7291 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -335,6 +335,14 @@ CONFIG_6PACK=m - CONFIG_BPQETHER=m - CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m -+CONFIG_CAN=m -+CONFIG_CAN_RAW=m -+CONFIG_CAN_BCM=m -+CONFIG_CAN_GW=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_DEV=m -+CONFIG_CAN_CALC_BITTIMING=y -+CONFIG_CAN_MCP251X=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m - -From 8e999dc420b342d1304fc2bcd755ab6a36d6896c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 13:55:05 +0200 -Subject: [PATCH 197/216] BCM270x: Move thermal sensor to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add Device Tree support to bcm2835-thermal driver. -Add thermal sensor device to Device Tree. -Don't add platform device when booting in DT mode. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 4 ++++ - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - drivers/thermal/bcm2835-thermal.c | 8 +++++++- - 4 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index dc7df47..fcb5828 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -143,6 +143,10 @@ - reg = <0x7e00b840 0xf>; - interrupts = <0 2>; - }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ }; - }; - - clocks { -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6298309..e141c0b 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -984,7 +984,7 @@ void __init bcm2708_init(void) - } - - bcm_register_device(&bcm2835_hwmon_device); -- bcm_register_device(&bcm2835_thermal_device); -+ bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) - bcm_register_device_dt(&bcm2708_i2s_device); -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d8c2336..6dadb80 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1007,7 +1007,7 @@ void __init bcm2709_init(void) - } - - bcm_register_device(&bcm2835_hwmon_device); -- bcm_register_device(&bcm2835_thermal_device); -+ bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) - bcm_register_device_dt(&bcm2708_i2s_device); -diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c -index 0c556d1..3bc80f1 100644 ---- a/drivers/thermal/bcm2835-thermal.c -+++ b/drivers/thermal/bcm2835-thermal.c -@@ -167,13 +167,19 @@ static struct thermal_zone_device_ops ops = { - .get_mode = bcm2835_get_mode, - }; - --/* Thermal Driver */ -+static const struct of_device_id bcm2835_thermal_of_match_table[] = { -+ { .compatible = "brcm,bcm2835-thermal", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); -+ - static struct platform_driver bcm2835_thermal_driver = { - .probe = bcm2835_thermal_probe, - .remove = bcm2835_thermal_remove, - .driver = { - .name = "bcm2835_thermal", - .owner = THIS_MODULE, -+ .of_match_table = bcm2835_thermal_of_match_table, - }, - }; - - -From fd724791a4d515e8069884b72f52752501ee0f92 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 13:55:22 +0200 -Subject: [PATCH 198/216] bcm2835: Add thermal sensor to Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add the BCM2835 thermal sensor to Device Tree. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index 40fc759..efaf4df 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -170,6 +170,10 @@ - reg = <0x7e00b840 0xf>; - interrupts = <0 2>; - }; -+ -+ thermal: thermal { -+ compatible = "brcm,bcm2835-thermal"; -+ }; - }; - - clocks { - -From 34638ffefe49111b137c8b0927c47f9aab23215b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 15:51:24 +0200 -Subject: [PATCH 199/216] BCM270x: Enable bcm2835_wdt and bcm2835-rng -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Change the kconfig dependency to make bcm2835_wdt and bcm2835-rng -available on ARCH_BCM2708 and ARCH_BCM2709. -Enable them as loadable modules in bcmrpi_defconfig and -bcm2709_defconfig. - -There is a commit in linux-next that will move restart/pm_power_off -to bcm2835_wdt for ARCH_BCM2835. This will not affect ARCH_BCM270x -since arm_pm_restart (.restart = bcm2708_restart) and -pm_power_off (=bcm2708_power_off) is set in -arch/arm/mach-bcm270X/bcm270X.c and will take presedence. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - drivers/char/hw_random/Kconfig | 2 +- - drivers/watchdog/Kconfig | 2 +- - 4 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 2a1a15a..d08ae51 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -561,6 +561,7 @@ CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y - CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m - CONFIG_HW_RANDOM_BCM2708=m - CONFIG_RAW_DRIVER=y - CONFIG_BRCM_CHAR_DRIVERS=y -@@ -603,6 +604,7 @@ CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y - CONFIG_BCM2708_WDT=m -+CONFIG_BCM2835_WDT=m - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index a2d7291..11bbfac 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -557,6 +557,7 @@ CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y - CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m - CONFIG_HW_RANDOM_BCM2708=m - CONFIG_RAW_DRIVER=y - CONFIG_BRCM_CHAR_DRIVERS=y -@@ -599,6 +600,7 @@ CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y - CONFIG_BCM2708_WDT=m -+CONFIG_BCM2835_WDT=m - CONFIG_UCB1400_CORE=m - CONFIG_MFD_STMPE=y - CONFIG_STMPE_SPI=y -diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 1c97093..0996083 100644 ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX - - config HW_RANDOM_BCM2835 - tristate "Broadcom BCM2835 Random Number Generator support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index ca7d6463..e010420 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1222,7 +1222,7 @@ config BCM63XX_WDT - - config BCM2835_WDT - tristate "Broadcom BCM2835 hardware watchdog" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select WATCHDOG_CORE - help - Watchdog driver for the built in watchdog hardware in Broadcom - -From 6779bd793d41be8d73ee771b149606e13e13e0b7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 2 Jun 2015 15:51:52 +0200 -Subject: [PATCH 200/216] BCM270X_DT: Add bcm2835-pm-wdt and bcm2835-rng -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This makes it possible to use the mainline watchdog and -random generator drivers: -dtparam=watchdog=on -dtparam=random=on - -bcm2708_wdog and bcm2708-rng can still be used. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 12 ++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 4 files changed, 18 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 75df21c..52b1404 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -124,5 +124,7 @@ - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index df12b7d..876dfca 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -114,5 +114,7 @@ - act_led_trigger = <&act_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index fcb5828..a80b1a8 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -43,6 +43,18 @@ - #interrupt-cells = <2>; - }; - -+ watchdog: watchdog@7e100000 { -+ compatible = "brcm,bcm2835-pm-wdt"; -+ reg = <0x7e100000 0x28>; -+ status = "disabled"; -+ }; -+ -+ random: rng@7e104000 { -+ compatible = "brcm,bcm2835-rng"; -+ reg = <0x7e104000 0x10>; -+ status = "disabled"; -+ }; -+ - mailbox: mailbox@7e00b800 { - compatible = "brcm,bcm2708-vcio"; - reg = <0x7e00b880 0x40>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 78bc756..b226dfb 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -124,5 +124,7 @@ - pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - - audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; - }; - }; - -From 493b7b5c56b4afd21bd980e38deb0f9d7d06061c Mon Sep 17 00:00:00 2001 +From 070a6f51cd5f81f635cfcccd3452ee5f252a7ee4 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 201/216] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 73/77] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -153634,3120 +134261,186 @@ index 70f2f39..f7fdacd 100644 static const char * const bcm2835_compat[] = { -From e98419e0f836f39ae77a595f0d7218ba4b0576ab Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:34:24 +0200 -Subject: [PATCH 202/216] bcm2835: Match BCM270X Device Trees -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 45 +++++++++++------ - arch/arm/boot/dts/bcm2835-rpi-b.dts | 29 +++++++---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 85 +++++++++++++++++++++++++------- - arch/arm/boot/dts/bcm2835.dtsi | 12 ++--- - 4 files changed, 122 insertions(+), 49 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -index e479515..b0fb0e8 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts -@@ -4,27 +4,40 @@ - / { - compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; - model = "Raspberry Pi Model B+"; -+}; -+ -+&gpio { -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; - -- leds { -- act { -- gpios = <&gpio 47 0>; -- }; -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+&act_led { -+ gpios = <&gpio 47 0>; -+}; - -- pwr { -- label = "PWR"; -- gpios = <&gpio 35 0>; -- default-state = "keep"; -- linux,default-trigger = "default-on"; -- }; -+&leds { -+ pwr_led: pwr { -+ label = "led1"; -+ linux,default-trigger = "input"; -+ gpios = <&gpio 35 0>; - }; - }; - --&gpio { -- pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; - -- /* I2S interface */ -- i2s_alt0: i2s_alt0 { -- brcm,pins = <18 19 20 21>; -- brcm,function = <4>; /* alt0 */ -+ pwr_led_gpio = <&pwr_led>,"gpios:4"; -+ pwr_led_activelow = <&pwr_led>,"gpios:8"; -+ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts -index bafa46f..b867224 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts -@@ -5,19 +5,28 @@ - compatible = "raspberrypi,model-b", "brcm,bcm2835"; - model = "Raspberry Pi Model B"; - -- leds { -- act { -- gpios = <&gpio 16 1>; -- }; -- }; - }; - - &gpio { -- pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; -- -- /* I2S interface */ -- i2s_alt2: i2s_alt2 { -+ i2s_pins: i2s { - brcm,pins = <28 29 30 31>; -- brcm,function = <6>; /* alt2 */ -+ brcm,function = <4>; /* alt0 */ -+ }; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+&act_led { -+ gpios = <&gpio 16 1>; -+}; -+ -+/ { -+ __overrides__ { -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index f23835e..466f02b 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -1,17 +1,29 @@ - /include/ "bcm2835.dtsi" - - / { -+ /* This is left here in case u-boot needs it */ - memory { - reg = <0 0x10000000>; - }; - -- leds { -+ aliases { -+ soc = &soc; -+ spi0 = &spi0; -+ i2c0 = &i2c0; -+ i2c1 = &i2c1; -+ i2s = &i2s; -+ gpio = &gpio; -+ intc = &intc; -+ leds = &leds; -+ sound = &sound; -+ }; -+ -+ leds: leds { - compatible = "gpio-leds"; - -- act { -- label = "ACT"; -- default-state = "keep"; -- linux,default-trigger = "heartbeat"; -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; - }; - }; - -@@ -19,35 +31,61 @@ - audio: audio { - compatible = "brcm,bcm2835-audio"; - brcm,pwm-channels = <8>; -+ status = "disabled"; -+ }; -+ -+ /* External sound card */ -+ sound: sound { - }; - }; - - &gpio { -- pinctrl-names = "default"; -+ spi0_pins: spi0_pins { -+ brcm,pins = <7 8 9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; - -- gpioout: gpioout { -- brcm,pins = <6>; -- brcm,function = <1>; /* GPIO out */ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; - }; - -- alt0: alt0 { -- brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; -- brcm,function = <4>; /* alt0 */ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; - }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; - -- alt3: alt3 { -- brcm,pins = <48 49 50 51 52 53>; -- brcm,function = <7>; /* alt3 */ -+ spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; - }; - }; - - &i2c0 { -- status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; - clock-frequency = <100000>; - }; - - &i2c1 { -- status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; - clock-frequency = <100000>; - }; - -@@ -59,3 +97,16 @@ - &fb { - status = "okay"; - }; -+ -+/ { -+ __overrides__ { -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ audio = <&audio>,"status"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi -index efaf4df..4b6dd65f 100644 ---- a/arch/arm/boot/dts/bcm2835.dtsi -+++ b/arch/arm/boot/dts/bcm2835.dtsi -@@ -9,7 +9,7 @@ - bootargs = ""; - }; - -- soc { -+ soc: soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; -@@ -51,12 +51,12 @@ - #interrupt-cells = <2>; - }; - -- watchdog@7e100000 { -+ watchdog: watchdog@7e100000 { - compatible = "brcm,bcm2835-pm-wdt"; - reg = <0x7e100000 0x28>; - }; - -- rng@7e104000 { -+ random: rng@7e104000 { - compatible = "brcm,bcm2835-rng"; - reg = <0x7e104000 0x10>; - }; -@@ -90,7 +90,7 @@ - #interrupt-cells = <2>; - }; - -- uart@7e201000 { -+ uart0: uart@7e201000 { - compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; - reg = <0x7e201000 0x1000>; - interrupts = <2 25>; -@@ -109,7 +109,7 @@ - status = "disabled"; - }; - -- spi: spi@7e204000 { -+ spi0: spi@7e204000 { - compatible = "brcm,bcm2835-spi"; - reg = <0x7e204000 0x1000>; - interrupts = <2 22>; -@@ -150,7 +150,7 @@ - status = "disabled"; - }; - -- usb@7e980000 { -+ usb: usb@7e980000 { - compatible = "brcm,bcm2835-usb"; - reg = <0x7e980000 0x10000>; - interrupts = <1 9>; - -From 3ac358b4ca8e0b71da28992689669218e0dbbacf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:35:11 +0200 -Subject: [PATCH 203/216] dts: Enable overlays on ARCH_BCM2835 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Build Device Tree overlays on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 3 +++ - arch/arm/boot/dts/overlays/Makefile | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index d5b6a82..e7ce7c4 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -12,6 +12,9 @@ endif - ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif - - subdir-$(RPI_DT_OVERLAYS) += overlays - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index d18a1f2..c449c3f 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -8,6 +8,9 @@ endif - ifeq ($(CONFIG_BCM2709_DT),y) - RPI_DT_OVERLAYS=y - endif -+ifeq ($(CONFIG_ARCH_BCM2835),y) -+ RPI_DT_OVERLAYS=y -+endif - - dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb - dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb - -From 6c6321340ea33c79dbfb15441ad58db03ec94167 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:35:55 +0200 -Subject: [PATCH 204/216] bcm2835: Make camera and sound drivers available -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Change kconfig dependency to make SND_BCM2708_SOC_* and -VIDEO_BCM2835 available on ARCH_BCM2835. - -Signed-off-by: Noralf Trønnes ---- - drivers/media/platform/bcm2835/Kconfig | 2 +- - sound/soc/bcm/Kconfig | 14 +++++++------- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig -index 2cb1a68..99a5cbc 100644 ---- a/drivers/media/platform/bcm2835/Kconfig -+++ b/drivers/media/platform/bcm2835/Kconfig -@@ -2,7 +2,7 @@ - - config VIDEO_BCM2835 - bool "Broadcom BCM2835 camera interface driver" -- depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709) -+ depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) - ---help--- - Say Y here to enable camera host interface devices for - Broadcom BCM2835 SoC. This operates over the VCHIQ interface -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 003ae28..516ab9d 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -21,49 +21,49 @@ config SND_BCM2708_SOC_I2S - - config SND_BCM2708_SOC_HIFIBERRY_DAC - tristate "Support for HifiBerry DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM5102A - help - Say Y or M if you want to add support for HifiBerry DAC. - - config SND_BCM2708_SOC_HIFIBERRY_DACPLUS - tristate "Support for HifiBerry DAC+" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM512x - help - Say Y or M if you want to add support for HifiBerry DAC+. - - config SND_BCM2708_SOC_HIFIBERRY_DIGI - tristate "Support for HifiBerry Digi" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_WM8804 - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - - config SND_BCM2708_SOC_HIFIBERRY_AMP - tristate "Support for the HifiBerry Amp" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_TAS5713 - help - Say Y or M if you want to add support for the HifiBerry Amp amplifier board. - - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. - - config SND_BCM2708_SOC_RPI_PROTO - tristate "Support for Rpi-PROTO" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_WM8731 - help - Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). - - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" -- depends on SND_BCM2708_SOC_I2S -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S - select SND_SOC_PCM512x_I2C - help - Say Y or M if you want to add support for IQaudIO-DAC. - -From b5b5fa6e2a877089b48daaaac9b135c95c71e24f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Wed, 3 Jun 2015 12:36:19 +0200 -Subject: [PATCH 205/216] bcm2835: Merge bcm2835_defconfig with - bcmrpi_defconfig -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These commands where used to make this commit: - -./scripts/diffconfig -m arch/arm/configs/bcm2835_defconfig arch/arm/configs/bcmrpi_defconfig > merge.cfg - -cat << EOF > filter -CONFIG_ARCH_BCM2708 -CONFIG_BCM2708_DT -CONFIG_ARM_PATCH_PHYS_VIRT -CONFIG_PHYS_OFFSET -CONFIG_CMDLINE -CONFIG_BCM2708_WDT -CONFIG_HW_RANDOM_BCM2708 -CONFIG_I2C_BCM2708 -CONFIG_SPI_BCM2708 -CONFIG_SND_BCM2708_SOC_I2S -CONFIG_USB_DWCOTG -CONFIG_LIRC_RPI -EOF - -grep -F -v -f filter merge.cfg > filtered.cfg - -cat << EOF > added.cfg -CONFIG_WATCHDOG=y -CONFIG_BCM2835_WDT=y -CONFIG_MISC_FILESYSTEMS=y -CONFIG_SND_BCM2835_SOC_I2S=m -EOF - -ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2835_defconfig filtered.cfg added.cfg -ARCH=arm make oldconfig - -ARCH=arm make savedefconfig -cp defconfig arch/arm/configs/bcm2835_defconfig - -rm merge.cfg filter filtered.cfg added.cfg defconfig - -ARCH=arm make bcm2835_defconfig -ARCH=arm make oldconfig - -Signed-off-by: Noralf Trønnes ---- - arch/arm/configs/bcm2835_defconfig | 1114 +++++++++++++++++++++++++++++++++++- - 1 file changed, 1097 insertions(+), 17 deletions(-) - -diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig -index 1af6069..2e8a95a 100644 ---- a/arch/arm/configs/bcm2835_defconfig -+++ b/arch/arm/configs/bcm2835_defconfig -@@ -1,107 +1,1071 @@ - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y - CONFIG_FHANDLE=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y - CONFIG_BSD_PROCESS_ACCT=y - CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_IKCONFIG=m -+CONFIG_IKCONFIG_PROC=y - CONFIG_LOG_BUF_SHIFT=18 - CONFIG_CGROUP_FREEZER=y - CONFIG_CGROUP_DEVICE=y - CONFIG_CPUSETS=y - CONFIG_CGROUP_CPUACCT=y -+CONFIG_MEMCG=y - CONFIG_CGROUP_PERF=y - CONFIG_CFS_BANDWIDTH=y - CONFIG_RT_GROUP_SCHED=y -+CONFIG_BLK_CGROUP=y - CONFIG_NAMESPACES=y - CONFIG_SCHED_AUTOGROUP=y --CONFIG_RELAY=y - CONFIG_BLK_DEV_INITRD=y - CONFIG_CC_OPTIMIZE_FOR_SIZE=y --CONFIG_KALLSYMS_ALL=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_PROFILING=y --CONFIG_OPROFILE=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y - CONFIG_JUMP_LABEL=y - CONFIG_CC_STACKPROTECTOR_REGULAR=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_MULTI_V6=y - # CONFIG_ARCH_MULTI_V7 is not set - CONFIG_ARCH_BCM=y - CONFIG_ARCH_BCM2835=y --CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_PREEMPT=y - CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y - CONFIG_KSM=y - CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_CMA=y -+CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_KEXEC=y - CONFIG_CRASH_DUMP=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=m -+CONFIG_CPU_FREQ_STAT_DETAILS=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_VFP=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+CONFIG_BINFMT_MISC=m - # CONFIG_SUSPEND is not set - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m - CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_LRO=m -+CONFIG_INET_DIAG=m -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_TUNNEL=m -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y - CONFIG_NETWORK_SECMARK=y - CONFIG_NETFILTER=y --CONFIG_CFG80211=y --CONFIG_MAC80211=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=m -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+CONFIG_IP_SET=m -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_IPTABLES=m -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_FILTER=m -+CONFIG_IP_NF_TARGET_REJECT=m -+CONFIG_IP_NF_NAT=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_IP_NF_RAW=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_NF_CONNTRACK_IPV6=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_NAT=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+CONFIG_BRIDGE=m -+CONFIG_VLAN_8021Q=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_ATALK=m -+CONFIG_6LOWPAN=m -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_CGROUP=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_U32=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m -+CONFIG_OPENVSWITCH=m -+CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m -+CONFIG_CAN=m -+CONFIG_CAN_VCAN=m -+CONFIG_CAN_MCP251X=m -+CONFIG_IRDA=m -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+CONFIG_IRDA_ULTRA=y -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_USB_IRDA=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_BT=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+CONFIG_BT_6LOWPAN=m -+CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_MAC80211=m -+CONFIG_MAC80211_MESH=y -+CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_NFC_PN533=m - CONFIG_DEVTMPFS=y - CONFIG_DEVTMPFS_MOUNT=y - # CONFIG_STANDALONE is not set -+CONFIG_DMA_CMA=y -+CONFIG_CMA_SIZE_MBYTES=5 -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_ATA_OVER_ETH=m -+CONFIG_EEPROM_AT24=m - CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_CHR_DEV_SG=m - CONFIG_SCSI_CONSTANTS=y - CONFIG_SCSI_SCAN_ASYNC=y -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+CONFIG_MD=y -+CONFIG_MD_LINEAR=m -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_RAID=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m - CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_DUMMY=m -+CONFIG_IFB=m -+CONFIG_MACVLAN=m -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_ENC28J60=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOATM=m -+CONFIG_PPPOE=m -+CONFIG_PPPOL2TP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m - CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SR9800=m -+CONFIG_USB_NET_SMSC75XX=m - CONFIG_USB_NET_SMSC95XX=y --CONFIG_ZD1211RW=y --CONFIG_INPUT_EVDEV=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_AT76C50X_USB=m -+CONFIG_USB_ZD1201=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_RTL8187=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_ATH_CARDS=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_USB=m -+CONFIG_AR5523=m -+CONFIG_B43=m -+# CONFIG_B43_PHY_N is not set -+CONFIG_B43LEGACY=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_USB=y -+CONFIG_HOSTAP=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RTL8192CU=m -+CONFIG_ZD1211RW=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_WIMAX_I2400M_USB=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_JOYDEV=m -+CONFIG_INPUT_EVDEV=m -+# CONFIG_KEYBOARD_ATKBD is not set -+CONFIG_KEYBOARD_GPIO=m -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_ADS7846=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+CONFIG_TOUCHSCREEN_STMPE=m -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+CONFIG_INPUT_ADXL34X=m -+CONFIG_INPUT_CMA3000=m -+CONFIG_SERIO=m -+CONFIG_SERIO_RAW=m -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y - # CONFIG_LEGACY_PTYS is not set - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_BCM2835=m -+CONFIG_RAW_DRIVER=y -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y -+CONFIG_BCM_VC_SM=y - CONFIG_I2C=y --CONFIG_I2C_CHARDEV=y -+CONFIG_I2C_CHARDEV=m - CONFIG_I2C_BCM2835=y - CONFIG_SPI=y --CONFIG_SPI_BCM2835=y -+CONFIG_SPI_BCM2835=m -+CONFIG_SPI_SPIDEV=y -+CONFIG_PPS=m -+CONFIG_PPS_CLIENT_LDISC=m -+CONFIG_PPS_CLIENT_GPIO=m - CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_ARIZONA=m -+CONFIG_GPIO_STMPE=y -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2406=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+CONFIG_BATTERY_DS2760=m - # CONFIG_HWMON is not set -+CONFIG_THERMAL=y -+CONFIG_THERMAL_BCM2835=y -+CONFIG_WATCHDOG=y -+CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m -+CONFIG_MFD_STMPE=y -+CONFIG_STMPE_SPI=y -+CONFIG_MFD_ARIZONA_I2C=m -+CONFIG_MFD_ARIZONA_SPI=m -+CONFIG_MFD_WM5102=y -+CONFIG_MEDIA_SUPPORT=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_DTCS033=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SE401=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_VIDEO_USBTV=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_GO7007=m -+CONFIG_VIDEO_GO7007_USB=m -+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_DVB_USB=m -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_DVBSKY=m -+CONFIG_SMS_USB_DRV=m -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_DVB_AS102=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+CONFIG_I2C_SI4713=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -+CONFIG_VIDEO_UDA1342=m -+CONFIG_VIDEO_SONY_BTF_MPX=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TW2804=m -+CONFIG_VIDEO_TW9903=m -+CONFIG_VIDEO_TW9906=m -+CONFIG_VIDEO_OV7640=m -+CONFIG_VIDEO_MT9V011=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+CONFIG_FB_SSD1307=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_GPIO=m - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+CONFIG_SND=m -+CONFIG_SND_SEQUENCER=m -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_HRTIMER=m -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_BCM2835_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m -+CONFIG_SND_SIMPLE_CARD=m -+CONFIG_SOUND_PRIME=m -+CONFIG_HIDRAW=y -+CONFIG_HID_A4TECH=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_APPLE=m -+CONFIG_HID_BELKIN=m -+CONFIG_HID_CHERRY=m -+CONFIG_HID_CHICONY=m -+CONFIG_HID_CYPRESS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_EZKEY=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_KYE=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_KENSINGTON=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LOGITECH=m -+CONFIG_HID_MAGICMOUSE=m -+CONFIG_HID_MICROSOFT=m -+CONFIG_HID_MONTEREY=m -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_WACOM=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y - CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=m -+CONFIG_USB_PRINTER=m - CONFIG_USB_STORAGE=y -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_USBAT=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_ENE_UB6250=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_USBIP_CORE=m -+CONFIG_USBIP_VHCI_HCD=m -+CONFIG_USBIP_HOST=m - CONFIG_USB_DWC2=y -+CONFIG_USB_SERIAL=m -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_EMPEG=m -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_PL2303=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_WISHBONE=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_EMI62=m -+CONFIG_USB_EMI26=m -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_RIO500=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_LCD=m -+CONFIG_USB_LED=m -+CONFIG_USB_CYPRESS_CY7C63=m -+CONFIG_USB_CYTHERM=m -+CONFIG_USB_IDMOUSE=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_APPLEDISPLAY=m -+CONFIG_USB_LD=m -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_TEST=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_ATM=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_CXACRU=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m - CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - CONFIG_MMC_BCM2835_DMA=y -+CONFIG_MMC_BCM2835_SDHOST=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2835=y --CONFIG_NEW_LEDS=y -+CONFIG_MMC_SPI=m - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_GPIO=y --CONFIG_LEDS_TRIGGERS=y - CONFIG_LEDS_TRIGGER_TIMER=y - CONFIG_LEDS_TRIGGER_ONESHOT=y - CONFIG_LEDS_TRIGGER_HEARTBEAT=y -+CONFIG_LEDS_TRIGGER_BACKLIGHT=y - CONFIG_LEDS_TRIGGER_CPU=y - CONFIG_LEDS_TRIGGER_GPIO=y - CONFIG_LEDS_TRIGGER_DEFAULT_ON=y --CONFIG_LEDS_TRIGGER_TRANSIENT=y --CONFIG_LEDS_TRIGGER_CAMERA=y -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_TRIGGER_INPUT=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1374=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_MAX6900=m -+CONFIG_RTC_DRV_RS5C372=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_ISL12022=m -+CONFIG_RTC_DRV_ISL12057=m -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_PCF8523=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_S35390A=m -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_RTC_DRV_M41T93=m -+CONFIG_RTC_DRV_M41T94=m -+CONFIG_RTC_DRV_DS1305=m -+CONFIG_RTC_DRV_DS1390=m -+CONFIG_RTC_DRV_MAX6902=m -+CONFIG_RTC_DRV_R9701=m -+CONFIG_RTC_DRV_RS5C348=m -+CONFIG_RTC_DRV_DS3234=m -+CONFIG_RTC_DRV_PCF2123=m -+CONFIG_RTC_DRV_RX4581=m - CONFIG_DMADEVICES=y - CONFIG_DMA_BCM2708=y -+CONFIG_UIO=m -+CONFIG_UIO_PDRV_GENIRQ=m - CONFIG_STAGING=y -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_R8188EU=m -+CONFIG_R8723AU=m -+CONFIG_VT6656=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_FB_TFT=m -+CONFIG_FB_TFT_AGM1264K_FL=m -+CONFIG_FB_TFT_BD663474=m -+CONFIG_FB_TFT_HX8340BN=m -+CONFIG_FB_TFT_HX8347D=m -+CONFIG_FB_TFT_HX8353D=m -+CONFIG_FB_TFT_ILI9320=m -+CONFIG_FB_TFT_ILI9325=m -+CONFIG_FB_TFT_ILI9340=m -+CONFIG_FB_TFT_ILI9341=m -+CONFIG_FB_TFT_ILI9481=m -+CONFIG_FB_TFT_ILI9486=m -+CONFIG_FB_TFT_PCD8544=m -+CONFIG_FB_TFT_RA8875=m -+CONFIG_FB_TFT_S6D02A1=m -+CONFIG_FB_TFT_S6D1121=m -+CONFIG_FB_TFT_SSD1289=m -+CONFIG_FB_TFT_SSD1306=m -+CONFIG_FB_TFT_SSD1331=m -+CONFIG_FB_TFT_SSD1351=m -+CONFIG_FB_TFT_ST7735R=m -+CONFIG_FB_TFT_TINYLCD=m -+CONFIG_FB_TFT_TLS8204=m -+CONFIG_FB_TFT_UC1701=m -+CONFIG_FB_TFT_UPD161704=m -+CONFIG_FB_TFT_WATTEROTT=m -+CONFIG_FB_FLEX=m -+CONFIG_FB_TFT_FBTFT_DEVICE=m - CONFIG_MAILBOX=y - CONFIG_BCM2708_MBOX=y - # CONFIG_IOMMU_SUPPORT is not set -+CONFIG_EXTCON=m -+CONFIG_EXTCON_ARIZONA=m - CONFIG_EXT2_FS=y - CONFIG_EXT2_FS_XATTR=y - CONFIG_EXT2_FS_POSIX_ACL=y -@@ -109,18 +1073,110 @@ CONFIG_EXT3_FS=y - CONFIG_EXT3_FS_POSIX_ACL=y - CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_JFS_STATISTICS=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m - CONFIG_FANOTIFY=y -+CONFIG_QFMT_V1=m -+CONFIG_QFMT_V2=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_FSCACHE=y -+CONFIG_FSCACHE_STATS=y -+CONFIG_FSCACHE_HISTOGRAM=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y --# CONFIG_MISC_FILESYSTEMS is not set -+CONFIG_CONFIGFS_FS=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_F2FS_FS=y - CONFIG_NFS_FS=y --CONFIG_NFSD=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_NFS_SWAP=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" - CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m - CONFIG_NLS_ASCII=y --CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m - CONFIG_NLS_UTF8=y -+CONFIG_DLM=m - CONFIG_PRINTK_TIME=y - CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_DYNAMIC_DEBUG=y -@@ -130,14 +1186,38 @@ CONFIG_DEBUG_INFO=y - CONFIG_UNUSED_SYMBOLS=y - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_LOCKUP_DETECTOR=y -+CONFIG_TIMER_STATS=y -+# CONFIG_DEBUG_PREEMPT is not set -+CONFIG_LATENCYTOP=y -+CONFIG_IRQSOFF_TRACER=y - CONFIG_SCHED_TRACER=y - CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set - CONFIG_FUNCTION_PROFILER=y - CONFIG_TEST_KSTRTOX=y - CONFIG_KGDB=y - CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y - CONFIG_STRICT_DEVMEM=y - CONFIG_DEBUG_LL=y - CONFIG_EARLY_PRINTK=y -+CONFIG_CRYPTO_USER=m -+CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=m -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_SHA1_ARM=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_AES_ARM=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+# CONFIG_CRYPTO_HW is not set -+CONFIG_CRC_ITU_T=y -+CONFIG_LIBCRC32C=y - # CONFIG_XZ_DEC_ARM is not set - # CONFIG_XZ_DEC_ARMTHUMB is not set - -From c712b42d06623b5410a3921f71278963a9a45209 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 24 Mar 2015 16:57:04 +0000 -Subject: [PATCH 206/216] BCM270x_DT: Configure UART using DT - -See: https://github.com/raspberrypi/firmware/issues/393 ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 7 +++++++ - arch/arm/boot/dts/bcm2708_common.dtsi | 27 +++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 7 +++++++ - arch/arm/mach-bcm2708/bcm2708.c | 9 +++++---- - arch/arm/mach-bcm2709/bcm2709.c | 9 +++++---- - 6 files changed, 58 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 52b1404..99ab3c9 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -108,6 +113,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 876dfca..e8c80cd 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -102,6 +107,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a80b1a8..a09a3c7 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -84,6 +84,17 @@ - status = "disabled"; - }; - -+ uart0: uart@7e201000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x7e201000 0x1000>; -+ interrupts = <2 25>; -+ clocks = <&clk_uart0 &clk_apb_p>; -+ clock-names = "uartclk","apb_pclk"; -+ arm,primecell-periphid = <0x00241011>; // For an explanation, see -+ // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 -+ status = "disabled"; -+ }; -+ - i2s: i2s@7e203000 { - compatible = "brcm,bcm2708-i2s"; - reg = <0x7e203000 0x20>, -@@ -188,5 +199,21 @@ - clock-output-names = "spi"; - clock-frequency = <250000000>; - }; -+ -+ clk_uart0: clock@3 { -+ compatible = "fixed-clock"; -+ reg = <3>; -+ #clock-cells = <0>; -+ clock-output-names = "uart0_pclk"; -+ clock-frequency = <3000000>; -+ }; -+ -+ clk_apb_p: clock@4 { -+ compatible = "fixed-clock"; -+ reg = <4>; -+ #clock-cells = <0>; -+ clock-output-names = "apb_pclk"; -+ clock-frequency = <126000000>; -+ }; - }; - }; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index b226dfb..39b6fd4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -16,6 +16,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -@@ -53,6 +54,10 @@ - status = "okay"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_pins>; -@@ -108,6 +113,8 @@ - - / { - __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; - i2s = <&i2s>,"status"; - spi = <&spi0>,"status"; - i2c0 = <&i2c0>,"status"; -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e141c0b..e17c1de 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -1020,10 +1020,11 @@ void __init bcm2708_init(void) - i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); - #endif - -- -- for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -- struct amba_device *d = amba_devs[i]; -- amba_device_register(d, &iomem_resource); -+ if (!use_dt) { -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); -+ } - } - system_rev = boardrev; - system_serial_low = serial; -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 6dadb80..8834a10 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1043,10 +1043,11 @@ void __init bcm2709_init(void) - i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); - #endif - -- -- for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -- struct amba_device *d = amba_devs[i]; -- amba_device_register(d, &iomem_resource); -+ if (!use_dt) { -+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { -+ struct amba_device *d = amba_devs[i]; -+ amba_device_register(d, &iomem_resource); -+ } - } - system_rev = boardrev; - system_serial_low = serial; - -From aa05d1fe61d794be63d7e6055881e36c33cdb09c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 4 Jun 2015 16:16:08 +0100 -Subject: [PATCH 207/216] vchiq_arm: ARCH_BCM2835 compatibility - -Use virt_to_dma (not ideal, I know) to calculate the virt-to-bus -offset. This will make use of the "dma-ranges" property, if -present. ---- - drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 660aad2..c739083 100644 ---- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -46,7 +46,7 @@ - - #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - --#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x)) -+#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) - - #include "vchiq_arm.h" - #include "vchiq_2835.h" -@@ -66,7 +66,8 @@ typedef struct vchiq_2835_state_struct { - static void __iomem *g_regs; - static FRAGMENTS_T *g_fragments_base; - static FRAGMENTS_T *g_free_fragments; --struct semaphore g_free_fragments_sema; -+static struct semaphore g_free_fragments_sema; -+static unsigned long g_virt_to_bus_offset; - - extern int vchiq_arm_log_level; - -@@ -92,6 +93,8 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) - int slot_mem_size, frag_mem_size; - int err, irq, i; - -+ g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); -+ - /* Allocate space for the channels in coherent memory */ - slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); - frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); - -From fa0a4bff157dddc6207cba9911a1581864cf2307 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Jun 2015 14:00:54 +0100 -Subject: [PATCH 208/216] BCM270x_DT: Enable UART in the example Compute Module - DTS as well +From 3add74da14e27d18ef276f66c55a69e6dc014216 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 16 Jun 2015 17:47:27 +0100 +Subject: [PATCH 74/77] platform: Add force_core command line setting to boot + from a different core number --- - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 11 +++++++++++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 3 ++- - 3 files changed, 14 insertions(+), 1 deletion(-) + arch/arm/mach-bcm2709/armctrl.c | 17 ++++++++++++++++- + arch/arm/mach-bcm2709/bcm2709.c | 2 ++ + 2 files changed, 18 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -index 45f8244..238bd65 100755 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -5,3 +5,14 @@ - / { - model = "Raspberry Pi Compute Module"; - }; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+/ { -+ __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 1c2cfcf..43830a6 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -11,6 +11,7 @@ - intc = &intc; - leds = &leds; - sound = &sound; -+ uart0 = &uart0; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a09a3c7..dc0346b 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -185,10 +185,11 @@ - clock-frequency = <250000000>; - }; - -- clk_i2c: i2c { -+ clk_i2c: clock@1 { - compatible = "fixed-clock"; - reg = <1>; - #clock-cells = <0>; -+ clock-output-names = "i2c"; - clock-frequency = <250000000>; - }; - - -From fae583caba82c37f9a1e0cff81fbaa4c3f768657 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Jun 2015 15:59:08 +0100 -Subject: [PATCH 209/216] bcm270x defconfigs: Remove spurious entries - ---- - arch/arm/configs/bcm2709_defconfig | 5 ----- - arch/arm/configs/bcmrpi_defconfig | 8 -------- - 2 files changed, 13 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index d08ae51..78e1202 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -344,12 +344,7 @@ CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m --CONFIG_CAN_RAW=m --CONFIG_CAN_BCM=m --CONFIG_CAN_GW=m - CONFIG_CAN_VCAN=m --CONFIG_CAN_DEV=m --CONFIG_CAN_CALC_BITTIMING=y - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 11bbfac..c6a5db2 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -335,14 +335,6 @@ CONFIG_6PACK=m - CONFIG_BPQETHER=m - CONFIG_BAYCOM_SER_FDX=m - CONFIG_BAYCOM_SER_HDX=m --CONFIG_CAN=m --CONFIG_CAN_RAW=m --CONFIG_CAN_BCM=m --CONFIG_CAN_GW=m --CONFIG_CAN_VCAN=m --CONFIG_CAN_DEV=m --CONFIG_CAN_CALC_BITTIMING=y --CONFIG_CAN_MCP251X=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m - -From 549ff9d4fee2f6dc0abdeaa552754ce2197ba331 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 09:00:01 +0100 -Subject: [PATCH 210/216] BCM270x_DT: Add a label to the clocks node, and a few - aliases - ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 2 ++ - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 2 ++ - arch/arm/boot/dts/bcm2708_common.dtsi | 2 +- - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 2 ++ - 5 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 99ab3c9..c9053f8 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e8c80cd..32066c3 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index 43830a6..f38a0c2 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -10,8 +10,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index dc0346b..a9f1507 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -172,7 +172,7 @@ - }; - }; - -- clocks { -+ clocks: clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 39b6fd4..a9adaf4 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -15,8 +15,10 @@ - gpio = &gpio; - intc = &intc; - leds = &leds; -+ audio = &audio; - sound = &sound; - uart0 = &uart0; -+ clocks = &clocks; - }; - - sound: sound { - -From 1b8bcc8ef9b600f7ac5e4d40bd70b507ad02aa01 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 May 2015 09:01:02 +0100 -Subject: [PATCH 211/216] sdhost-overlay: Move clock declaration out of /soc - ---- - arch/arm/boot/dts/overlays/sdhost-overlay.dts | 29 +++++++++++++++------------ - 1 file changed, 16 insertions(+), 13 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -index b2653e9..8fb28e9 100644 ---- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts -+++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts -@@ -24,23 +24,26 @@ - brcm,overclock-50 = <0>; - status = "okay"; - }; -+ }; -+ }; - -- clocks { -- #address-cells = <1>; -- #size-cells = <0>; -+ fragment@1 { -+ target = <&clocks>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; - -- clk_sdhost: clock@3 { -- compatible = "fixed-clock"; -- reg = <0>; -- #clock-cells = <0>; -- clock-output-names = "sdhost"; -- clock-frequency = <250000000>; -- }; -+ clk_sdhost: sdhost { -+ compatible = "fixed-clock"; -+ reg = <0>; -+ #clock-cells = <0>; -+ clock-output-names = "sdhost"; -+ clock-frequency = <250000000>; - }; - }; - }; - -- fragment@1 { -+ fragment@2 { - target = <&gpio>; - __overlay__ { - sdhost_pins: sdhost_pins { -@@ -50,7 +53,7 @@ - }; - }; - -- fragment@2 { -+ fragment@3 { - target = <&mmc>; - __overlay__ { - /* Find a way to disable the other driver */ -@@ -59,7 +62,7 @@ - }; - }; - -- fragment@3 { -+ fragment@4 { - target-path = "/__overrides__"; - __overlay__ { - sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; - -From 24d8164a16fb825c4bee4a8cca87f55a68f33edf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 6 Jun 2015 23:45:32 +0200 -Subject: [PATCH 212/216] BCM270X_DT: Enable 'make clean' on overlays directory -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Always add the overlays directory to subdir so it can be -cleaned with 'make clean'. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index e7ce7c4..d85583c 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -16,8 +16,6 @@ ifeq ($(CONFIG_ARCH_BCM2835),y) - RPI_DT_OVERLAYS=y - endif - --subdir-$(RPI_DT_OVERLAYS) += overlays -- - dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb - # Keep at91 dtb files sorted alphabetically for each SoC -@@ -676,3 +674,5 @@ clean-files := *.dtb - ifeq ($(RPI_DT_OVERLAYS),y) - DTC_FLAGS ?= -@ - endif -+ -+subdir-y += overlays - -From 2b53c727bbb2ba40102236f127ea6e68b1148335 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 13:35:33 +0200 -Subject: [PATCH 213/216] hwmon: Remove bcm2835-hwmon -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -bcm2835-thermal combined with the configs HWMON=y and -THERMAL_HWMON=y, gives the same functionality. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 5 - - arch/arm/mach-bcm2709/bcm2709.c | 5 - - drivers/hwmon/Kconfig | 10 -- - drivers/hwmon/Makefile | 1 - - drivers/hwmon/bcm2835-hwmon.c | 219 ---------------------------------------- - 5 files changed, 240 deletions(-) - delete mode 100644 drivers/hwmon/bcm2835-hwmon.c - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e17c1de..4f191d9 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -697,10 +697,6 @@ static struct platform_device bcm2708_bsc1_device = { - .resource = bcm2708_bsc1_resources, +diff --git a/arch/arm/mach-bcm2709/armctrl.c b/arch/arm/mach-bcm2709/armctrl.c +index a366275..90805a6 100644 +--- a/arch/arm/mach-bcm2709/armctrl.c ++++ b/arch/arm/mach-bcm2709/armctrl.c +@@ -45,6 +45,8 @@ static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { + INTERRUPT_VC_ARASANSDIO }; --static struct platform_device bcm2835_hwmon_device = { -- .name = "bcm2835_hwmon", --}; -- - static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; -@@ -983,7 +979,6 @@ void __init bcm2708_init(void) - bcm_register_device_dt(&bcm2708_bsc1_device); - } - -- bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8834a10..d61bb30 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -718,10 +718,6 @@ static struct platform_device bcm2708_bsc1_device = { - .resource = bcm2708_bsc1_resources, - }; - --static struct platform_device bcm2835_hwmon_device = { -- .name = "bcm2835_hwmon", --}; -- - static struct platform_device bcm2835_thermal_device = { - .name = "bcm2835_thermal", - }; -@@ -1006,7 +1002,6 @@ void __init bcm2709_init(void) - bcm_register_device_dt(&bcm2708_bsc1_device); - } - -- bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device_dt(&bcm2835_thermal_device); - - #if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 8c4474d..110fade 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -1703,16 +1703,6 @@ config SENSORS_ULTRA45 - This driver provides support for the Ultra45 workstation environmental - sensors. - --config SENSORS_BCM2835 -- depends on THERMAL_BCM2835=n -- tristate "Broadcom BCM2835 HWMON Driver" -- help -- If you say yes here you get support for the hardware -- monitoring features of the BCM2835 Chip -- -- This driver can also be built as a module. If so, the module -- will be called bcm2835-hwmon. -- - if ACPI - - comment "ACPI drivers" -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index e7c60cb..6c94147 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -155,7 +155,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o - obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o - obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o - obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o --obj-$(CONFIG_SENSORS_BCM2835) += bcm2835-hwmon.o - - obj-$(CONFIG_PMBUS) += pmbus/ - -diff --git a/drivers/hwmon/bcm2835-hwmon.c b/drivers/hwmon/bcm2835-hwmon.c -deleted file mode 100644 -index d14502c..0000000 ---- a/drivers/hwmon/bcm2835-hwmon.c -+++ /dev/null -@@ -1,219 +0,0 @@ --/***************************************************************************** --* Copyright 2011 Broadcom Corporation. All rights reserved. --* --* Unless you and Broadcom execute a separate written software license --* agreement governing use of this software, this software is licensed to you --* under the terms of the GNU General Public License version 2, available at --* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). --* --* Notwithstanding the above, under no circumstances may you combine this --* software in any way with any other Broadcom software provided under a --* license other than the GPL, without Broadcom's express prior written --* consent. --*****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define MODULE_NAME "bcm2835_hwmon" -- --/*#define HWMON_DEBUG_ENABLE*/ -- --#ifdef HWMON_DEBUG_ENABLE --#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__) --#else --#define print_debug(fmt,...) --#endif --#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__) --#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__) -- --#define VC_TAG_GET_TEMP 0x00030006 --#define VC_TAG_GET_MAX_TEMP 0x0003000A -- --/* --- STRUCTS --- */ --struct bcm2835_hwmon_data { -- struct device *hwmon_dev; --}; -- --/* tag part of the message */ --struct vc_msg_tag { -- uint32_t tag_id; /* the tag ID for the temperature */ -- uint32_t buffer_size; /* size of the buffer (should be 8) */ -- uint32_t request_code; /* identifies message as a request (should be 0) */ -- uint32_t id; /* extra ID field (should be 0) */ -- uint32_t val; /* returned value of the temperature */ --}; -- --/* message structure to be sent to videocore */ --struct vc_msg { -- uint32_t msg_size; /* simply, sizeof(struct vc_msg) */ -- uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */ -- struct vc_msg_tag tag; /* the tag structure above to make */ -- uint32_t end_tag; /* an end identifier, should be set to NULL */ --}; -- --typedef enum { -- TEMP, -- MAX_TEMP, --} temp_type; -- --/* --- PROTOTYPES --- */ --static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf); --static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf); -- --/* --- GLOBALS --- */ -- --static struct bcm2835_hwmon_data *bcm2835_data; --static struct platform_driver bcm2835_hwmon_driver; -- --static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0); --static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP); --static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP); -- --static struct attribute* bcm2835_attributes[] = { -- &sensor_dev_attr_name.dev_attr.attr, -- &sensor_dev_attr_temp1_input.dev_attr.attr, -- &sensor_dev_attr_temp1_max.dev_attr.attr, -- NULL, --}; -- --static struct attribute_group bcm2835_attr_group = { -- .attrs = bcm2835_attributes, --}; -- --/* --- FUNCTIONS --- */ -- --static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf) --{ -- return sprintf(buf,"bcm2835_hwmon\n"); --} -- --static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf) --{ -- struct vc_msg msg; -- int result; -- uint temp = 0; -- int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index; -- -- print_debug("IN"); -- -- /* wipe all previous message data */ -- memset(&msg, 0, sizeof msg); -- -- /* determine the message type */ -- if(index == TEMP) -- msg.tag.tag_id = VC_TAG_GET_TEMP; -- else if (index == MAX_TEMP) -- msg.tag.tag_id = VC_TAG_GET_MAX_TEMP; -- else -- { -- print_debug("Unknown temperature message!"); -- return -EINVAL; -- } -- -- msg.msg_size = sizeof msg; -- msg.tag.buffer_size = 8; -- -- /* send the message */ -- result = bcm_mailbox_property(&msg, sizeof msg); -- -- /* check if it was all ok and return the rate in milli degrees C */ -- if (result == 0 && (msg.request_code & 0x80000000)) -- temp = (uint)msg.tag.val; -- #ifdef HWMON_DEBUG_ENABLE -- else -- print_debug("Failed to get temperature!"); -- #endif -- print_debug("Got temperature as %u",temp); -- print_debug("OUT"); -- return sprintf(buf, "%u\n", temp); --} -- -- --static int bcm2835_hwmon_probe(struct platform_device *pdev) --{ -- int err; -- -- print_debug("IN"); -- print_debug("HWMON Driver has been probed!"); -- -- /* check that the device isn't null!*/ -- if(pdev == NULL) -- { -- print_debug("Platform device is empty!"); -- return -ENODEV; -- } -- -- /* allocate memory for neccessary data */ -- bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL); -- if(!bcm2835_data) -- { -- print_debug("Unable to allocate memory for hwmon data!"); -- err = -ENOMEM; -- goto kzalloc_error; -- } -- -- /* create the sysfs files */ -- if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group)) -- { -- print_debug("Unable to create sysfs files!"); -- err = -EFAULT; -- goto sysfs_error; -- } -- -- /* register the hwmon device */ -- bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev); -- if (IS_ERR(bcm2835_data->hwmon_dev)) -- { -- err = PTR_ERR(bcm2835_data->hwmon_dev); -- goto hwmon_error; -- } -- print_debug("OUT"); -- return 0; -- -- /* error goto's */ -- hwmon_error: -- sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -- -- sysfs_error: -- kfree(bcm2835_data); -- -- kzalloc_error: -- -- return err; -- --} -- --static int bcm2835_hwmon_remove(struct platform_device *pdev) --{ -- print_debug("IN"); -- hwmon_device_unregister(bcm2835_data->hwmon_dev); -- -- sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group); -- print_debug("OUT"); -- return 0; --} -- --/* Hwmon Driver */ --static struct platform_driver bcm2835_hwmon_driver = { -- .probe = bcm2835_hwmon_probe, -- .remove = bcm2835_hwmon_remove, -- .driver = { -- .name = "bcm2835_hwmon", -- .owner = THIS_MODULE, -- }, --}; -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Dorian Peake"); --MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip"); -- --module_platform_driver(bcm2835_hwmon_driver); - -From a4573f4e07996b61582f828189091bede1296d25 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 6 Jun 2015 22:59:28 +0200 -Subject: [PATCH 214/216] BCM270x: Make uart1 work with Device Tree -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add uart1 to Device Tree. Enable it in AUXENB when it's used. -Remove old platform device. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + - arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 1 + - arch/arm/boot/dts/bcm2708_common.dtsi | 10 +++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + - arch/arm/mach-bcm2708/bcm2708.c | 35 +++++++++++--------------------- - arch/arm/mach-bcm2709/bcm2709.c | 34 +++++++++++-------------------- - 7 files changed, 38 insertions(+), 45 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index c9053f8..0fa2210 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 32066c3..3fd49d0 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -index f38a0c2..3da7d3b 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -13,6 +13,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index a9f1507..8caa234 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -134,6 +134,16 @@ - status = "disabled"; - }; - -+ uart1: uart@7e215040 { -+ compatible = "brcm,bcm2835-aux-uart", "ns16550"; -+ reg = <0x7e215040 0x40>; -+ interrupts = <1 29>; -+ clock-frequency = <500000000>; -+ reg-shift = <2>; -+ no-loopback-test; -+ status = "disabled"; -+ }; ++extern unsigned force_core; + - i2c1: i2c@7e804000 { - compatible = "brcm,bcm2708-i2c"; - reg = <0x7e804000 0x1000>; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index a9adaf4..8aaaf1f 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -18,6 +18,7 @@ - audio = &audio; - sound = &sound; - uart0 = &uart0; -+ uart1 = &uart1; - clocks = &clocks; - }; - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 4f191d9..f1706366 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -353,28 +353,6 @@ static struct platform_device bcm2708_fb_device = { - }, - }; - --static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -- { -- .mapbase = UART1_BASE + 0x40, -- .irq = IRQ_AUX, -- .uartclk = 500000000, -- .regshift = 2, -- .iotype = UPIO_MEM, -- .flags = UPF_SHARE_IRQ | UPF_FIXED_TYPE | UPF_FIXED_PORT | -- UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_16550, -- }, -- {}, --}; -- --static struct platform_device bcm2708_uart1_device = { -- .name = "serial8250", -- .id = PLAT8250_DEV_PLATFORM, -- .dev = { -- .platform_data = bcm2708_uart1_platform_data, -- }, --}; -- - static struct resource bcm2708_usb_resources[] = { - [0] = { - .start = USB_BASE, -@@ -897,6 +875,17 @@ static void bcm2708_power_off(void) - } - } - -+static void __init bcm2708_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2708: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ - #ifdef CONFIG_OF - static void __init bcm2708_dt_init(void) + static void armctrl_mask_irq(struct irq_data *d) { -@@ -952,13 +941,13 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); + static const unsigned int disables[4] = { +@@ -92,7 +94,13 @@ static void armctrl_unmask_irq(struct irq_data *d) + int i; + if (d->irq >= FIQ_START) { + unsigned int data; +- if (num_online_cpus() > 1) { ++ if (force_core) { ++ data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ data &= ~0xc; ++ data |= ((force_core-1) << 2); ++ writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ } ++ else if (num_online_cpus() > 1) { + data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); + data &= ~0xc; + data |= (1 << 2); +@@ -119,6 +127,13 @@ static void armctrl_unmask_irq(struct irq_data *d) + } #endif - bcm2708_init_led(); -+ bcm2708_init_uart1(); - - /* Only create the platform devices for the ALSA driver in the - absence of an enabled "audio" DT node */ + } else if (d->irq >= ARM_IRQ1_BASE && d->irq < ARM_IRQ_LOCAL_BASE) { ++ if (force_core) { ++ unsigned int data; ++ data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ data &= ~0x3; ++ data |= ((force_core-1) << 0); ++ writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); ++ } + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); + } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index d61bb30..ffa667e 100644 +index 507ff52..c5e51e8 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -363,27 +363,6 @@ static struct platform_device bcm2708_fb_device = { - }, - }; +@@ -96,6 +96,7 @@ static unsigned w1_gpio_pin = W1_GPIO; + static unsigned w1_gpio_pullup = W1_PULLUP; + static bool vc_i2c_override = false; + static int pps_gpio_pin = -1; ++unsigned force_core; --static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { -- { -- .mapbase = UART1_BASE + 0x40, -- .irq = IRQ_AUX, -- .uartclk = 125000000, -- .regshift = 2, -- .iotype = UPIO_MEM, -- .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, -- .type = PORT_8250, -- }, -- {}, --}; -- --static struct platform_device bcm2708_uart1_device = { -- .name = "serial8250", -- .id = PLAT8250_DEV_PLATFORM, -- .dev = { -- .platform_data = bcm2708_uart1_platform_data, -- }, --}; -- - static struct resource bcm2708_usb_resources[] = { - [0] = { - .start = USB_BASE, -@@ -918,6 +897,17 @@ static void bcm2709_power_off(void) + static unsigned use_dt = 0; + +@@ -1305,6 +1306,7 @@ MACHINE_START(BCM2708, "BCM2709") + .dt_compat = bcm2709_compat, + MACHINE_END + ++module_param(force_core, uint, 0644); + module_param(boardrev, uint, 0644); + module_param(serial, uint, 0644); + module_param(uart_clock, uint, 0644); + +From a283be0c98260b1f29c8c46df7e8fb2a9cdaf5a8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jun 2015 17:46:17 +0100 +Subject: [PATCH 75/77] mach-bcm270x: Enable the building of pinctrl-bcm2835 + +--- + drivers/pinctrl/Makefile | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index 6eadf04..ca6e1be 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o + ++obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ + obj-$(CONFIG_ARCH_BCM) += bcm/ + obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-y += freescale/ + +From fd08db11f15960c30449a5a2cb14d3ab7fd470ea Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jun 2015 18:06:28 +0100 +Subject: [PATCH 76/77] squash: Fix inconsistency in pinctrl Makefile patch + +--- + drivers/pinctrl/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index ca6e1be..9119513 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -38,7 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o + +-obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ ++obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += bcm/ + obj-$(CONFIG_ARCH_BCM) += bcm/ + obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-y += freescale/ + +From 05376fce25aaab4f47182a5af04928bfa06f30d6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Jun 2015 19:53:58 +0100 +Subject: [PATCH 77/77] platform: squash: Remove IRQF_DISABLED + +--- + arch/arm/mach-bcm2708/armctrl.c | 2 +- + arch/arm/mach-bcm2708/bcm2708.c | 2 +- + arch/arm/mach-bcm2708/bcm2708_gpio.c | 2 +- + arch/arm/mach-bcm2709/bcm2709.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c +index 74bacb3..0429225 100644 +--- a/arch/arm/mach-bcm2708/armctrl.c ++++ b/arch/arm/mach-bcm2708/armctrl.c +@@ -305,7 +305,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); +- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - } -+static void __init bcm2709_init_uart1(void) -+{ -+ struct device_node *np; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); -+ if (of_device_is_available(np)) { -+ pr_info("bcm2709: Mini UART enabled\n"); -+ writel(1, __io_address(UART1_BASE + 0x4)); -+ } -+} -+ - #ifdef CONFIG_OF - static void __init bcm2709_dt_init(void) - { -@@ -975,13 +965,13 @@ void __init bcm2709_init(void) - #endif - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_uart1_device); - bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); - #endif - bcm2709_init_led(); -+ bcm2709_init_uart1(); - - /* Only create the platform devices for the ALSA driver in the - absence of an enabled "audio" DT node */ - -From 31c0f40b228b657d4c8968c32768992a3bbcefb6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 20:42:35 +0200 -Subject: [PATCH 215/216] fixup: BCM2709: Remove unused clock implementation - ---- - arch/arm/mach-bcm2709/clock.c | 61 ------------------------------------------- - arch/arm/mach-bcm2709/clock.h | 24 ----------------- - 2 files changed, 85 deletions(-) - delete mode 100644 arch/arm/mach-bcm2709/clock.c - delete mode 100644 arch/arm/mach-bcm2709/clock.h - -diff --git a/arch/arm/mach-bcm2709/clock.c b/arch/arm/mach-bcm2709/clock.c -deleted file mode 100644 -index 4fc556e..0000000 ---- a/arch/arm/mach-bcm2709/clock.c -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.c -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "clock.h" -- --int clk_enable(struct clk *clk) --{ -- return 0; --} --EXPORT_SYMBOL(clk_enable); -- --void clk_disable(struct clk *clk) --{ --} --EXPORT_SYMBOL(clk_disable); -- --unsigned long clk_get_rate(struct clk *clk) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_get_rate); -- --long clk_round_rate(struct clk *clk, unsigned long rate) --{ -- return clk->rate; --} --EXPORT_SYMBOL(clk_round_rate); -- --int clk_set_rate(struct clk *clk, unsigned long rate) --{ -- return -EIO; --} --EXPORT_SYMBOL(clk_set_rate); -diff --git a/arch/arm/mach-bcm2709/clock.h b/arch/arm/mach-bcm2709/clock.h -deleted file mode 100644 -index 5f9d725..0000000 ---- a/arch/arm/mach-bcm2709/clock.h -+++ /dev/null -@@ -1,24 +0,0 @@ --/* -- * linux/arch/arm/mach-bcm2708/clock.h -- * -- * Copyright (C) 2010 Broadcom -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ --struct module; -- --struct clk { -- unsigned long rate; --}; - -From 6ae9c7a93909159bde1a92fd305e99443e4ac680 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sun, 7 Jun 2015 20:42:52 +0200 -Subject: [PATCH 216/216] BCM270x: Remove bcm2708_systemtimer and - bcm2708_powerman -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These devices do not have a matching driver. - -Signed-off-by: Noralf Trønnes ---- - arch/arm/mach-bcm2708/bcm2708.c | 50 -------------------------------------- - arch/arm/mach-bcm2709/bcm2709.c | 54 ----------------------------------------- - 2 files changed, 104 deletions(-) - + armctrl_pm_register(base, irq_start, resume_sources); diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f1706366..00fc5d6 100644 +index cfc4f13..937c2d3 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -465,33 +465,6 @@ static struct platform_device bcm2708_gpio_device = { +@@ -1028,7 +1028,7 @@ static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, }; - #endif --static struct resource bcm2708_systemtimer_resources[] = { -- [0] = { /* system timer access */ -- .start = ST_BASE, -- .end = ST_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -- { -- .start = IRQ_TIMER3, -- .end = IRQ_TIMER3, -- .flags = IORESOURCE_IRQ, -- } -- --}; -- --static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --static struct platform_device bcm2708_systemtimer_device = { -- .name = "bcm2708_systemtimer", -- .id = -1, /* only one VideoCore I/O area */ -- .resource = bcm2708_systemtimer_resources, -- .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -- .dev = { -- .dma_mask = &systemtimer_dmamask, -- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -- }, --}; -- - #ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ - static struct resource bcm2835_emmc_resources[] = { - [0] = { -@@ -520,27 +493,6 @@ struct platform_device bcm2835_emmc_device = { +diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c +index c1e9254..e33265d 100644 +--- a/arch/arm/mach-bcm2708/bcm2708_gpio.c ++++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c +@@ -306,7 +306,7 @@ static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, }; - #endif /* CONFIG_MMC_BCM2835 */ --static struct resource bcm2708_powerman_resources[] = { -- [0] = { -- .start = PM_BASE, -- .end = PM_BASE + SZ_256 - 1, -- .flags = IORESOURCE_MEM, -- }, --}; -- --static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --struct platform_device bcm2708_powerman_device = { -- .name = "bcm2708_powerman", -- .id = 0, -- .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -- .resource = bcm2708_powerman_resources, -- .dev = { -- .dma_mask = &powerman_dmamask, -- .coherent_dma_mask = 0xffffffffUL}, --}; -- -- - static struct platform_device bcm2708_alsa_devices[] = { - [0] = { - .name = "bcm2835_AUD0", -@@ -938,10 +890,8 @@ void __init bcm2708_init(void) - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; - bcm_register_device_dt(&w1_device); - #endif -- bcm_register_device(&bcm2708_systemtimer_device); - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index ffa667e..a5cac5b 100644 +index c5e51e8..fe71c50 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -485,35 +485,6 @@ static struct platform_device bcm2708_gpio_device = { +@@ -1050,7 +1050,7 @@ static irqreturn_t bcm2709_timer_interrupt(int irq, void *dev_id) + + static struct irqaction bcm2709_timer_irq = { + .name = "BCM2709 Timer Tick", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2709_timer_interrupt, }; - #endif --#ifdef SYSTEM_TIMER --static struct resource bcm2708_systemtimer_resources[] = { -- [0] = { /* system timer access */ -- .start = ST_BASE, -- .end = ST_BASE + SZ_4K - 1, -- .flags = IORESOURCE_MEM, -- }, -- { -- .start = IRQ_TIMER3, -- .end = IRQ_TIMER3, -- .flags = IORESOURCE_IRQ, -- } -- --}; -- --static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --static struct platform_device bcm2708_systemtimer_device = { -- .name = "bcm2708_systemtimer", -- .id = -1, /* only one VideoCore I/O area */ -- .resource = bcm2708_systemtimer_resources, -- .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), -- .dev = { -- .dma_mask = &systemtimer_dmamask, -- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), -- }, --}; --#endif -- - #ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ - static struct resource bcm2835_emmc_resources[] = { - [0] = { -@@ -542,27 +513,6 @@ struct platform_device bcm2835_emmc_device = { - }; - #endif /* CONFIG_MMC_BCM2835 */ - --static struct resource bcm2708_powerman_resources[] = { -- [0] = { -- .start = PM_BASE, -- .end = PM_BASE + SZ_256 - 1, -- .flags = IORESOURCE_MEM, -- }, --}; -- --static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); -- --struct platform_device bcm2708_powerman_device = { -- .name = "bcm2708_powerman", -- .id = 0, -- .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), -- .resource = bcm2708_powerman_resources, -- .dev = { -- .dma_mask = &powerman_dmamask, -- .coherent_dma_mask = 0xffffffffUL}, --}; -- -- - static struct platform_device bcm2708_alsa_devices[] = { - [0] = { - .name = "bcm2835_AUD0", -@@ -960,12 +910,8 @@ void __init bcm2709_init(void) - w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; - bcm_register_device_dt(&w1_device); - #endif --#ifdef SYSTEM_TIMER -- bcm_register_device(&bcm2708_systemtimer_device); --#endif - bcm_register_device_dt(&bcm2708_fb_device); - bcm_register_device_dt(&bcm2708_usb_device); -- bcm_register_device(&bcm2708_powerman_device); - - #ifdef CONFIG_MMC_BCM2835 - bcm_register_device_dt(&bcm2835_emmc_device); From 6ff0766cae433f411b7714445b58def792ff7e7b Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 19 Jun 2015 12:05:29 +0200 Subject: [PATCH 13/29] linux: remove linux-4.0 support Signed-off-by: Stephan Raue --- packages/linux/package.mk | 4 - .../4.0.5/linux-003-no_dev_console.patch | 21 - .../linux-051-ouya_controller_support.patch | 315 - .../4.0.5/linux-052-XBOX_remote_support.patch | 1029 - .../linux-053-spinelplus-remote-0.2.patch | 161 - ...1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 12 - ...-add_Adaptec_eHome_Infrared_Receiver.patch | 21 - ...tomer-code-restriction-in-rc6-decode.patch | 28 - ..._Manufacturing_Inc_Infrared_Receiver.patch | 13 - ..._sony-add_autorepeat_for_PS3_remotes.patch | 64 - .../linux-062-imon_pad_ignore_diagonal.patch | 21 - ...x-203-stb0899_enable_low_symbol_rate.patch | 12 - ...linux-212-mantis_stb0899_faster_lock.patch | 138 - .../4.0.5/linux-221-ngene-octopus.patch | 34102 ---------------- .../linux-222-stb0899_signal_quality.patch | 62 - ...-video-artifacts-with-tt-3600-s2-usb.patch | 17 - .../linux-224-STK1160-addFramescaling.patch | 284 - ...linux-227-ds3000-invalid-symbol-rate.patch | 18 - .../4.0.5/linux-228-technotrend-s2-4600.patch | 382 - .../4.0.5/linux-229-hauppauge-hvr-955q.patch | 2706 -- .../4.0.5/linux-706-Sitecom-N300.patch | 11 - ...x-950-saa716x_PCIe_interface_chipset.patch | 13031 ------ ...utputting-HDMI-audio-before-prepare-.patch | 83 - .../linux-995-CX24120-13Z_frontend.patch | 1577 - .../linux-999-i915-use-legacy-turbo.patch | 30 - ...able-async-suspend-resume-by-default.patch | 25 - ...alize-partitions-on-RPMB-flagged-are.patch | 26 - ...linux-999.10-amd-limited-color-range.patch | 269 - 28 files changed, 54462 deletions(-) delete mode 100644 packages/linux/patches/4.0.5/linux-003-no_dev_console.patch delete mode 100644 packages/linux/patches/4.0.5/linux-051-ouya_controller_support.patch delete mode 100644 packages/linux/patches/4.0.5/linux-052-XBOX_remote_support.patch delete mode 100644 packages/linux/patches/4.0.5/linux-053-spinelplus-remote-0.2.patch delete mode 100644 packages/linux/patches/4.0.5/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch delete mode 100644 packages/linux/patches/4.0.5/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch delete mode 100644 packages/linux/patches/4.0.5/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch delete mode 100644 packages/linux/patches/4.0.5/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch delete mode 100644 packages/linux/patches/4.0.5/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch delete mode 100644 packages/linux/patches/4.0.5/linux-062-imon_pad_ignore_diagonal.patch delete mode 100644 packages/linux/patches/4.0.5/linux-203-stb0899_enable_low_symbol_rate.patch delete mode 100644 packages/linux/patches/4.0.5/linux-212-mantis_stb0899_faster_lock.patch delete mode 100644 packages/linux/patches/4.0.5/linux-221-ngene-octopus.patch delete mode 100644 packages/linux/patches/4.0.5/linux-222-stb0899_signal_quality.patch delete mode 100644 packages/linux/patches/4.0.5/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch delete mode 100644 packages/linux/patches/4.0.5/linux-224-STK1160-addFramescaling.patch delete mode 100644 packages/linux/patches/4.0.5/linux-227-ds3000-invalid-symbol-rate.patch delete mode 100644 packages/linux/patches/4.0.5/linux-228-technotrend-s2-4600.patch delete mode 100644 packages/linux/patches/4.0.5/linux-229-hauppauge-hvr-955q.patch delete mode 100644 packages/linux/patches/4.0.5/linux-706-Sitecom-N300.patch delete mode 100644 packages/linux/patches/4.0.5/linux-950-saa716x_PCIe_interface_chipset.patch delete mode 100644 packages/linux/patches/4.0.5/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch delete mode 100644 packages/linux/patches/4.0.5/linux-995-CX24120-13Z_frontend.patch delete mode 100644 packages/linux/patches/4.0.5/linux-999-i915-use-legacy-turbo.patch delete mode 100644 packages/linux/patches/4.0.5/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch delete mode 100644 packages/linux/patches/4.0.5/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch delete mode 100644 packages/linux/patches/4.0.5/linux-999.10-amd-limited-color-range.patch diff --git a/packages/linux/package.mk b/packages/linux/package.mk index 38fac29265..5a3c688cad 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -39,10 +39,6 @@ case "$LINUX" in PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET imx6-status-led imx6-soc-fan" ;; - 4.0) - PKG_VERSION="4.0.5" - PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/$PKG_NAME-$PKG_VERSION.tar.xz" - ;; *) PKG_VERSION="4.1-rc8" PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/testing/$PKG_NAME-$PKG_VERSION.tar.xz" diff --git a/packages/linux/patches/4.0.5/linux-003-no_dev_console.patch b/packages/linux/patches/4.0.5/linux-003-no_dev_console.patch deleted file mode 100644 index df35a7ab9a..0000000000 --- a/packages/linux/patches/4.0.5/linux-003-no_dev_console.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/init/main.c b/init/main.c -index 9484f4b..db55edd 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -880,8 +880,14 @@ static noinline void __init kernel_init_freeable(void) - do_basic_setup(); - - /* Open the /dev/console on the rootfs, this should never fail */ -- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) -- pr_err("Warning: unable to open an initial console.\n"); -+ char *console = "/dev_console"; -+ -+ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) { -+ sys_mknod(console, S_IFCHR|0600, (TTYAUX_MAJOR<<8)|1); -+ if (sys_open(console, O_RDWR, 0) < 0) -+ printk(KERN_WARNING "Warning: unable to open an initial console.\n"); -+ sys_unlink(console); -+ } - - (void) sys_dup(0); - (void) sys_dup(0); diff --git a/packages/linux/patches/4.0.5/linux-051-ouya_controller_support.patch b/packages/linux/patches/4.0.5/linux-051-ouya_controller_support.patch deleted file mode 100644 index 9b0f253372..0000000000 --- a/packages/linux/patches/4.0.5/linux-051-ouya_controller_support.patch +++ /dev/null @@ -1,315 +0,0 @@ -diff -Naur linux-3.19.orig/drivers/hid/hid-core.c linux-3.19/drivers/hid/hid-core.c ---- linux-3.19.orig/drivers/hid/hid-core.c 2015-02-20 14:01:17.080322846 -0800 -+++ linux-3.19/drivers/hid/hid-core.c 2015-02-20 14:03:30.375519421 -0800 -@@ -1884,6 +1884,7 @@ - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, -+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, - { 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) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, -diff -Naur linux-3.19.orig/drivers/hid/hid-ids.h linux-3.19/drivers/hid/hid-ids.h ---- linux-3.19.orig/drivers/hid/hid-ids.h 2015-02-20 14:01:17.080322846 -0800 -+++ linux-3.19/drivers/hid/hid-ids.h 2015-02-20 14:03:30.382519482 -0800 -@@ -721,6 +721,9 @@ - #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 - #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 - -+#define USB_VENDOR_ID_OUYA 0x2836 -+#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001 -+ - #define USB_VENDOR_ID_PLANTRONICS 0x047f - - #define USB_VENDOR_ID_PANASONIC 0x04da -diff -Naur linux-3.19.orig/drivers/hid/hid-ouya.c linux-3.19/drivers/hid/hid-ouya.c ---- linux-3.19.orig/drivers/hid/hid-ouya.c 1969-12-31 16:00:00.000000000 -0800 -+++ linux-3.19/drivers/hid/hid-ouya.c 2015-02-20 14:03:30.371519386 -0800 -@@ -0,0 +1,260 @@ -+/* -+ * HID driver for OUYA Game Controller(s) -+ * -+ * Copyright (c) 2013 OUYA -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "hid-ids.h" -+ -+#define OUYA_TOUCHPAD_FIXUP (1 << 0) -+ -+struct ouya_sc { -+ unsigned long quirks; -+}; -+ -+/* Fixed report descriptor */ -+static __u8 ouya_rdesc_fixed[] = { -+ -+ 0x05, 0x01, /* Usage Page (Desktop), */ -+ 0x09, 0x05, /* Usage (Game Pad), */ -+ -+ 0xA1, 0x01, /* Collection (Application), */ -+ 0x85, 0x07, /* Report ID (7), */ -+ -+ 0xA1, 0x00, /* Collection (Physical), */ -+ 0x09, 0x30, /* Usage (X), */ -+ 0x09, 0x31, /* Usage (Y), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x35, 0x00, /* Physical Minimum (0), */ -+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -+ 0x95, 0x02, /* Report Count (2), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0xA1, 0x00, /* Collection (Physical), */ -+ 0x09, 0x33, /* Usage (Rx), */ -+ 0x09, 0x34, /* Usage (Ry), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x35, 0x00, /* Physical Minimum (0), */ -+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -+ 0x95, 0x02, /* Report Count (2), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0xA1, 0x00, /* Collection (Physical), */ -+ 0x09, 0x32, /* Usage (Z), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x35, 0x00, /* Physical Minimum (0), */ -+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -+ 0x95, 0x01, /* Report Count (1), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0xA1, 0x00, /* Collection (Physical), */ -+ 0x09, 0x35, /* Usage (Rz), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x35, 0x00, /* Physical Minimum (0), */ -+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -+ 0x95, 0x01, /* Report Count (1), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0x05, 0x09, /* Usage Page (Button), */ -+ 0x19, 0x01, /* Usage Minimum (01h), */ -+ 0x29, 0x10, /* Usage Maximum (10h), */ -+ 0x95, 0x10, /* Report Count (16), */ -+ 0x75, 0x01, /* Report Size (1), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ -+ /* ORIGINAL REPORT DESCRIPTOR FOR TOUCHPAD INPUT */ -+ /* 06 00 ff a1 02 09 02 15 00 26 ff 00 35 00 46 ff 00 95 03 75 08 81 02 c0 */ -+ -+ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ -+ 0x09, 0x02, /* Usage (Mouse), */ -+ 0x09, 0x01, /* Usage (Pointer), */ -+ 0xA1, 0x00, /* Collection (Physical), */ -+ 0x05, 0x09, /* Usage Page (Button), */ -+ 0x19, 0x01, /* Usage Minimum (01h), */ -+ 0x29, 0x03, /* Usage Maximum (03h), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x25, 0x01, /* Logical Maximum (1), */ -+ 0x95, 0x03, /* Report Count (3), */ -+ 0x75, 0x01, /* Report Size (1), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0x95, 0x01, /* Report Count (1), */ -+ 0x75, 0x05, /* Report Size (5), */ -+ 0x81, 0x01, /* Input (Constant), */ -+ 0x05, 0x01, /* Usage Page (Desktop), */ -+ 0x09, 0x30, /* Usage (X), */ -+ 0x09, 0x31, /* Usage (Y), */ -+ 0x15, 0x81, /* Logical Minimum (-127), */ -+ 0x25, 0x7f, /* Logical Maximum (127), */ -+ 0x95, 0x02, /* Report Count (2), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x81, 0x06, /* Input (Relative), */ -+ 0xC0, /* End Collection, */ -+ -+ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ -+ 0xA1, 0x02, /* Collection (Logical), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x95, 0x07, /* Report Count (7), */ -+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x09, 0x01, /* Usage (Pointer), */ -+ 0x91, 0x02, /* Output (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0xC0, /* End Collection */ -+ -+ -+ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ -+ 0x05, 0x0C, /* Usage Page (Consumer), */ -+ 0x09, 0x01, /* Usage (Consumer Control), */ -+ -+ 0xA1, 0x01, /* Collection (Application), */ -+ 0x85, 0x03, /* Report ID (3), */ -+ 0x05, 0x01, /* Usage Page (Desktop), */ -+ 0x09, 0x06, /* Usage (Keyboard), */ -+ 0xA1, 0x02, /* Collection (Logical), */ -+ 0x05, 0x06, /* Usage Page (Generic), */ -+ 0x09, 0x20, /* Usage (Battery Strgth), */ -+ 0x15, 0x00, /* Logical Minimum (0), */ -+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x95, 0x01, /* Report Count (1), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0x06, 0xBC, 0xFF, /* Usage Page (Custom), */ -+ -+ 0x0A, 0xAD, 0xBD, /* UNKNOWN */ -+ -+ 0x75, 0x08, /* Report Size (8), */ -+ 0x95, 0x06, /* Report Count (6), */ -+ 0x81, 0x02, /* Input (Variable), */ -+ 0xC0, /* End Collection, */ -+ -+ 0xC0, /* End Collection */ -+ -+ 0x00 -+}; -+ -+static __u8 *ouya_report_fixup(struct hid_device *hdev, __u8 *rdesc, -+ unsigned int *rsize) -+{ -+ struct ouya_sc *sc = hid_get_drvdata(hdev); -+ -+ if (sc->quirks & OUYA_TOUCHPAD_FIXUP) { -+ rdesc = ouya_rdesc_fixed; -+ *rsize = sizeof(ouya_rdesc_fixed); -+ } -+ return rdesc; -+} -+ -+static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ struct ouya_sc *sc = hid_get_drvdata(hdev); -+ -+ if (!(sc->quirks & OUYA_TOUCHPAD_FIXUP)) { -+ return 0; -+ } -+ -+ if ((usage->hid & 0x90000) == 0x90000 && -+ (field->physical & 0xff000000) == 0xff000000 && -+ usage->collection_index == 5 && -+ field->report_count == 3) { -+ -+ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_MOUSE + (usage->hid - 0x90001)); -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id) -+{ -+ int ret; -+ struct ouya_sc *sc; -+ -+ sc = kzalloc(sizeof(*sc), GFP_KERNEL); -+ if (sc == NULL) { -+ hid_err(hdev, "can't alloc ouya descriptor\n"); -+ return -ENOMEM; -+ } -+ -+ if(((hdev->version & 0xff00) == 0x0100 && (hdev->version & 0xff) >= 0x04) || -+ ((hdev->version & 0xff00) == 0xe100 && (hdev->version & 0xff) >= 0x3a)) { -+ hid_info(hdev, "ouya controller - new version\n"); -+ sc->quirks = OUYA_TOUCHPAD_FIXUP; -+ } else { -+ sc->quirks = 0; -+ } -+ hid_set_drvdata(hdev, sc); -+ -+ ret = hid_parse(hdev); -+ if (ret) { -+ hid_err(hdev, "parse failed\n"); -+ goto err_free; -+ } -+ -+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | -+ HID_CONNECT_HIDDEV_FORCE); -+ if (ret) { -+ hid_err(hdev, "hw start failed\n"); -+ goto err_free; -+ } -+ -+ return 0; -+ -+err_free: -+ kfree(sc); -+ return ret; -+} -+ -+static void ouya_remove(struct hid_device *hdev) -+{ -+ hid_hw_stop(hdev); -+ kfree(hid_get_drvdata(hdev)); -+} -+ -+static const struct hid_device_id ouya_devices[] = { -+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(hid, ouya_devices); -+ -+static struct hid_driver ouya_driver = { -+ .name = "ouya", -+ .id_table = ouya_devices, -+ .probe = ouya_probe, -+ .remove = ouya_remove, -+ .input_mapping = ouya_input_mapping, -+ .report_fixup = ouya_report_fixup -+}; -+ -+static int __init ouya_init(void) -+{ -+ return hid_register_driver(&ouya_driver); -+} -+ -+static void __exit ouya_exit(void) -+{ -+ hid_unregister_driver(&ouya_driver); -+} -+ -+module_init(ouya_init); -+module_exit(ouya_exit); -diff -Naur linux-3.19.orig/drivers/hid/Kconfig linux-3.19/drivers/hid/Kconfig ---- linux-3.19.orig/drivers/hid/Kconfig 2015-02-20 14:01:17.081322855 -0800 -+++ linux-3.19/drivers/hid/Kconfig 2015-02-20 14:03:30.381519473 -0800 -@@ -528,6 +528,12 @@ - - Ortek WKB-2000 - - Skycable wireless presenter - -+config HID_OUYA -+ tristate "OUYA Game Controller" -+ depends on USB_HID -+ ---help--- -+ Support for OUYA Game Controller. -+ - config HID_PANTHERLORD - tristate "Pantherlord/GreenAsia game controller" - depends on HID -diff -Naur linux-3.19.orig/drivers/hid/Makefile linux-3.19/drivers/hid/Makefile ---- linux-3.19.orig/drivers/hid/Makefile 2015-02-20 14:01:17.081322855 -0800 -+++ linux-3.19/drivers/hid/Makefile 2015-02-20 14:03:30.382519482 -0800 -@@ -70,6 +70,7 @@ - obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o - obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o - obj-$(CONFIG_HID_ORTEK) += hid-ortek.o -+obj-$(CONFIG_HID_OUYA) += hid-ouya.o - obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o - obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o - obj-$(CONFIG_HID_PENMOUNT) += hid-penmount.o diff --git a/packages/linux/patches/4.0.5/linux-052-XBOX_remote_support.patch b/packages/linux/patches/4.0.5/linux-052-XBOX_remote_support.patch deleted file mode 100644 index 6b43f9b315..0000000000 --- a/packages/linux/patches/4.0.5/linux-052-XBOX_remote_support.patch +++ /dev/null @@ -1,1029 +0,0 @@ -diff -Naur linux-3.9.4/drivers/staging/media/lirc/Kconfig linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig ---- linux-3.9.4/drivers/staging/media/lirc/Kconfig 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig 2013-05-30 18:18:57.238957100 +0200 -@@ -63,10 +63,17 @@ - help - Driver for the SIR IrDA port - -+config LIRC_XBOX -+ tristate "XBOX USB IR Remote" -+ depends on LIRC && USB -+ help -+ Driver for the Microsoft XBOX USB IR Remote -+ - config LIRC_ZILOG - tristate "Zilog/Hauppauge IR Transmitter" - depends on LIRC && I2C - help - Driver for the Zilog/Hauppauge IR Transmitter, found on - PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards -+ - endif -diff -Naur linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c ---- linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c 2013-05-30 18:40:22.523775446 +0200 -@@ -0,0 +1,995 @@ -+/* -+ * lirc_xbox - USB remote support for LIRC -+ * (supports Microsoft XBOX DVD Dongle) -+ * -+ * Copyright (C) 2003-2004 Paul Miller -+ * -+ * This driver was derived from: -+ * Vladimir Dergachev 's 2002 -+ * "USB ATI Remote support" (input device) -+ * Adrian Dewhurst 's 2002 -+ * "USB StreamZap remote driver" (LIRC) -+ * Artur Lipowski 's 2002 -+ * "lirc_dev" and "lirc_gpio" LIRC modules -+ * Michael Wojciechowski -+ * initial xbox support -+ * Vassilis Virvilis 2006 -+ * reworked the patch for lirc submission -+ * Paul Miller's 2004 -+ * lirc_atiusb - removed all ati remote support -+ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+ -+//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) -+//#include -+//#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#include "drivers/kcompat.h" -+//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) -+#include -+#include -+//#else -+//#include "drivers/lirc.h" -+//#include "drivers/lirc_dev/lirc_dev.h" -+//#endif -+ -+#define DRIVER_VERSION "$Revision: 0.01 $" -+#define DRIVER_AUTHOR "Jason Martin " -+#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" -+#define DRIVER_NAME "lirc_xbox" -+ -+#define CODE_LENGTH 6 -+#define CODE_MIN_LENGTH 6 -+#define DECODE_LENGTH 1 -+ -+#ifndef URB_ASYNC_UNLINK -+#define URB_ASYNC_UNLINK 0 -+#endif -+ -+/* module parameters */ -+#ifdef CONFIG_USB_DEBUG -+static int debug = 1; -+#else -+static int debug; -+#endif -+ -+#define dprintk(fmt, args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_DEBUG fmt, ## args); \ -+ } while (0) -+ -+/* -+ * USB_BUFF_LEN must be the maximum value of the code_length array. -+ * It is used for static arrays. -+ */ -+#define USB_BUFF_LEN 6 -+ -+static int mask = 0xFFFF; /* channel acceptance bit mask */ -+static int unique; /* enable channel-specific codes */ -+static int repeat = 10; /* repeat time in 1/100 sec */ -+static unsigned long repeat_jiffies; /* repeat timeout */ -+ -+/* get hi and low bytes of a 16-bits int */ -+#define HI(a) ((unsigned char)((a) >> 8)) -+#define LO(a) ((unsigned char)((a) & 0xff)) -+ -+/* general constants */ -+#define SEND_FLAG_IN_PROGRESS 1 -+#define SEND_FLAG_COMPLETE 2 -+#define FREE_ALL 0xFF -+ -+/* endpoints */ -+#define EP_KEYS 0 -+#define EP_MOUSE 1 -+#define EP_MOUSE_ADDR 0x81 -+#define EP_KEYS_ADDR 0x82 -+ -+/* USB vendor ids for XBOX DVD Dongles */ -+#define VENDOR_MS1 0x040b -+#define VENDOR_MS2 0x045e -+#define VENDOR_MS3 0xFFFF -+ -+static struct usb_device_id usb_remote_table[] = { -+ /* Gamester Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS1, 0x6521) }, -+ -+ /* Microsoft Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS2, 0x0284) }, -+ -+ /* -+ * Some Chinese manufacturer -- conflicts with the joystick from the -+ * same manufacturer -+ */ -+ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, -+ -+ /* Terminating entry */ -+ { } -+}; -+ -+/* init strings */ -+#define USB_OUTLEN 7 -+ -+static char init1[] = {0x01, 0x00, 0x20, 0x14}; -+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; -+ -+struct in_endpt { -+ /* inner link in list of endpoints for the remote specified by ir */ -+ struct list_head iep_list_link; -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ unsigned int len; -+ dma_addr_t dma; -+ -+ /* handle repeats */ -+ unsigned char old[USB_BUFF_LEN]; -+ unsigned long old_jiffies; -+}; -+ -+struct out_endpt { -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ dma_addr_t dma; -+ -+ /* handle sending (init strings) */ -+ int send_flags; -+ wait_queue_head_t wait; -+}; -+ -+ -+/* data structure for each usb remote */ -+struct xbox_dev { -+ /* inner link in list of all remotes managed by this module */ -+ struct list_head remote_list_link; -+ /* Number of usb interfaces associated with this device */ -+ int dev_refcount; -+ -+ /* usb */ -+ struct usb_device *usbdev; -+ /* Head link to list of all inbound endpoints in this remote */ -+ struct list_head iep_listhead; -+ struct out_endpt *out_init; -+ int devnum; -+ -+ /* lirc */ -+ struct lirc_driver *d; -+ int connected; -+ -+ /* locking */ -+ struct mutex lock; -+}; -+ -+/* list of all registered devices via the remote_list_link in xbox_dev */ -+static struct list_head remote_list; -+ -+/* -+ * Convenience macros to retrieve a pointer to the surrounding struct from -+ * the given list_head reference within, pointed at by link. -+ */ -+#define get_iep_from_link(link) \ -+ list_entry((link), struct in_endpt, iep_list_link); -+#define get_irctl_from_link(link) \ -+ list_entry((link), struct xbox_dev, remote_list_link); -+ -+/* send packet - used to initialize remote */ -+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) -+{ -+ struct xbox_dev *ir = oep->ir; -+ DECLARE_WAITQUEUE(wait, current); -+ int timeout = HZ; /* 1 second */ -+ unsigned char buf[USB_OUTLEN]; -+ -+ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); -+ -+ mutex_lock(&ir->lock); -+ oep->urb->transfer_buffer_length = LO(cmd) + 1; -+ oep->urb->dev = oep->ir->usbdev; -+ oep->send_flags = SEND_FLAG_IN_PROGRESS; -+ -+ memcpy(buf+1, data, LO(cmd)); -+ buf[0] = HI(cmd); -+ memcpy(oep->buf, buf, LO(cmd)+1); -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&oep->wait, &wait); -+ -+ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+ -+ while (timeout && (oep->urb->status == -EINPROGRESS) -+ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { -+ timeout = schedule_timeout(timeout); -+ rmb(); -+ } -+ -+ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+} -+ -+static int unregister_from_lirc(struct xbox_dev *ir) -+{ -+ struct lirc_driver *d = ir->d; -+ int devnum; -+ -+ devnum = ir->devnum; -+ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); -+ -+ lirc_unregister_driver(d->minor); -+ -+ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); -+ return 0; -+} -+ -+static int set_use_inc(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ int rtn; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); -+ return -EIO; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (!ir->connected) { -+ if (!ir->usbdev) { -+ mutex_unlock(&ir->lock); -+ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); -+ return -ENOENT; -+ } -+ -+ /* Iterate through the inbound endpoints */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ /* extract the current in_endpt */ -+ iep = get_iep_from_link(pos); -+ iep->urb->dev = ir->usbdev; -+ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); -+ if (rtn) { -+ printk(DRIVER_NAME "[%d]: open result = %d " -+ "error submitting urb\n", -+ ir->devnum, rtn); -+ mutex_unlock(&ir->lock); -+ return -EIO; -+ } -+ } -+ ir->connected = 1; -+ } -+ mutex_unlock(&ir->lock); -+ -+ return 0; -+} -+ -+static void set_use_dec(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); -+ return; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (ir->connected) { -+ /* Free inbound usb urbs */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ iep = get_iep_from_link(pos); -+ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ usb_kill_urb(iep->urb); -+ } -+ ir->connected = 0; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static void print_data(struct in_endpt *iep, char *buf, int len) -+{ -+ const int clen = CODE_LENGTH; -+ char codes[clen * 3 + 1]; -+ int i; -+ -+ if (len <= 0) -+ return; -+ -+ for (i = 0; i < len && i < clen; i++) -+ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); -+ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", -+ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); -+} -+ -+static int code_check_xbox(struct in_endpt *iep, int len) -+{ -+ // struct xbox_dev *ir = iep->ir; -+ const int clen = CODE_LENGTH; -+ -+ if (len != clen) { -+ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " -+ "ir.. ?\n", len, clen); -+ return -1; -+ } -+ -+ /* check for repeats */ -+ if (memcmp(iep->old, iep->buf, len) == 0) { -+ if (iep->old_jiffies + repeat_jiffies > jiffies) -+ return -1; -+ } else { -+ /* -+ * the third byte of xbox ir packet seems to contain key info -+ * the last two bytes are.. some kind of clock? -+ */ -+ iep->buf[0] = iep->buf[2]; -+ memset(iep->buf + 1, 0, len - 1); -+ memcpy(iep->old, iep->buf, len); -+ } -+ iep->old_jiffies = jiffies; -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_recv(struct urb *urb) -+#endif -+{ -+ struct in_endpt *iep; -+ int len, result = -1; -+ -+ if (!urb) -+ return; -+ iep = urb->context; -+ if (!iep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!iep->ir->usbdev) -+ return; -+ -+ len = urb->actual_length; -+ if (debug) -+ print_data(iep, urb->transfer_buffer, len); -+ -+ switch (urb->status) { -+ -+ case 0: -+ result = code_check_xbox(iep, len); -+ -+ if (result < 0) -+ break; -+ -+ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); -+ wake_up(&iep->ir->d->rbuf->wait_poll); -+ break; -+ -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ -+ case -EPIPE: -+ default: -+ break; -+ } -+ -+ usb_submit_urb(urb, GFP_ATOMIC); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_send(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_send(struct urb *urb) -+#endif -+{ -+ struct out_endpt *oep; -+ -+ if (!urb) -+ return; -+ oep = urb->context; -+ if (!oep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!oep->ir->usbdev) -+ return; -+ -+ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); -+ -+ if (urb->status) -+ return; -+ -+ oep->send_flags |= SEND_FLAG_COMPLETE; -+ wmb(); -+ if (waitqueue_active(&oep->wait)) -+ wake_up(&oep->wait); -+} -+ -+ -+/* -+ * Initialization and removal -+ */ -+ -+/* -+ * Free iep according to mem_failure which specifies a checkpoint into the -+ * initialization sequence for rollback recovery. -+ */ -+static void free_in_endpt(struct in_endpt *iep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); -+ if (!iep) -+ return; -+ -+ ir = iep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 5: -+ list_del(&iep->iep_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " -+ "from list\n", ir->devnum, iep->ep->bEndpointAddress); -+ case 4: -+ if (iep->urb) { -+ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(iep->urb); -+ usb_free_urb(iep->urb); -+ iep->urb = 0; -+ } else -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", -+ ir->devnum); -+ case 3: -+ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -+ iep->buf = 0; -+ case 2: -+ kfree(iep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+/* -+ * Construct a new inbound endpoint for this remote, and add it to the list of -+ * in_epts in ir. -+ */ -+static struct in_endpt *new_in_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct in_endpt *iep; -+ int pipe, maxp, len, addr; -+ int mem_failure; -+ -+ addr = ep->bEndpointAddress; -+ pipe = usb_rcvintpipe(dev, addr); -+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); -+ -+/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; -+ * len -= (len % CODE_LENGTH); */ -+ len = CODE_LENGTH; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " -+ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); -+ -+ mem_failure = 0; -+ iep = kzalloc(sizeof(*iep), GFP_KERNEL); -+ if (!iep) { -+ mem_failure = 1; -+ goto new_in_endpt_failure_check; -+ } -+ iep->ir = ir; -+ iep->ep = ep; -+ iep->len = len; -+ -+ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); -+ if (!iep->buf) { -+ mem_failure = 2; -+ goto new_in_endpt_failure_check; -+ } -+ -+ iep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!iep->urb) -+ mem_failure = 3; -+ -+new_in_endpt_failure_check: -+ -+ if (mem_failure) { -+ free_in_endpt(iep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, addr, mem_failure); -+ return NULL; -+ } -+ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); -+ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", -+ ir->devnum, iep->ep->bEndpointAddress); -+ return iep; -+} -+ -+static void free_out_endpt(struct out_endpt *oep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); -+ if (!oep) -+ return; -+ -+ wake_up_all(&oep->wait); -+ -+ ir = oep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 4: -+ if (oep->urb) { -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+ usb_free_urb(oep->urb); -+ oep->urb = 0; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", -+ ir->devnum); -+ } -+ case 3: -+ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, -+ oep->buf, oep->dma); -+ oep->buf = 0; -+ case 2: -+ kfree(oep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct out_endpt *new_out_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct out_endpt *oep; -+ int mem_failure; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", -+ ir->devnum, ep->bEndpointAddress); -+ -+ mem_failure = 0; -+ oep = kzalloc(sizeof(*oep), GFP_KERNEL); -+ if (!oep) -+ mem_failure = 1; -+ else { -+ oep->ir = ir; -+ oep->ep = ep; -+ init_waitqueue_head(&oep->wait); -+ -+ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, -+ GFP_ATOMIC, &oep->dma); -+ if (!oep->buf) -+ mem_failure = 2; -+ else { -+ oep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!oep->urb) -+ mem_failure = 3; -+ } -+ } -+ if (mem_failure) { -+ free_out_endpt(oep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, ep->bEndpointAddress, mem_failure); -+ return NULL; -+ } -+ return oep; -+} -+ -+static void free_irctl(struct xbox_dev *ir, int mem_failure) -+{ -+ struct list_head *pos, *n; -+ struct in_endpt *in; -+ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); -+ -+ if (!ir) -+ return; -+ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ in = get_iep_from_link(pos); -+ free_in_endpt(in, FREE_ALL); -+ } -+ if (ir->out_init) { -+ free_out_endpt(ir->out_init, FREE_ALL); -+ ir->out_init = NULL; -+ } -+ -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 6: -+ if (!--ir->dev_refcount) { -+ list_del(&ir->remote_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " -+ "remote from list\n", ir->devnum); -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," -+ "aborting free_irctl\n", -+ ir->devnum, ir->dev_refcount); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ case 5: -+ case 4: -+ case 3: -+ if (ir->d) { -+ switch (mem_failure) { -+ case 5: -+ lirc_buffer_free(ir->d->rbuf); -+ case 4: -+ kfree(ir->d->rbuf); -+ case 3: -+ kfree(ir->d); -+ } -+ } else -+ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", -+ ir->devnum); -+ case 2: -+ mutex_unlock(&ir->lock); -+ kfree(ir); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct xbox_dev *new_irctl(struct usb_interface *intf) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct xbox_dev *ir; -+ struct lirc_driver *driver; -+ int devnum, dclen; -+ int mem_failure; -+ -+ devnum = dev->devnum; -+ -+ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); -+ -+ mem_failure = 0; -+ ir = kzalloc(sizeof(*ir), GFP_KERNEL); -+ if (!ir) { -+ mem_failure = 1; -+ goto new_irctl_failure_check; -+ } -+ -+ dclen = DECODE_LENGTH; -+ -+ /* -+ * add this infrared remote struct to remote_list, keeping track -+ * of the number of drivers registered. -+ */ -+ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); -+ list_add_tail(&ir->remote_list_link, &remote_list); -+ ir->dev_refcount = 1; -+ -+ driver = kzalloc(sizeof(*driver), GFP_KERNEL); -+ if (!driver) { -+ mem_failure = 2; -+ goto new_irctl_failure_check; -+ } -+ -+ ir->d = driver; -+ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); -+ if (!driver->rbuf) { -+ mem_failure = 3; -+ goto new_irctl_failure_check; -+ } -+ -+ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { -+ mem_failure = 4; -+ goto new_irctl_failure_check; -+ } -+ -+ strcpy(driver->name, DRIVER_NAME " "); -+ driver->minor = -1; -+ driver->code_length = dclen * 8; -+ driver->features = LIRC_CAN_REC_LIRCCODE; -+ driver->data = ir; -+ driver->set_use_inc = &set_use_inc; -+ driver->set_use_dec = &set_use_dec; -+ driver->dev = &intf->dev; -+ driver->owner = THIS_MODULE; -+ ir->usbdev = dev; -+ ir->devnum = devnum; -+ -+ mutex_init(&ir->lock); -+ INIT_LIST_HEAD(&ir->iep_listhead); -+ -+new_irctl_failure_check: -+ -+ if (mem_failure) { -+ free_irctl(ir, mem_failure); -+ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", -+ devnum, mem_failure); -+ return NULL; -+ } -+ return ir; -+} -+ -+/* -+ * Scan the global list of remotes to see if the device listed is one of them. -+ * If it is, the corresponding xbox_dev is returned, with its dev_refcount -+ * incremented. Otherwise, returns null. -+ */ -+static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) -+{ -+ struct list_head *pos; -+ struct xbox_dev *ir = NULL; -+ -+ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); -+ list_for_each(pos, &remote_list) { -+ ir = get_irctl_from_link(pos); -+ if (ir->usbdev != dev) { -+ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", -+ dev->devnum, ir->devnum); -+ ir = NULL; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", -+ dev->devnum); -+ ir->dev_refcount++; -+ break; -+ } -+ } -+ return ir; -+} -+ -+/* -+ * If the USB interface has an out endpoint for control. -+ */ -+static void send_outbound_init(struct xbox_dev *ir) -+{ -+ if (ir->out_init) { -+ struct out_endpt *oep = ir->out_init; -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " -+ "outbound ep\n", ir->devnum); -+ usb_fill_int_urb(oep->urb, ir->usbdev, -+ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), -+ oep->buf, USB_OUTLEN, usb_remote_send, -+ oep, oep->ep->bInterval); -+ oep->urb->transfer_dma = oep->dma; -+ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ send_packet(oep, 0x8004, init1); -+ send_packet(oep, 0x8007, init2); -+ } -+} -+ -+/* Log driver and usb info */ -+static void log_usb_dev_info(struct usb_device *dev) -+{ -+ char buf[63], name[128] = ""; -+ -+ if (dev->descriptor.iManufacturer -+ && usb_string(dev, dev->descriptor.iManufacturer, -+ buf, sizeof(buf)) > 0) -+ strlcpy(name, buf, sizeof(name)); -+ if (dev->descriptor.iProduct -+ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) -+ snprintf(name + strlen(name), sizeof(name) - strlen(name), -+ " %s", buf); -+ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, -+ dev->bus->busnum, dev->devnum); -+} -+ -+ -+static int usb_remote_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_host_interface *idesc; -+ struct usb_endpoint_descriptor *ep; -+ struct in_endpt *iep; -+ struct xbox_dev *ir; -+ int i; -+ -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", -+ dev->devnum, dev, intf, id); -+ -+ idesc = intf->cur_altsetting; -+ -+ /* Check if a usb remote has already been registered for this device */ -+ ir = get_prior_reg_ir(dev); -+ -+ if (!ir) { -+ ir = new_irctl(intf); -+ if (!ir) -+ return -ENOMEM; -+ } -+ -+ /* -+ * step through the endpoints to find first in and first out endpoint -+ * of type interrupt transfer -+ */ -+ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { -+ ep = &idesc->endpoint[i].desc; -+ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", -+ dev->devnum, i); -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_IN) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT)) { -+ -+ iep = new_in_endpt(ir, ep); -+ if (iep) -+ { -+ usb_fill_int_urb(iep->urb, dev, -+ usb_rcvintpipe(dev, -+ iep->ep->bEndpointAddress), -+ iep->buf, iep->len, usb_remote_recv, -+ iep, iep->ep->bInterval); -+ iep->urb->transfer_dma = iep->dma; -+ iep->urb->transfer_flags |= -+ URB_NO_TRANSFER_DMA_MAP; -+ } -+ } -+ -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_OUT) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT) && -+ (ir->out_init == NULL)) -+ ir->out_init = new_out_endpt(ir, ep); -+ } -+ if (list_empty(&ir->iep_listhead)) { -+ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", -+ ir->devnum); -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ if (ir->dev_refcount == 1) { -+ ir->d->minor = lirc_register_driver(ir->d); -+ if (ir->d->minor < 0) { -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ -+ /* Note new driver registration in kernel logs */ -+ log_usb_dev_info(dev); -+ -+ /* outbound data (initialization) */ -+ send_outbound_init(ir); -+ } -+ -+ usb_set_intfdata(intf, ir); -+ return 0; -+} -+ -+static void usb_remote_disconnect(struct usb_interface *intf) -+{ -+ /* struct usb_device *dev = interface_to_usbdev(intf); */ -+ struct xbox_dev *ir = usb_get_intfdata(intf); -+ usb_set_intfdata(intf, NULL); -+ -+ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", -+ (ir ? ir->devnum : -1)); -+ if (!ir || !ir->d) -+ return; -+ -+ if (ir->usbdev) { -+ /* Only unregister once */ -+ ir->usbdev = NULL; -+ unregister_from_lirc(ir); -+ } -+ -+ /* This also removes the current remote from remote_list */ -+ free_irctl(ir, FREE_ALL); -+} -+ -+static struct usb_driver usb_remote_driver = { -+ .name = DRIVER_NAME, -+ .probe = usb_remote_probe, -+ .disconnect = usb_remote_disconnect, -+ .id_table = usb_remote_table -+}; -+ -+static int __init usb_remote_init(void) -+{ -+ int i; -+ -+ INIT_LIST_HEAD(&remote_list); -+ -+ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " -+ DRIVER_VERSION "\n"); -+ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); -+ dprintk(DRIVER_NAME ": debug mode enabled: " -+ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); -+ -+ repeat_jiffies = repeat*HZ/100; -+ -+ i = usb_register(&usb_remote_driver); -+ if (i) { -+ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit usb_remote_exit(void) -+{ -+ usb_deregister(&usb_remote_driver); -+} -+ -+module_init(usb_remote_init); -+module_exit(usb_remote_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(usb, usb_remote_table); -+ -+module_param(debug, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); -+ -+module_param(mask, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); -+ -+module_param(unique, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); -+ -+module_param(repeat, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); -diff -Naur linux-3.9.4/drivers/staging/media/lirc/Makefile linux-3.9.4.patch/drivers/staging/media/lirc/Makefile ---- linux-3.9.4/drivers/staging/media/lirc/Makefile 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/Makefile 2013-05-30 18:17:39.163634834 +0200 -@@ -10,4 +10,5 @@ - obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o - obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o - obj-$(CONFIG_LIRC_SIR) += lirc_sir.o -+obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o - obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/packages/linux/patches/4.0.5/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/4.0.5/linux-053-spinelplus-remote-0.2.patch deleted file mode 100644 index a4068872d2..0000000000 --- a/packages/linux/patches/4.0.5/linux-053-spinelplus-remote-0.2.patch +++ /dev/null @@ -1,161 +0,0 @@ -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,9 @@ - { 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) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, - { 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,9 @@ - - #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_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 @@ -+/* -+ * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes -+ * -+ * Copyright (c) 2010 Panagiotis Skintzos -+ * -+ * Renamed to Spinel, cleanup and modified to also support -+ * Spinel Plus 0471:20CC by Stephan Raue 2012. -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the Free -+ * Software Foundation; either version 2 of the License, or (at your option) -+ * any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "hid-ids.h" -+ -+#define spinelplus_map_key(c) set_bit(EV_REP, hi->input->evbit); \ -+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) -+ -+static int spinelplus_input_mapping(struct hid_device *hdev, -+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ switch (usage->hid) { -+ case 0xffbc000d: spinelplus_map_key(KEY_MEDIA); break; -+ case 0xffbc0024: spinelplus_map_key(KEY_MEDIA); break; -+ case 0xffbc0027: spinelplus_map_key(KEY_ZOOM); break; -+ case 0xffbc0033: spinelplus_map_key(KEY_HOME); break; -+ case 0xffbc0035: spinelplus_map_key(KEY_CAMERA); break; -+ case 0xffbc0036: spinelplus_map_key(KEY_EPG); break; -+ case 0xffbc0037: spinelplus_map_key(KEY_DVD); break; -+ case 0xffbc0038: spinelplus_map_key(KEY_HOME); break; -+ case 0xffbc0039: spinelplus_map_key(KEY_MP3); break; -+ case 0xffbc003a: spinelplus_map_key(KEY_VIDEO); break; -+ case 0xffbc005a: spinelplus_map_key(KEY_TEXT); break; -+ case 0xffbc005b: spinelplus_map_key(KEY_RED); break; -+ case 0xffbc005c: spinelplus_map_key(KEY_GREEN); break; -+ case 0xffbc005d: spinelplus_map_key(KEY_YELLOW); break; -+ case 0xffbc005e: spinelplus_map_key(KEY_BLUE); break; -+ default: -+ return 0; -+ } -+ return 1; -+} -+ -+static int spinelplus_probe(struct hid_device *hdev, -+ const struct hid_device_id *id) -+{ -+ int ret; -+ /* Connect only to hid input (not hiddev & hidraw)*/ -+ unsigned int cmask = HID_CONNECT_HIDINPUT; -+ -+ ret = hid_parse(hdev); -+ if (ret) { -+ dev_err(&hdev->dev, "parse failed\n"); -+ goto err_free; -+ } -+ -+ ret = hid_hw_start(hdev, cmask); -+ if (ret) { -+ dev_err(&hdev->dev, "hw start failed\n"); -+ goto err_free; -+ } -+ -+ return 0; -+err_free: -+ return ret; -+} -+ -+static const struct hid_device_id spinelplus_devices[] = { -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(hid, spinelplus_devices); -+ -+static struct hid_driver spinelplus_driver = { -+ .name = "SpinelPlus", -+ .id_table = spinelplus_devices, -+ .input_mapping = spinelplus_input_mapping, -+ .probe = spinelplus_probe, -+}; -+ -+static int __init spinelplus_init(void) -+{ -+ return hid_register_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) 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/4.0.5/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/4.0.5/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch deleted file mode 100644 index 08566d1f13..0000000000 --- a/packages/linux/patches/4.0.5/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur linux-3.0/drivers/media/rc/nuvoton-cir.c linux-3.0.patch/drivers/media/rc/nuvoton-cir.c ---- linux-3.0/drivers/media/rc/nuvoton-cir.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/media/rc/nuvoton-cir.c 2011-07-22 21:30:48.374591146 +0200 -@@ -1110,7 +1110,7 @@ - rdev->dev.parent = &pdev->dev; - rdev->driver_name = NVT_DRIVER_NAME; - rdev->map_name = RC_MAP_RC6_MCE; -- rdev->timeout = MS_TO_NS(100); -+ rdev->timeout = US_TO_NS(1000); - /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ - rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); - #if 0 diff --git a/packages/linux/patches/4.0.5/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch b/packages/linux/patches/4.0.5/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch deleted file mode 100644 index 4116b9ff86..0000000000 --- a/packages/linux/patches/4.0.5/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -Naur linux-3.17.1/drivers/media/rc/mceusb.c linux-3.17.1.patch/drivers/media/rc/mceusb.c ---- linux-3.17.1/drivers/media/rc/mceusb.c 2014-10-15 12:29:30.000000000 +0200 -+++ linux-3.17.1.patch/drivers/media/rc/mceusb.c 2014-10-16 11:45:57.480176874 +0200 -@@ -188,6 +188,8 @@ - #define VENDOR_TWISTEDMELON 0x2596 - #define VENDOR_HAUPPAUGE 0x2040 - #define VENDOR_PCTV 0x2013 -+#define VENDOR_ADAPTEC 0x03f3 -+ - - enum mceusb_model_type { - MCE_GEN2 = 0, /* Most boards */ -@@ -401,6 +403,8 @@ - .driver_info = HAUPPAUGE_CX_HYBRID_TV }, - { USB_DEVICE(VENDOR_PCTV, 0x025e), - .driver_info = HAUPPAUGE_CX_HYBRID_TV }, -+ /* Adaptec / HP eHome Receiver */ -+ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, - - /* Terminating entry */ - { } diff --git a/packages/linux/patches/4.0.5/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/4.0.5/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch deleted file mode 100644 index 2bc9542311..0000000000 --- a/packages/linux/patches/4.0.5/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- linux/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:08:13.148418669 -0800 -+++ linux.patch/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:07:48.864417975 -0800 -@@ -39,7 +39,6 @@ - #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ - #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ - #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ --#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ - #ifndef CHAR_BIT - #define CHAR_BIT 8 /* Normally in */ - #endif -@@ -257,14 +256,9 @@ again: - toggle = 0; - break; - case 32: -- if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { -- protocol = RC_TYPE_RC6_MCE; -- toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); -- scancode &= ~RC6_6A_MCE_TOGGLE_MASK; -- } else { -- protocol = RC_BIT_RC6_6A_32; -- toggle = 0; -- } -+ protocol = RC_TYPE_RC6_MCE; -+ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); -+ scancode &= ~RC6_6A_MCE_TOGGLE_MASK; - break; - default: - IR_dprintk(1, "RC6(6A) unsupported length\n"); diff --git a/packages/linux/patches/4.0.5/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch b/packages/linux/patches/4.0.5/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch deleted file mode 100644 index 67fc7a0de8..0000000000 --- a/packages/linux/patches/4.0.5/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur linux-3.9.4/drivers/media/rc/mceusb.c linux-3.9.4.patch/drivers/media/rc/mceusb.c ---- linux-3.9.4/drivers/media/rc/mceusb.c 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/media/rc/mceusb.c 2013-05-27 12:28:12.811230633 +0200 -@@ -309,6 +309,9 @@ - /* SMK/I-O Data GV-MC7/RCKIT Receiver */ - { USB_DEVICE(VENDOR_SMK, 0x0353), - .driver_info = MCE_GEN2_NO_TX }, -+ /* SMK Manufacturing, Inc. Receiver */ -+ { USB_DEVICE(VENDOR_SMK, 0x0357), -+ .driver_info = MCE_GEN2_NO_TX }, - /* Tatung eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, - /* Shuttle eHome Infrared Transceiver */ diff --git a/packages/linux/patches/4.0.5/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/4.0.5/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch deleted file mode 100644 index 6fa866dfe8..0000000000 --- a/packages/linux/patches/4.0.5/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 7051422474e4c4e302ede3d07ffd8ef2682e07a2 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Tue, 22 Apr 2014 16:05:14 +0300 -Subject: [PATCH] [RFC] hid/sony: add autorepeat for PS3 remotes - -adapted to 3.17 - -Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes -Von: David Dillow -Datum: 28.06.2013 04:28 -An: linux-input@vger.kernel.org -Kopie (CC): Stephan Raue - -Some applications using the PS3 remote would like to have autorepeat -from the device. Use the input subsystem's software emulation to provide -this capability, and enable those that don't need it to turn it off. ---- -I'm not sure this is the correct approach, or if it is even appropriate -for a remote to do autorepeat. However, the media/rc subsystem does do -it by default, and it's been requested by users, so there is at least -some demand. - -This compiled against the hid-sony driver with the PS3 remote changes -merged, but I have done no testing of it. If the approach seems -reasonable, I'll try to test it when the MythTV is idle. ---- -diff -Naur linux-3.17.1/drivers/hid/hid-sony.c linux-3.17.1.patch/drivers/hid/hid-sony.c ---- linux-3.17.1/drivers/hid/hid-sony.c 2014-10-15 12:29:30.000000000 +0200 -+++ linux-3.17.1.patch/drivers/hid/hid-sony.c 2014-10-16 12:55:43.979181366 +0200 -@@ -875,6 +875,25 @@ - return 1; - } - -+static int ps3remote_setup_repeat(struct hid_device *hdev) -+{ -+ struct hid_input *hidinput = list_first_entry(&hdev->inputs, -+ struct hid_input, list); -+ struct input_dev *input = hidinput->input; -+ -+ /* -+ * Set up autorepeat defaults per the remote control subsystem; -+ * this must be done after hid_hw_start(), as having these non-zero -+ * at the time of input_register_device() tells the input system that -+ * the hardware does the autorepeat, and the PS3 remote does not. -+ */ -+ set_bit(EV_REP, input->evbit); -+ input->rep[REP_DELAY] = 500; -+ input->rep[REP_PERIOD] = 125; -+ -+ return 0; -+} -+ - static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) - { -@@ -1932,6 +1951,8 @@ - goto err_stop; - - sony_init_work(sc, dualshock4_state_worker); -+ } else if (sc->quirks & PS3REMOTE) { -+ ret = ps3remote_setup_repeat(hdev); - } else { - ret = 0; - } diff --git a/packages/linux/patches/4.0.5/linux-062-imon_pad_ignore_diagonal.patch b/packages/linux/patches/4.0.5/linux-062-imon_pad_ignore_diagonal.patch deleted file mode 100644 index 677de3ed7f..0000000000 --- a/packages/linux/patches/4.0.5/linux-062-imon_pad_ignore_diagonal.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -Naur linux-3.16.1/drivers/media/rc/imon.c linux-3.16.1.patch/drivers/media/rc/imon.c ---- linux-3.16.1/drivers/media/rc/imon.c 2014-08-14 04:36:35.000000000 +0200 -+++ linux-3.16.1.patch/drivers/media/rc/imon.c 2014-08-15 13:57:16.587620642 +0200 -@@ -1344,6 +1344,17 @@ - } - } else { - /* -+ * For users without stabilized, just ignore any value getting -+ * to close to the diagonal. -+ */ -+ if ((abs(rel_y) < 2 && abs(rel_x) < 2) || -+ abs(abs(rel_y) - abs(rel_x)) < 2 ) { -+ spin_lock_irqsave(&ictx->kc_lock, flags); -+ ictx->kc = KEY_UNKNOWN; -+ spin_unlock_irqrestore(&ictx->kc_lock, flags); -+ return; -+ } -+ /* - * Hack alert: instead of using keycodes, we have - * to use hard-coded scancodes here... - */ diff --git a/packages/linux/patches/4.0.5/linux-203-stb0899_enable_low_symbol_rate.patch b/packages/linux/patches/4.0.5/linux-203-stb0899_enable_low_symbol_rate.patch deleted file mode 100644 index f302b6ce1b..0000000000 --- a/packages/linux/patches/4.0.5/linux-203-stb0899_enable_low_symbol_rate.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:25:43.479645317 +0100 -@@ -1581,7 +1581,7 @@ - .frequency_max = 2150000, - .frequency_stepsize = 0, - .frequency_tolerance = 0, -- .symbol_rate_min = 5000000, -+ .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - - .caps = FE_CAN_INVERSION_AUTO | diff --git a/packages/linux/patches/4.0.5/linux-212-mantis_stb0899_faster_lock.patch b/packages/linux/patches/4.0.5/linux-212-mantis_stb0899_faster_lock.patch deleted file mode 100644 index eef4e1effc..0000000000 --- a/packages/linux/patches/4.0.5/linux-212-mantis_stb0899_faster_lock.patch +++ /dev/null @@ -1,138 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-16 10:28:33.633409961 +0100 -@@ -206,7 +206,6 @@ - static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) - { - struct stb0899_internal *internal = &state->internal; -- struct stb0899_params *params = &state->params; - - short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; - int index = 0; -@@ -216,10 +215,9 @@ - - /* timing loop computation & symbol rate optimisation */ - derot_limit = (internal->sub_range / 2L) / internal->mclk; -- derot_step = (params->srate / 2L) / internal->mclk; -+ derot_step = internal->derot_step * 4; /* dertot_step = decreasing delta */ - - while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { -- index++; - derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - - if (abs(derot_freq) > derot_limit) -@@ -230,6 +228,7 @@ - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - } -+ index++; - internal->direction = -internal->direction; /* Change zigzag direction */ - } - -@@ -278,14 +277,18 @@ - { - struct stb0899_internal *internal = &state->internal; - -- short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; -+ short int derot_freq = 0, last_derot_freq = 0, derot_limit, derot_step, next_loop = 3; - int index = 0; -+ int base_freq; - u8 cfr[2]; - u8 reg; - - internal->status = NOCARRIER; - derot_limit = (internal->sub_range / 2L) / internal->mclk; - derot_freq = internal->derot_freq; -+ derot_step = internal->derot_step * 2; -+ last_derot_freq = internal->derot_freq; -+ base_freq = internal->derot_freq; - - reg = stb0899_read_reg(state, STB0899_CFD); - STB0899_SETFIELD_VAL(CFD_ON, reg, 1); -@@ -294,11 +297,10 @@ - do { - dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); - if (stb0899_check_carrier(state) == NOCARRIER) { -- index++; - last_derot_freq = derot_freq; -- derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ -+ derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - -- if(abs(derot_freq) > derot_limit) -+ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) - next_loop--; - - if (next_loop) { -@@ -310,9 +312,10 @@ - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - } -+ index++; -+ internal->direction = -internal->direction; /* Change zigzag direction */ - } - -- internal->direction = -internal->direction; /* Change zigzag direction */ - } while ((internal->status != CARRIEROK) && next_loop); - - if (internal->status == CARRIEROK) { -@@ -338,6 +341,7 @@ - int lock = 0, index = 0, dataTime = 500, loop; - u8 reg; - -+ msleep(1); - internal->status = NODATA; - - /* RESET FEC */ -@@ -348,6 +352,7 @@ - reg = stb0899_read_reg(state, STB0899_TSTRES); - STB0899_SETFIELD_VAL(FRESACS, reg, 0); - stb0899_write_reg(state, STB0899_TSTRES, reg); -+ msleep(1); - - if (params->srate <= 2000000) - dataTime = 2000; -@@ -363,6 +368,7 @@ - - stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ - while (1) { -+ msleep(1); // Alex: added 1 mSec - /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ - reg = stb0899_read_reg(state, STB0899_VSTATUS); - lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); -@@ -390,20 +396,21 @@ - short int derot_freq, derot_step, derot_limit, next_loop = 3; - u8 cfr[2]; - u8 reg; -- int index = 1; -+ int index = 0; -+ int base_freq; - - struct stb0899_internal *internal = &state->internal; -- struct stb0899_params *params = &state->params; - -- derot_step = (params->srate / 4L) / internal->mclk; -+ derot_step = internal->derot_step; - derot_limit = (internal->sub_range / 2L) / internal->mclk; - derot_freq = internal->derot_freq; -+ base_freq = internal->derot_freq; - - do { - if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { - - derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ -- if (abs(derot_freq) > derot_limit) -+ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) - next_loop--; - - if (next_loop) { -@@ -417,9 +424,9 @@ - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - - stb0899_check_carrier(state); -- index++; - } - } -+ index++; - internal->direction = -internal->direction; /* change zig zag direction */ - } while ((internal->status != DATAOK) && next_loop); - diff --git a/packages/linux/patches/4.0.5/linux-221-ngene-octopus.patch b/packages/linux/patches/4.0.5/linux-221-ngene-octopus.patch deleted file mode 100644 index 7533bc8aec..0000000000 --- a/packages/linux/patches/4.0.5/linux-221-ngene-octopus.patch +++ /dev/null @@ -1,34102 +0,0 @@ -From 7ade7028747ff0ff56f74f29d30eb48c9bc52575 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Thu, 12 Feb 2015 13:16:54 +0200 -Subject: [PATCH] dvb: ngene/octopus - -source: http://linuxtv.org/hg/~endriss/media_build_experimental/ - -note: SYS_DVBC2 not added. ci extensions (en50221) not added. ---- - drivers/media/dvb-core/Makefile | 2 +- - drivers/media/dvb-core/dvb_netstream.c | 259 ++ - drivers/media/dvb-core/dvb_netstream.h | 94 + - drivers/media/dvb-core/dvbdev.c | 3 +- - drivers/media/dvb-core/dvbdev.h | 4 + - drivers/media/dvb-frontends/Kconfig | 27 + - drivers/media/dvb-frontends/Makefile | 3 + - drivers/media/dvb-frontends/cxd2843.c | 2022 ++++++++++++ - drivers/media/dvb-frontends/cxd2843.h | 30 + - drivers/media/dvb-frontends/drxk_hard.c | 3614 +++++++++----------- - drivers/media/dvb-frontends/drxk_hard.h | 298 +- - drivers/media/dvb-frontends/drxk_map.h | 3 - - drivers/media/dvb-frontends/lnbh25.c | 153 + - drivers/media/dvb-frontends/lnbh25.h | 28 + - drivers/media/dvb-frontends/stv0367dd.c | 2331 +++++++++++++ - drivers/media/dvb-frontends/stv0367dd.h | 17 + - drivers/media/dvb-frontends/stv0367dd_regs.h | 3431 +++++++++++++++++++ - drivers/media/dvb-frontends/stv090x.c | 45 +- - drivers/media/dvb-frontends/stv0910.c | 1371 ++++++++ - drivers/media/dvb-frontends/stv0910.h | 31 + - drivers/media/dvb-frontends/stv0910_regs.h | 3998 +++++++++++++++++++++++ - drivers/media/dvb-frontends/stv6111.c | 450 +++ - drivers/media/dvb-frontends/stv6111.h | 5 + - drivers/media/dvb-frontends/tda18212dd.c | 974 ++++++ - drivers/media/dvb-frontends/tda18212dd.h | 5 + - drivers/media/dvb-frontends/tda18271c2dd.c | 17 +- - drivers/media/dvb-frontends/tda18271c2dd.h | 6 +- - drivers/media/dvb-frontends/tda18271c2dd_maps.h | 8 +- - drivers/media/pci/ddbridge/Kconfig | 11 +- - drivers/media/pci/ddbridge/Makefile | 2 - - drivers/media/pci/ddbridge/ddbridge-core.c | 3941 ++++++++++++++++------ - drivers/media/pci/ddbridge/ddbridge-i2c.c | 257 ++ - drivers/media/pci/ddbridge/ddbridge-i2c.h | 105 + - drivers/media/pci/ddbridge/ddbridge-mod.c | 1148 +++++++ - drivers/media/pci/ddbridge/ddbridge-ns.c | 489 +++ - drivers/media/pci/ddbridge/ddbridge-regs.h | 347 +- - drivers/media/pci/ddbridge/ddbridge.c | 470 +++ - drivers/media/pci/ddbridge/ddbridge.h | 419 ++- - drivers/media/pci/ddbridge/octonet.c | 199 ++ - drivers/media/pci/ngene/Kconfig | 4 + - drivers/media/pci/ngene/Makefile | 3 +- - drivers/media/pci/ngene/ngene-av.c | 348 ++ - drivers/media/pci/ngene/ngene-cards.c | 975 ++++-- - drivers/media/pci/ngene/ngene-core.c | 410 ++- - drivers/media/pci/ngene/ngene-dvb.c | 379 ++- - drivers/media/pci/ngene/ngene-eeprom.c | 284 ++ - drivers/media/pci/ngene/ngene-i2c.c | 113 + - drivers/media/pci/ngene/ngene.h | 42 +- - include/uapi/linux/dvb/mod.h | 22 + - include/uapi/linux/dvb/ns.h | 68 + - 50 files changed, 25728 insertions(+), 3537 deletions(-) - create mode 100644 drivers/media/dvb-core/dvb_netstream.c - create mode 100644 drivers/media/dvb-core/dvb_netstream.h - create mode 100644 drivers/media/dvb-frontends/cxd2843.c - create mode 100644 drivers/media/dvb-frontends/cxd2843.h - create mode 100644 drivers/media/dvb-frontends/lnbh25.c - create mode 100644 drivers/media/dvb-frontends/lnbh25.h - create mode 100644 drivers/media/dvb-frontends/stv0367dd.c - create mode 100644 drivers/media/dvb-frontends/stv0367dd.h - create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h - create mode 100644 drivers/media/dvb-frontends/stv0910.c - create mode 100644 drivers/media/dvb-frontends/stv0910.h - create mode 100644 drivers/media/dvb-frontends/stv0910_regs.h - create mode 100644 drivers/media/dvb-frontends/stv6111.c - create mode 100644 drivers/media/dvb-frontends/stv6111.h - create mode 100644 drivers/media/dvb-frontends/tda18212dd.c - create mode 100644 drivers/media/dvb-frontends/tda18212dd.h - create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c - create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.h - create mode 100644 drivers/media/pci/ddbridge/ddbridge-mod.c - create mode 100644 drivers/media/pci/ddbridge/ddbridge-ns.c - create mode 100644 drivers/media/pci/ddbridge/ddbridge.c - create mode 100644 drivers/media/pci/ddbridge/octonet.c - create mode 100644 drivers/media/pci/ngene/ngene-av.c - create mode 100644 drivers/media/pci/ngene/ngene-eeprom.c - create mode 100644 include/uapi/linux/dvb/mod.h - create mode 100644 include/uapi/linux/dvb/ns.h - -diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile -index 8f22bcd..5ff851a 100644 ---- a/drivers/media/dvb-core/Makefile -+++ b/drivers/media/dvb-core/Makefile -@@ -6,6 +6,6 @@ dvb-net-$(CONFIG_DVB_NET) := dvb_net.o - - dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ -- $(dvb-net-y) dvb_ringbuffer.o dvb_math.o -+ $(dvb-net-y) dvb_ringbuffer.o dvb_math.o dvb_netstream.o - - obj-$(CONFIG_DVB_CORE) += dvb-core.o -diff --git a/drivers/media/dvb-core/dvb_netstream.c b/drivers/media/dvb-core/dvb_netstream.c -new file mode 100644 -index 0000000..43322c7 ---- /dev/null -+++ b/drivers/media/dvb-core/dvb_netstream.c -@@ -0,0 +1,259 @@ -+/* -+ * dvb_netstream.c: support for DVB to network streaming hardware -+ * -+ * Copyright (C) 2012-2013 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include "dvb_netstream.h" -+ -+static ssize_t ns_write(struct file *file, const char *buf, -+ size_t count, loff_t *ppos) -+{ -+ printk("%s\n", __func__); -+ return 0; -+} -+ -+static ssize_t ns_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ printk("%s\n", __func__); -+ return 0; -+} -+ -+static unsigned int ns_poll(struct file *file, poll_table *wait) -+{ -+ printk("%s\n", __func__); -+ return 0; -+} -+ -+static int ns_stop(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ -+ mutex_lock(&ns->mutex); -+ if (nss->running && ns->stop) { -+ ns->stop(nss); -+ nss->running = 0; -+ } -+ mutex_unlock(&ns->mutex); -+ return 0; -+} -+ -+static int ns_release(struct inode *inode, struct file *file) -+{ -+ struct dvbnss *nss = file->private_data; -+ struct dvb_netstream *ns = nss->ns; -+ -+ ns_stop(nss); -+ if (ns->free) -+ ns->free(nss); -+ mutex_lock(&ns->mutex); -+ list_del(&nss->nssl); -+ mutex_unlock(&ns->mutex); -+ vfree(nss); -+ return 0; -+} -+ -+static int ns_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct dvb_netstream *ns = dvbdev->priv; -+ struct dvbnss *nss; -+ -+ nss = vmalloc(sizeof(*nss)); -+ if (!nss) -+ return -ENOMEM; -+ nss->ns = ns; -+ if (ns->alloc && ns->alloc(nss) < 0) { -+ vfree(nss); -+ return -EBUSY; -+ } -+ file->private_data = nss; -+ nss->running = 0; -+ mutex_lock(&ns->mutex); -+ list_add(&nss->nssl, &ns->nssl); -+ mutex_unlock(&ns->mutex); -+ return 0; -+} -+ -+static int set_net(struct dvbnss *nss, struct dvb_ns_params *p) -+{ -+ return 0; -+} -+ -+static int do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvbnss *nss = file->private_data; -+ struct dvb_netstream *ns = nss->ns; -+ //unsigned long arg = (unsigned long) parg; -+ int ret = 0; -+ -+ switch (cmd) { -+ case NS_SET_RTCP_MSG: -+ { -+ struct dvb_ns_rtcp *rtcpm = parg; -+ -+ if (ns->set_rtcp_msg) { -+ //printk("%s calling NS_SET_RTCP_MSG\n", __func__); -+ ret = ns->set_rtcp_msg(nss, rtcpm->msg, rtcpm->len); -+ } -+ break; -+ } -+ -+ case NS_SET_NET: -+ memcpy(&nss->params, parg, sizeof(nss->params)); -+ if (ns->set_net) { -+ ret = ns->set_net(nss); -+ } else -+ ret = set_net(nss, (struct dvb_ns_params *) parg); -+ break; -+ -+ case NS_START: -+ mutex_lock(&ns->mutex); -+ if (nss->running) { -+ ret = -EBUSY; -+ } else if (ns->start) { -+ ret = ns->start(nss); -+ nss->running = 1; -+ } -+ mutex_unlock(&ns->mutex); -+ break; -+ -+ case NS_STOP: -+ ns_stop(nss); -+ break; -+ -+ case NS_SET_PACKETS: -+ { -+ struct dvb_ns_packet *packet = parg; -+ if (ns->set_ts_packets) { -+ ret = ns->set_ts_packets(nss, packet->buf, packet->count * 188); -+ } -+ break; -+ } -+ -+ case NS_INSERT_PACKETS: -+ { -+ u8 count = *(u8 *) parg; -+ if (ns->insert_ts_packets) -+ ret = ns->insert_ts_packets(nss, count); -+ break; -+ } -+ -+ case NS_SET_PID: -+ { -+ u16 pid = *(u16 *) parg; -+ u16 byte = (pid & 0x1fff) >> 3; -+ u8 bit = 1 << (pid & 7); -+ -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ memset(nss->pids, 0xff, 0x400); -+ else -+ memset(nss->pids, 0x00, 0x400); -+ } else { -+ if (pid & 0x8000) -+ nss->pids[byte] |= bit; -+ else -+ nss->pids[byte] &= ~bit; -+ } -+ if (ns->set_pid) -+ ret = ns->set_pid(nss, pid); -+ break; -+ } -+ -+ case NS_SET_PIDS: -+ ret = copy_from_user(nss->pids, *(u8 **) parg, 0x400); -+ if (ret < 0) -+ return ret; -+ if (ns->set_pids) -+ ret = ns->set_pids(nss); -+ break; -+ -+ case NS_SET_CI: -+ { -+ u8 ci = *(u8 *) parg; -+ -+ if (nss->running) -+ ret = -EBUSY; -+ else if (ns->set_ci) -+ ret = ns->set_ci(nss, ci); -+ break; -+ } -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static long ns_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, do_ioctl); -+} -+ -+static const struct file_operations ns_fops = { -+ .owner = THIS_MODULE, -+ .read = ns_read, -+ .write = ns_write, -+ .open = ns_open, -+ .release = ns_release, -+ .poll = ns_poll, -+ .mmap = 0, -+ .unlocked_ioctl = ns_ioctl, -+}; -+ -+static struct dvb_device ns_dev = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 1, -+ .fops = &ns_fops, -+}; -+ -+ -+int dvb_netstream_init(struct dvb_adapter *dvb_adapter, struct dvb_netstream *ns) -+{ -+ mutex_init(&ns->mutex); -+ spin_lock_init(&ns->lock); -+ ns->exit = 0; -+ dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns, -+ DVB_DEVICE_NS); -+ INIT_LIST_HEAD(&ns->nssl); -+ return 0; -+} -+ -+EXPORT_SYMBOL(dvb_netstream_init); -+ -+void dvb_netstream_release(struct dvb_netstream *ns) -+{ -+ ns->exit=1; -+ if (ns->dvbdev->users > 1) { -+ wait_event(ns->dvbdev->wait_queue, -+ ns->dvbdev->users == 1); -+ } -+ dvb_unregister_device(ns->dvbdev); -+} -+ -+EXPORT_SYMBOL(dvb_netstream_release); -diff --git a/drivers/media/dvb-core/dvb_netstream.h b/drivers/media/dvb-core/dvb_netstream.h -new file mode 100644 -index 0000000..df73ed5 ---- /dev/null -+++ b/drivers/media/dvb-core/dvb_netstream.h -@@ -0,0 +1,94 @@ -+/* -+ * dvb_netstream.c: support for DVB to network streaming hardware -+ * -+ * Copyright (C) 2012-2013 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef _DVB_NETSTREAM_H_ -+#define _DVB_NETSTREAM_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvbdev.h" -+ -+#define DVBNS_MAXPIDS 32 -+ -+struct dvbnss { -+ struct dvb_netstream *ns; -+ void *priv; -+ -+ u8 pids[1024]; -+ u8 packet[1328]; -+ u32 pp; -+ -+ struct socket *sock; -+ struct sockaddr_in sadr; -+ u32 sn; -+ -+ struct dvb_ns_params params; -+ -+ struct list_head nssl; -+ int running; -+}; -+ -+#define MAX_DVBNSS 32 -+ -+struct dvb_netstream { -+ void *priv; -+ -+ struct mutex mutex; -+ spinlock_t lock; -+ struct dvb_device *dvbdev; -+ int exit; -+ -+ struct list_head nssl; -+ -+ int (*set_net) (struct dvbnss *); -+ int (*set_pid) (struct dvbnss *, u16); -+ int (*set_pids) (struct dvbnss *); -+ int (*set_ci) (struct dvbnss *, u8); -+ int (*set_rtcp_msg) (struct dvbnss *, u8 *, u32); -+ int (*set_ts_packets) (struct dvbnss *, u8 *, u32); -+ int (*insert_ts_packets) (struct dvbnss *, u8); -+ int (*start) (struct dvbnss *); -+ int (*stop) (struct dvbnss *); -+ int (*alloc) (struct dvbnss *); -+ void (*free) (struct dvbnss *); -+ -+}; -+ -+ -+void dvb_netstream_release(struct dvb_netstream *); -+int dvb_netstream_init(struct dvb_adapter *, struct dvb_netstream *); -+ -+ -+#endif -diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c -index 983db75..bc218ab 100644 ---- a/drivers/media/dvb-core/dvbdev.c -+++ b/drivers/media/dvb-core/dvbdev.c -@@ -47,7 +47,7 @@ static DEFINE_MUTEX(dvbdev_register_lock); - - static const char * const dnames[] = { - "video", "audio", "sec", "frontend", "demux", "dvr", "ca", -- "net", "osd" -+ "net", "osd", "ci", "mod", "ns", "nsd" - }; - - #ifdef CONFIG_DVB_DYNAMIC_MINORS -@@ -431,6 +431,7 @@ out: - kfree(mbuf); - return err; - } -+EXPORT_SYMBOL(dvb_usercopy); - - static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) - { -diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h -index f96b28e..f901b54 100644 ---- a/drivers/media/dvb-core/dvbdev.h -+++ b/drivers/media/dvb-core/dvbdev.h -@@ -47,6 +47,10 @@ - #define DVB_DEVICE_CA 6 - #define DVB_DEVICE_NET 7 - #define DVB_DEVICE_OSD 8 -+#define DVB_DEVICE_CI 9 -+#define DVB_DEVICE_MOD 10 -+#define DVB_DEVICE_NS 11 -+#define DVB_DEVICE_NSD 12 - - #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ - static short adapter_nr[] = \ -diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig -index 6c75418..0b6233c 100644 ---- a/drivers/media/dvb-frontends/Kconfig -+++ b/drivers/media/dvb-frontends/Kconfig -@@ -72,6 +72,33 @@ config DVB_SI2165 - - Say Y when you want to support this frontend. - -+config DVB_STV0367DD -+ tristate "STV 0367 (DD)" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ STV 0367 DVB-C/T demodulator (Digital Devices driver). -+ -+ Say Y when you want to support this frontend. -+ -+config DVB_TDA18212DD -+ tristate "NXP TDA18212 silicon tuner (DD)" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ NXP TDA18212 silicon tuner (Digital Devices driver). -+ -+ Say Y when you want to support this tuner. -+ -+config DVB_CXD2843 -+ tristate "Sony CXD2843 DVB-C/T demodulator family" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ Sony CXD2843 demodulator (Digital Devices driver). -+ -+ Say Y when you want to support this frontend. -+ - comment "DVB-S (satellite) frontends" - depends on DVB_CORE - -diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile -index ba59df6..33bc12b 100644 ---- a/drivers/media/dvb-frontends/Makefile -+++ b/drivers/media/dvb-frontends/Makefile -@@ -105,6 +105,9 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o - obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o - obj-$(CONFIG_DVB_DRXK) += drxk.o - obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o -+obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o -+obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o -+obj-$(CONFIG_DVB_CXD2843) += cxd2843.o - obj-$(CONFIG_DVB_SI2165) += si2165.o - obj-$(CONFIG_DVB_A8293) += a8293.o - obj-$(CONFIG_DVB_SP2) += sp2.o -diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c -new file mode 100644 -index 0000000..27e5eac ---- /dev/null -+++ b/drivers/media/dvb-frontends/cxd2843.c -@@ -0,0 +1,2022 @@ -+/* -+ * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator. -+ * Also supports the CXD2837ER DVB-T/T2/C and the -+ * CXD2838ER ISDB-T demodulator. -+ * -+ * Copyright (C) 2013-2014 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "cxd2843.h" -+ -+#define USE_ALGO 1 -+ -+enum EDemodType { CXD2843, CXD2837, CXD2838 }; -+enum EDemodState { Unknown, Shutdown, Sleep, ActiveT, -+ ActiveT2, ActiveC, ActiveC2, ActiveIT }; -+enum ET2Profile { T2P_Base, T2P_Lite }; -+enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC, -+ OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT }; -+ -+struct cxd_state { -+ struct dvb_frontend frontend; -+ struct i2c_adapter *i2c; -+ struct mutex mutex; -+ -+ u8 adrt; -+ u8 curbankt; -+ -+ u8 adrx; -+ u8 curbankx; -+ -+ enum EDemodType type; -+ enum EDemodState state; -+ enum ET2Profile T2Profile; -+ enum omode omode; -+ -+ u8 IF_FS; -+ int ContinuousClock; -+ int SerialMode; -+ u8 SerialClockFrequency; -+ -+ u32 LockTimeout; -+ u32 TSLockTimeout; -+ u32 L1PostTimeout; -+ u32 DataSliceID; -+ int FirstTimeLock; -+ u32 plp; -+ u32 last_status; -+ -+ u32 bandwidth; -+ u32 bw; -+ -+ unsigned long tune_time; -+ -+ u32 LastBERNominator; -+ u32 LastBERDenominator; -+ u8 BERScaleMax; -+}; -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = { -+ .addr = adr, .flags = 0, .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("cxd2843: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int writeregs(struct cxd_state *state, u8 adr, u8 reg, -+ u8 *regd, u16 len) -+{ -+ u8 data[len + 1]; -+ -+ data[0] = reg; -+ memcpy(data + 1, regd, len); -+ return i2c_write(state->i2c, adr, data, len + 1); -+} -+ -+static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) -+{ -+ u8 mm[2] = {reg, dat}; -+ -+ return i2c_write(state->i2c, adr, mm, 2); -+} -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_err("cxd2843: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int readregs(struct cxd_state *state, u8 adr, u8 reg, -+ u8 *val, int count) -+{ -+ return i2c_read(state->i2c, adr, ®, 1, val, count); -+} -+ -+static int readregst_unlocked(struct cxd_state *cxd, u8 bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (bank != 0xFF && cxd->curbankt != bank) { -+ status = writereg(cxd, cxd->adrt, 0, bank); -+ if (status < 0) { -+ cxd->curbankt = 0xFF; -+ return status; -+ } -+ cxd->curbankt = bank; -+ } -+ status = readregs(cxd, cxd->adrt, Address, pValue, count); -+ return status; -+} -+ -+static int readregst(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregst_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankx != Bank) { -+ status = writereg(cxd, cxd->adrx, 0, Bank); -+ if (status < 0) { -+ cxd->curbankx = 0xFF; -+ return status; -+ } -+ cxd->curbankx = Bank; -+ } -+ status = readregs(cxd, cxd->adrx, Address, pValue, count); -+ return status; -+} -+ -+static int readregsx(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregsx_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankx != Bank) { -+ status = writereg(cxd, cxd->adrx, 0, Bank); -+ if (status < 0) { -+ cxd->curbankx = 0xFF; -+ return status; -+ } -+ cxd->curbankx = Bank; -+ } -+ status = writeregs(cxd, cxd->adrx, Address, pValue, count); -+ return status; -+} -+ -+static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = writeregsx_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) -+{ -+ return writeregsx(cxd, Bank, Address, &val, 1); -+} -+ -+static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank, -+ u8 Address, u8 *pValue, u16 count) -+{ -+ int status = 0; -+ -+ if (Bank != 0xFF && cxd->curbankt != Bank) { -+ status = writereg(cxd, cxd->adrt, 0, Bank); -+ if (status < 0) { -+ cxd->curbankt = 0xFF; -+ return status; -+ } -+ cxd->curbankt = Bank; -+ } -+ status = writeregs(cxd, cxd->adrt, Address, pValue, count); -+ return status; -+} -+ -+static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 *pValue, u16 count) -+{ -+ int status; -+ -+ mutex_lock(&cxd->mutex); -+ status = writeregst_unlocked(cxd, Bank, Address, pValue, count); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) -+{ -+ return writeregst(cxd, Bank, Address, &val, 1); -+} -+ -+static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 Value, u8 Mask) -+{ -+ int status = 0; -+ u8 tmp; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1); -+ if (status < 0) -+ return status; -+ tmp = (tmp & ~Mask) | Value; -+ status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address, -+ u8 Value, u8 Mask) -+{ -+ int status = 0; -+ u8 Tmp = 0x00; -+ -+ mutex_lock(&cxd->mutex); -+ status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1); -+ if (status < 0) -+ return status; -+ Tmp = (Tmp & ~Mask) | Value; -+ status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static int freeze_regst(struct cxd_state *cxd) -+{ -+ mutex_lock(&cxd->mutex); -+ return writereg(cxd, cxd->adrt, 1, 1); -+} -+ -+static int unfreeze_regst(struct cxd_state *cxd) -+{ -+ int status = 0; -+ -+ status = writereg(cxd, cxd->adrt, 1, 0); -+ mutex_unlock(&cxd->mutex); -+ return status; -+} -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+/* TPSData[0] [7:6] CNST[1:0] */ -+/* TPSData[0] [5:3] HIER[2:0] */ -+/* TPSData[0] [2:0] HRATE[2:0] */ -+/* TPSData[1] [7:5] LRATE[2:0] */ -+/* TPSData[1] [4:3] GI[1:0] */ -+/* TPSData[1] [2:1] MODE[1:0] */ -+/* TPSData[2] [7:6] FNUM[1:0] */ -+/* TPSData[2] [5:0] LENGTH_INDICATOR[5:0] */ -+/* TPSData[3] [7:0] CELLID[15:8] */ -+/* TPSData[4] [7:0] CELLID[7:0] */ -+/* TPSData[5] [5:0] RESERVE_EVEN[5:0] */ -+/* TPSData[6] [5:0] RESERVE_ODD[5:0] */ -+ -+static int read_tps(struct cxd_state *state, u8 *tps) -+{ -+ if (state->last_status != 0x1f) -+ return 0; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x10, 0x2f, tps, 7); -+ unfreeze_regst(state); -+ return 0; -+} -+ -+static void Active_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static void ActiveT2_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ -+ writeregt(state, 0x13, 0x83, 0x40); -+ writeregt(state, 0x13, 0x86, 0x21); -+ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); -+ writeregt(state, 0x13, 0x9F, 0xFB); -+ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static void ActiveC2_to_Sleep(struct cxd_state *state) -+{ -+ if (state->state <= Sleep) -+ return; -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+ writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ -+ writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ -+ -+ writeregt(state, 0x20, 0xC2, 0x11); -+ writebitst(state, 0x25, 0x6A, 0x02, 0x03); -+ { -+ static u8 data[3] = { 0x07, 0x61, 0x36 }; -+ writeregst(state, 0x25, 0x89, data, sizeof(data)); -+ } -+ writebitst(state, 0x25, 0xCB, 0x05, 0x07); -+ { -+ static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 }; -+ writeregst(state, 0x25, 0xDC, data, sizeof(data)); -+ } -+ writeregt(state, 0x25, 0xE2, 0x2F); -+ writeregt(state, 0x25, 0xE5, 0x2F); -+ writebitst(state, 0x27, 0x20, 0x00, 0x01); -+ writebitst(state, 0x27, 0x35, 0x00, 0x01); -+ writebitst(state, 0x27, 0xD9, 0x19, 0x3F); -+ writebitst(state, 0x2A, 0x78, 0x01, 0x07); -+ writeregt(state, 0x2A, 0x86, 0x08); -+ writeregt(state, 0x2A, 0x88, 0x14); -+ writebitst(state, 0x2B, 0x2B, 0x00, 0x1F); -+ { -+ u8 data[2] = { 0x75, 0x75 }; -+ writeregst(state, 0x2D, 0x24, data, sizeof(data)); -+ } -+ -+ writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ -+ writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ -+ writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ -+ writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ -+ state->state = Sleep; -+} -+ -+static int ConfigureTS(struct cxd_state *state, -+ enum EDemodState newDemodState) -+{ -+ int status = 0; -+ u8 OSERCKMODE = state->SerialMode ? 1 : 0; -+ u8 OSERDUTYMODE = state->SerialMode ? 1 : 0; -+ u8 OTSCKPERIOD = 8; -+ u8 OREG_CKSEL_TSIF = state->SerialMode ? -+ state->SerialClockFrequency : 0; -+ -+ if (state->SerialMode && state->SerialClockFrequency >= 3) { -+ OSERCKMODE = 2; -+ OSERDUTYMODE = 2; -+ OTSCKPERIOD = 16; -+ OREG_CKSEL_TSIF = state->SerialClockFrequency - 3; -+ } -+ writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */ -+ writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */ -+ writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */ -+ writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */ -+ /* OREG_CKSEL_TSIF */ -+ writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); -+ writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */ -+ -+ if (newDemodState == ActiveT) -+ writebitst(state, 0x10, 0x66, 0x01, 0x01); -+ if (newDemodState == ActiveC) -+ writebitst(state, 0x40, 0x66, 0x01, 0x01); -+ -+ return status; -+} -+ -+static void BandSettingT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x01, 0xE0 }; -+ u8 NF_data[] = { 0x01, 0x02 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 7: -+ { -+ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x12, 0xF8 }; -+ u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x02, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ u8 CL_data[] = { 0x1F, 0xDC }; -+ u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ case 5: -+ { -+ static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; -+ static u8 CL_data[] = { 0x26, 0x3C }; -+ static u8 NF_data[] = { 0x00, 0x03 }; -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x06, 0x07); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); -+ break; -+ } -+ } -+} -+ -+static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveT); -+ writeregx(state, 0x00, 0x17, 0x01); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */ -+ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ -+ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */ -+ writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */ -+ writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ BandSettingT(state, iffreq); -+ -+ writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void BandSettingT2(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, -+ iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ /* Timing recovery */ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ /* Add EQ Optimisation for tuner here */ -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ /* System Bandwidth */ -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ } -+ break; -+ case 7: -+ { -+ u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x02, 0x07); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ } -+ break; -+ case 5: -+ { -+ u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x06, 0x07); -+ } -+ break; -+ case 2: /* 1.7 MHz */ -+ { -+ u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC }; -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x03, 0x07); -+ } -+ break; -+ } -+} -+ -+ -+static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveT2); -+ -+ writeregx(state, 0x00, 0x17, 0x02); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ -+ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */ -+ writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */ -+ writeregt(state, 0x13, 0x86, 0x34); -+ writebitst(state, 0x13, 0x9E, 0x09, 0x0F); -+ writeregt(state, 0x13, 0x9F, 0xD8); -+ -+ BandSettingT2(state, iffreq); -+ -+ writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+ -+static void BandSettingC(struct cxd_state *state, u32 iffreq) -+{ -+ u8 data[3]; -+ -+ data[0] = (iffreq >> 16) & 0xFF; -+ data[1] = (iffreq >> 8) & 0xFF; -+ data[2] = (iffreq) & 0xFF; -+ writeregst(state, 0x10, 0xB6, data, 3); -+} -+ -+static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveC); -+ -+ writeregx(state, 0x00, 0x17, 0x04); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */ -+ writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ BandSettingC(state, iffreq); -+ -+ writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */ -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void BandSettingC2(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; -+ u8 data[2] = { 0x11, 0x9E }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x00, 0x07); -+ writeregst(state, 0x50, 0xEC, data, sizeof(data)); -+ writeregt(state, 0x50, 0xEF, 0x11); -+ writeregt(state, 0x50, 0xF1, 0x9E); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; -+ u8 data[2] = { 0x17, 0x70 }; -+ -+ writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writebitst(state, 0x10, 0xD7, 0x04, 0x07); -+ writeregst(state, 0x50, 0xEC, data, sizeof(data)); -+ writeregt(state, 0x50, 0xEF, 0x17); -+ writeregt(state, 0x50, 0xF1, 0x70); -+ } -+ break; -+ } -+} -+ -+static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq) -+{ -+ ConfigureTS(state, ActiveC2); -+ -+ writeregx(state, 0x00, 0x17, 0x05); /* Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ writeregst(state, 0x00, 0x43, data, sizeof(data)); -+ /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ -+ writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ -+ writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ -+ -+ writeregt(state, 0x20, 0xC2, 0x00); -+ writebitst(state, 0x25, 0x6A, 0x00, 0x03); -+ { -+ u8 data[3] = { 0x0C, 0xD1, 0x40 }; -+ writeregst(state, 0x25, 0x89, data, sizeof(data)); -+ } -+ writebitst(state, 0x25, 0xCB, 0x01, 0x07); -+ { -+ u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 }; -+ writeregst(state, 0x25, 0xDC, data, sizeof(data)); -+ } -+ writeregt(state, 0x25, 0xE2, 0x30); -+ writeregt(state, 0x25, 0xE5, 0x30); -+ writebitst(state, 0x27, 0x20, 0x01, 0x01); -+ writebitst(state, 0x27, 0x35, 0x01, 0x01); -+ writebitst(state, 0x27, 0xD9, 0x18, 0x3F); -+ writebitst(state, 0x2A, 0x78, 0x00, 0x07); -+ writeregt(state, 0x2A, 0x86, 0x20); -+ writeregt(state, 0x2A, 0x88, 0x32); -+ writebitst(state, 0x2B, 0x2B, 0x10, 0x1F); -+ { -+ u8 data[2] = { 0x01, 0x01 }; -+ writeregst(state, 0x2D, 0x24, data, sizeof(data)); -+ } -+ -+ BandSettingC2(state, iffreq); -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+ -+static void BandSettingIT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 IF_data[3] = { (iffreq >> 16) & 0xff, -+ (iffreq >> 8) & 0xff, iffreq & 0xff}; -+ -+ switch (state->bw) { -+ default: -+ case 8: -+ { -+ u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */ -+ u8 CL_data[] = { 0x15, 0xA8 }; -+ -+ /*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ /* Add EQ Optimisation for tuner here */ -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ -+ writeregt(state, 0x10, 0xD7, 0x00); /* System Bandwidth */ -+ /*u8 CL_data[] = { 0x13, 0xFC }; */ -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ case 7: -+ { -+ u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x1B, 0x5D }; -+ -+ /*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ -+ writeregt(state, 0x10, 0xD7, 0x02); -+ /*static u8 CL_data[] = { 0x1A, 0xFA };*/ -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ case 6: -+ { -+ u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 }; -+ u8 CL_data[] = { 0x1F, 0xEC }; -+ /*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */ -+ /*u8 CL_data[] = { 0x1F, 0x79 }; */ -+ -+ writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); -+ writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); -+ writeregt(state, 0x10, 0xD7, 0x04); -+ writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); -+ } -+ break; -+ } -+} -+ -+static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq) -+{ -+ u8 data2[3] = { 0xB9, 0xBA, 0x63 }; /* 20.5/41 MHz */ -+ /*u8 data2[3] = { 0xB7,0x1B,0x00 }; */ /* 24 MHz */ -+ u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */ -+ /*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */ -+ -+ pr_info("%s\n", __func__); -+ -+ ConfigureTS(state, ActiveIT); -+ -+ /* writeregx(state, 0x00,0x17,0x01); */ /* 2838 has only one Mode */ -+ writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ -+ writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ -+ writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ -+ writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ -+ -+ { -+ u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz, 24 MHz */ -+ /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ -+ writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ -+ } -+ writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ -+ -+ writeregst(state, 0x60, 0xA8, data2, sizeof(data2)); -+ -+ writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); -+ -+ writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */ -+ writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ -+ -+ BandSettingIT(state, iffreq); -+ -+ writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ -+ writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ -+} -+ -+static void T2_SetParameters(struct cxd_state *state) -+{ -+ u8 Profile = 0x01; /* Profile Base */ -+ u8 notT2time = 12; /* early unlock detection time */ -+ -+ if (state->T2Profile == T2P_Lite) { -+ Profile = 0x05; -+ notT2time = 40; -+ } -+ -+ if (state->plp != 0xffffffff) { -+ state->T2Profile = ((state->plp & 0x100) != 0) ? -+ T2P_Lite : T2P_Base; -+ writeregt(state, 0x23, 0xAF, state->plp); -+ writeregt(state, 0x23, 0xAD, 0x01); -+ } else { -+ state->T2Profile = T2P_Base; -+ writeregt(state, 0x23, 0xAD, 0x00); -+ } -+ -+ writebitst(state, 0x2E, 0x10, Profile, 0x07); -+ writeregt(state, 0x2B, 0x19, notT2time); -+} -+ -+static void C2_ReleasePreset(struct cxd_state *state) -+{ -+ { -+ static u8 data[2] = { 0x02, 0x80}; -+ writeregst(state, 0x27, 0xF4, data, sizeof(data)); -+ } -+ writebitst(state, 0x27, 0x51, 0x40, 0xF0); -+ writebitst(state, 0x27, 0x73, 0x07, 0x0F); -+ writebitst(state, 0x27, 0x74, 0x19, 0x3F); -+ writebitst(state, 0x27, 0x75, 0x19, 0x3F); -+ writebitst(state, 0x27, 0x76, 0x19, 0x3F); -+ if (state->bw == 6) { -+ static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA}; -+ writeregst(state, 0x20, 0x9F, data, sizeof(data)); -+ } else { -+ static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00}; -+ writeregst(state, 0x20, 0x9F, data, sizeof(data)); -+ } -+ writebitst(state, 0x27, 0xC9, 0x07, 0x07); -+ writebitst(state, 0x20, 0xC2, 0x11, 0x33); -+ { -+ static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8, -+ 0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 }; -+ writeregst(state, 0x2A, 0x20, data, sizeof(data)); -+ } -+ { -+ static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 }; -+ writeregst(state, 0x50, 0x6B, data, sizeof(data)); -+ } -+ writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */ -+} -+ -+static void C2_DemodSetting2(struct cxd_state *state) -+{ -+ u8 data[6]; -+ u32 TunePosition = -+ state->frontend.dtv_property_cache.frequency / 1000; -+ -+ if (state->bw == 6) -+ TunePosition = ((TunePosition * 1792) / 3) / 1000; -+ else -+ TunePosition = (TunePosition * 448) / 1000; -+ -+ TunePosition = ((TunePosition + 6) / 12) * 12; -+ -+ pr_info("TunePosition = %u\n", TunePosition); -+ -+ data[0] = ((TunePosition >> 16) & 0xFF); -+ data[1] = ((TunePosition >> 8) & 0xFF); -+ data[2] = (TunePosition & 0xFF); -+ data[3] = 0x02; -+ data[4] = (state->DataSliceID & 0xFF); -+ data[5] = (state->plp & 0xFF); -+ writeregst(state, 0x50, 0x7A, data, sizeof(data)); -+ writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */ -+} -+ -+static void Stop(struct cxd_state *state) -+{ -+ -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ -+} -+ -+static void ShutDown(struct cxd_state *state) -+{ -+ switch (state->state) { -+ case ActiveT2: -+ ActiveT2_to_Sleep(state); -+ break; -+ case ActiveC2: -+ ActiveC2_to_Sleep(state); -+ break; -+ default: -+ Active_to_Sleep(state); -+ break; -+ } -+} -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01); -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ Stop(state); -+ ShutDown(state); -+ kfree(state); -+} -+ -+static int Start(struct cxd_state *state, u32 IntermediateFrequency) -+{ -+ enum EDemodState newDemodState = Unknown; -+ u32 iffreq; -+ -+ if (state->state < Sleep) -+ return -EINVAL; -+ -+ iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000); -+ -+ switch (state->omode) { -+ case OM_DVBT: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveT; -+ break; -+ case OM_DVBT2: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveT2; -+ break; -+ case OM_DVBC: -+ case OM_QAM_ITU_C: -+ if (state->type == CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveC; -+ break; -+ case OM_DVBC2: -+ if (state->type != CXD2843) -+ return -EINVAL; -+ newDemodState = ActiveC2; -+ break; -+ case OM_ISDBT: -+ if (state->type != CXD2838) -+ return -EINVAL; -+ newDemodState = ActiveIT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ state->LockTimeout = 0; -+ state->TSLockTimeout = 0; -+ state->L1PostTimeout = 0; -+ state->last_status = 0; -+ state->FirstTimeLock = 1; -+ state->LastBERNominator = 0; -+ state->LastBERDenominator = 1; -+ state->BERScaleMax = 19; -+ -+ if (state->state == newDemodState) { -+ writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS Output */ -+ switch (newDemodState) { -+ case ActiveT: -+ /* Stick with HP ( 0x01 = LP ) */ -+ writeregt(state, 0x10, 0x67, 0x00); -+ BandSettingT(state, iffreq); -+ state->BERScaleMax = 18; -+ break; -+ case ActiveT2: -+ T2_SetParameters(state); -+ BandSettingT2(state, iffreq); -+ state->BERScaleMax = 12; -+ break; -+ case ActiveC: -+ BandSettingC(state, iffreq); -+ state->BERScaleMax = 19; -+ break; -+ case ActiveC2: -+ BandSettingC2(state, iffreq); -+ C2_ReleasePreset(state); -+ C2_DemodSetting2(state); -+ break; -+ case ActiveIT: -+ BandSettingIT(state, iffreq); -+ break; -+ default: -+ break; -+ } -+ } else { -+ if (state->state > Sleep) { -+ switch (state->state) { -+ case ActiveT2: -+ ActiveT2_to_Sleep(state); -+ break; -+ case ActiveC2: -+ ActiveC2_to_Sleep(state); -+ break; -+ default: -+ Active_to_Sleep(state); -+ break; -+ } -+ } -+ switch (newDemodState) { -+ case ActiveT: -+ /* Stick with HP ( 0x01 = LP ) */ -+ writeregt(state, 0x10, 0x67, 0x00); -+ Sleep_to_ActiveT(state, iffreq); -+ state->BERScaleMax = 18; -+ break; -+ case ActiveT2: -+ T2_SetParameters(state); -+ Sleep_to_ActiveT2(state, iffreq); -+ state->BERScaleMax = 12; -+ break; -+ case ActiveC: -+ Sleep_to_ActiveC(state, iffreq); -+ state->BERScaleMax = 19; -+ break; -+ case ActiveC2: -+ Sleep_to_ActiveC2(state, iffreq); -+ C2_ReleasePreset(state); -+ C2_DemodSetting2(state); -+ break; -+ case ActiveIT: -+ Sleep_to_ActiveIT(state, iffreq); -+ break; -+ default: -+ break; -+ } -+ } -+ state->state = newDemodState; -+ writeregt(state, 0x00, 0xFE, 0x01); /* SW Reset */ -+ writeregt(state, 0x00, 0xC3, 0x00); /* Enable TS Output */ -+ -+ return 0; -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat; -+ struct cxd_state *state = fe->demodulator_priv; -+ u32 IF; -+ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ state->omode = OM_DVBC; -+ break; -+ case SYS_DVBT: -+ state->omode = OM_DVBT; -+ break; -+ case SYS_DVBT2: -+ state->omode = OM_DVBT2; -+ break; -+ case SYS_ISDBT: -+ state->omode = OM_ISDBT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; -+ state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000; -+ if (fe->dtv_property_cache.stream_id == 0xffffffff) { -+ state->DataSliceID = 0xffffffff; -+ state->plp = 0xffffffff; -+ } else { -+ state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8) -+ & 0xff; -+ state->plp = fe->dtv_property_cache.stream_id & 0xff; -+ } -+ /* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */ -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ stat = Start(state, IF); -+ return stat; -+} -+ -+ -+static void init(struct cxd_state *state) -+{ -+ u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */ -+ -+ state->omode = OM_NONE; -+ state->state = Unknown; -+ -+ writeregx(state, 0xFF, 0x02, 0x00); -+ usleep_range(4000, 5000); -+ writeregx(state, 0x00, 0x15, 0x01); -+ if (state->type != CXD2838) -+ writeregx(state, 0x00, 0x17, 0x01); -+ usleep_range(4000, 5000); -+ -+ writeregx(state, 0x00, 0x10, 0x01); -+ -+ writeregsx(state, 0x00, 0x13, data, 2); -+ writeregx(state, 0x00, 0x15, 0x00); -+ usleep_range(3000, 4000); -+ writeregx(state, 0x00, 0x10, 0x00); -+ usleep_range(2000, 3000); -+ -+ state->curbankx = 0xFF; -+ state->curbankt = 0xFF; -+ -+ writeregt(state, 0x00, 0x43, 0x0A); -+ writeregt(state, 0x00, 0x41, 0x0A); -+ if (state->type == CXD2838) -+ writeregt(state, 0x60, 0x5A, 0x00); -+ -+ writebitst(state, 0x10, 0xCB, 0x00, 0x40); -+ writeregt(state, 0x10, 0xCD, state->IF_FS); -+ -+ writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98); -+ writebitst(state, 0x00, 0xC5, 0x01, 0x07); -+ writebitst(state, 0x00, 0xCB, 0x00, 0x01); -+ writebitst(state, 0x00, 0xC6, 0x00, 0x1D); -+ writebitst(state, 0x00, 0xC8, 0x01, 0x1D); -+ writebitst(state, 0x00, 0xC9, 0x00, 0x1D); -+ writebitst(state, 0x00, 0x83, 0x00, 0x07); -+ writeregt(state, 0x00, 0x84, 0x00); -+ writebitst(state, 0x00, 0xD3, -+ (state->type == CXD2838) ? 0x01 : 0x00, 0x01); -+ writebitst(state, 0x00, 0xDE, 0x00, 0x01); -+ -+ state->state = Sleep; -+} -+ -+ -+static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) -+{ -+ state->adrt = cfg->adr; -+ state->adrx = cfg->adr + 0x02; -+ state->curbankt = 0xff; -+ state->curbankx = 0xff; -+ mutex_init(&state->mutex); -+ -+ state->SerialMode = cfg->parallel ? 0 : 1; -+ state->ContinuousClock = 1; -+ state->SerialClockFrequency = -+ (cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ? -+ cfg->ts_clock : 1; /* 1 = fastest (82 MBit/s), 5 = slowest */ -+ state->SerialClockFrequency = 1; -+ /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ -+ state->IF_FS = 0x50; -+} -+ -+static int get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ case SYS_DVBC_ANNEX_C: -+ /*return c_get_tune_settings(fe, sets);*/ -+ default: -+ /* DVB-T: Use info.frequency_stepsize. */ -+ return -EINVAL; -+ } -+} -+ -+static int read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ u8 rdata; -+ -+ *status = 0; -+ switch (state->state) { -+ case ActiveC: -+ readregst(state, 0x40, 0x88, &rdata, 1); -+ if (rdata & 0x02) -+ break; -+ if (rdata & 0x01) { -+ *status |= 0x07; -+ readregst(state, 0x40, 0x10, &rdata, 1); -+ if (rdata & 0x20) -+ *status |= 0x1f; -+ } -+ break; -+ case ActiveT: -+ readregst(state, 0x10, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= 0x07; -+ if (rdata & 0x20) -+ *status |= 0x1f; -+ } -+ break; -+ case ActiveT2: -+ readregst(state, 0x20, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= 0x07; -+ if (rdata & 0x20) -+ *status |= 0x08; -+ } -+ if (*status & 0x08) { -+ readregst(state, 0x22, 0x12, &rdata, 1); -+ if (rdata & 0x01) -+ *status |= 0x10; -+ } -+ break; -+ case ActiveC2: -+ readregst(state, 0x20, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if ((rdata & 0x07) == 0x06) { -+ *status |= 0x07; -+ if (rdata & 0x20) -+ *status |= 0x18; -+ } -+ if ((*status & 0x10) && state->FirstTimeLock) { -+ u8 data; -+ -+ /* Change1stTrial */ -+ readregst(state, 0x28, 0xE6, &rdata, 1); -+ data = rdata & 1; -+ readregst(state, 0x50, 0x15, &rdata, 1); -+ data |= ((rdata & 0x18) >> 2); -+ /*writebitst(state, 0x50,0x6F,rdata,0x07);*/ -+ state->FirstTimeLock = 0; -+ } -+ break; -+ case ActiveIT: -+ readregst(state, 0x60, 0x10, &rdata, 1); -+ if (rdata & 0x10) -+ break; -+ if (rdata & 0x02) { -+ *status |= 0x07; -+ if (rdata & 0x01) -+ *status |= 0x18; -+ } -+ break; -+ default: -+ break; -+ } -+ state->last_status = *status; -+ return 0; -+} -+ -+static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ u8 BERRegs[3]; -+ u8 Scale; -+ -+ *n = 0; -+ *d = 1; -+ -+ readregst(state, 0x10, 0x62, BERRegs, 3); -+ readregst(state, 0x10, 0x60, &Scale, 1); -+ Scale &= 0x1F; -+ -+ if (BERRegs[0] & 0x80) { -+ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | -+ (((u32) BERRegs[1]) << 8) | BERRegs[2]; -+ state->LastBERDenominator = 1632 << Scale; -+ if (state->LastBERNominator < 256 && -+ Scale < state->BERScaleMax) { -+ writebitst(state, 0x10, 0x60, Scale + 1, 0x1F); -+ } else if (state->LastBERNominator > 512 && Scale > 11) -+ writebitst(state, 0x10, 0x60, Scale - 1, 0x1F); -+ } -+ *n = state->LastBERNominator; -+ *d = state->LastBERDenominator; -+ -+ return 0; -+} -+ -+static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ u8 BERRegs[3]; -+ u8 Scale; -+ -+ *n = 0; -+ *d = 1; -+ -+ readregst(state, 0x40, 0x62, BERRegs, 3); -+ readregst(state, 0x40, 0x60, &Scale, 1); -+ Scale &= 0x1F; -+ -+ if (BERRegs[0] & 0x80) { -+ state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | -+ (((u32) BERRegs[1]) << 8) | BERRegs[2]; -+ state->LastBERDenominator = 1632 << Scale; -+ if (state->LastBERNominator < 256 && -+ Scale < state->BERScaleMax) { -+ writebitst(state, 0x40, 0x60, Scale + 1, 0x1F); -+ } else if (state->LastBERNominator > 512 && Scale > 11) -+ writebitst(state, 0x40, 0x60, Scale - 1, 0x1F); -+ } -+ *n = state->LastBERNominator; -+ *d = state->LastBERDenominator; -+ -+ return 0; -+} -+ -+static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) -+{ -+ *n = 0; -+ *d = 1; -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ u32 n, d; -+ int s = 0; -+ -+ *ber = 0; -+ switch (state->state) { -+ case ActiveT: -+ s = get_ber_t(state, &n, &d); -+ break; -+ case ActiveT2: -+ s = get_ber_t2(state, &n, &d); -+ break; -+ case ActiveC: -+ s = get_ber_c(state, &n, &d); -+ break; -+ case ActiveC2: -+ s = get_ber_c2(state, &n, &d); -+ break; -+ case ActiveIT: -+ s = get_ber_it(state, &n, &d); -+ break; -+ default: -+ break; -+ } -+ if (s) -+ return s; -+ -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ if (fe->ops.tuner_ops.get_rf_strength) -+ fe->ops.tuner_ops.get_rf_strength(fe, strength); -+ else -+ *strength = 0; -+ return 0; -+} -+ -+static s32 Log10x100(u32 x) -+{ -+ static u32 LookupTable[100] = { -+ 101157945, 103514217, 105925373, 108392691, 110917482, -+ 113501082, 116144861, 118850223, 121618600, 124451461, -+ 127350308, 130316678, 133352143, 136458314, 139636836, -+ 142889396, 146217717, 149623566, 153108746, 156675107, -+ 160324539, 164058977, 167880402, 171790839, 175792361, -+ 179887092, 184077200, 188364909, 192752491, 197242274, -+ 201836636, 206538016, 211348904, 216271852, 221309471, -+ 226464431, 231739465, 237137371, 242661010, 248313311, -+ 254097271, 260015956, 266072506, 272270131, 278612117, -+ 285101827, 291742701, 298538262, 305492111, 312607937, -+ 319889511, 327340695, 334965439, 342767787, 350751874, -+ 358921935, 367282300, 375837404, 384591782, 393550075, -+ 402717034, 412097519, 421696503, 431519077, 441570447, -+ 451855944, 462381021, 473151259, 484172368, 495450191, -+ 506990708, 518800039, 530884444, 543250331, 555904257, -+ 568852931, 582103218, 595662144, 609536897, 623734835, -+ 638263486, 653130553, 668343918, 683911647, 699841996, -+ 716143410, 732824533, 749894209, 767361489, 785235635, -+ 803526122, 822242650, 841395142, 860993752, 881048873, -+ 901571138, 922571427, 944060876, 966050879, 988553095, -+ }; -+ s32 y; -+ int i; -+ -+ if (x == 0) -+ return 0; -+ y = 800; -+ if (x >= 1000000000) { -+ x /= 10; -+ y += 100; -+ } -+ -+ while (x < 100000000) { -+ x *= 10; -+ y -= 100; -+ } -+ i = 0; -+ while (i < 100 && x > LookupTable[i]) -+ i += 1; -+ y += i; -+ return y; -+} -+ -+#if 0 -+static void GetPLPIds(struct cxd_state *state, u32 nValues, -+ u8 *Values, u32 *Returned) -+{ -+ u8 nPids = 0; -+ -+ *Returned = 0; -+ if (state->state != ActiveT2) -+ return; -+ if (state->last_status != 0x1f) -+ return; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x22, 0x7F, &nPids, 1); -+ -+ Values[0] = nPids; -+ if (nPids >= nValues) -+ nPids = nValues - 1; -+ -+ readregst_unlocked(state, 0x22, 0x80, &Values[1], -+ nPids > 128 ? 128 : nPids); -+ -+ if (nPids > 128) -+ readregst_unlocked(state, 0x23, 0x10, &Values[129], -+ nPids - 128); -+ -+ *Returned = nPids + 1; -+ -+ unfreeze_regst(state); -+} -+#endif -+ -+static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 51441) -+ reg = 51441; -+ -+ if (state->bw == 8) { -+ if (reg > 1143) -+ reg = 1143; -+ *SignalToNoise = (Log10x100(reg) - -+ Log10x100(1200 - reg)) + 220; -+ } else -+ *SignalToNoise = Log10x100(reg) - 90; -+} -+ -+static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 51441) -+ reg = 51441; -+ -+ *SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384; -+} -+ -+ -+static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 10876) -+ reg = 10876; -+ -+ *SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320; -+} -+ -+static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise) -+{ -+ u8 Data[2]; -+ u32 reg; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = (Data[0] << 8) | Data[1]; -+ if (reg > 4996) -+ reg = 4996; -+ -+ *SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285; -+} -+ -+static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise) -+{ -+ u8 Data[2]; -+ u8 Constellation = 0; -+ u32 reg; -+ -+ *SignalToNoise = 0; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x40, 0x19, &Constellation, 1); -+ readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data)); -+ unfreeze_regst(state); -+ -+ reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]); -+ if (reg == 0) -+ return; -+ -+ switch (Constellation & 0x07) { -+ case 0: /* QAM 16 */ -+ case 2: /* QAM 64 */ -+ case 4: /* QAM 256 */ -+ if (reg < 126) -+ reg = 126; -+ *SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000; -+ break; -+ case 1: /* QAM 32 */ -+ case 3: /* QAM 128 */ -+ if (reg < 69) -+ reg = 69; -+ *SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000; -+ break; -+ } -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ u32 SNR = 0; -+ -+ *snr = 0; -+ if (state->last_status != 0x1f) -+ return 0; -+ -+ switch (state->state) { -+ case ActiveC: -+ GetSignalToNoiseC(state, &SNR); -+ break; -+ case ActiveC2: -+ GetSignalToNoiseC2(state, &SNR); -+ break; -+ case ActiveT: -+ GetSignalToNoiseT(state, &SNR); -+ break; -+ case ActiveT2: -+ GetSignalToNoiseT2(state, &SNR); -+ break; -+ case ActiveIT: -+ GetSignalToNoiseIT(state, &SNR); -+ break; -+ default: -+ break; -+ } -+ *snr = SNR; -+ return 0; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ *ucblocks = 0; -+ return 0; -+} -+ -+static int tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, fe_status_t *status) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ int r; -+ -+ if (re_tune) { -+ r = set_parameters(fe); -+ if (r) -+ return r; -+ state->tune_time = jiffies; -+ -+ } -+ if (*status & FE_HAS_LOCK) -+ return 0; -+ /* *delay = 50; */ -+ r = read_status(fe, status); -+ if (r) -+ return r; -+ return 0; -+} -+ -+static enum dvbfe_search search(struct dvb_frontend *fe) -+{ -+ int r; -+ u32 loops = 20, i; -+ fe_status_t status; -+ -+ r = set_parameters(fe); -+ -+ for (i = 0; i < loops; i++) { -+ msleep(50); -+ r = read_status(fe, &status); -+ if (r) -+ return DVBFE_ALGO_SEARCH_ERROR; -+ if (status & FE_HAS_LOCK) -+ break; -+ } -+ -+ if (status & FE_HAS_LOCK) -+ return DVBFE_ALGO_SEARCH_SUCCESS; -+ else -+ return DVBFE_ALGO_SEARCH_AGAIN; -+} -+ -+static int get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+static int get_fe_t(struct cxd_state *state) -+{ -+ struct dvb_frontend *fe = &state->frontend; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u8 tps[7]; -+ -+ read_tps(state, tps); -+ -+/* TPSData[0] [7:6] CNST[1:0] -+ TPSData[0] [5:3] HIER[2:0] -+ TPSData[0] [2:0] HRATE[2:0] -+*/ -+ switch ((tps[0] >> 6) & 0x03) { -+ case 0: -+ p->modulation = QPSK; -+ break; -+ case 1: -+ p->modulation = QAM_16; -+ break; -+ case 2: -+ p->modulation = QAM_64; -+ break; -+ } -+ switch ((tps[0] >> 3) & 0x07) { -+ case 0: -+ p->hierarchy = HIERARCHY_NONE; -+ break; -+ case 1: -+ p->hierarchy = HIERARCHY_1; -+ break; -+ case 2: -+ p->hierarchy = HIERARCHY_2; -+ break; -+ case 3: -+ p->hierarchy = HIERARCHY_4; -+ break; -+ } -+ switch ((tps[0] >> 0) & 0x07) { -+ case 0: -+ p->code_rate_HP = FEC_1_2; -+ break; -+ case 1: -+ p->code_rate_HP = FEC_2_3; -+ break; -+ case 2: -+ p->code_rate_HP = FEC_3_4; -+ break; -+ case 3: -+ p->code_rate_HP = FEC_5_6; -+ break; -+ case 4: -+ p->code_rate_HP = FEC_7_8; -+ break; -+ } -+ -+/* TPSData[1] [7:5] LRATE[2:0] -+ TPSData[1] [4:3] GI[1:0] -+ TPSData[1] [2:1] MODE[1:0] -+*/ -+ switch ((tps[1] >> 5) & 0x07) { -+ case 0: -+ p->code_rate_LP = FEC_1_2; -+ break; -+ case 1: -+ p->code_rate_LP = FEC_2_3; -+ break; -+ case 2: -+ p->code_rate_LP = FEC_3_4; -+ break; -+ case 3: -+ p->code_rate_LP = FEC_5_6; -+ break; -+ case 4: -+ p->code_rate_LP = FEC_7_8; -+ break; -+ } -+ switch ((tps[1] >> 3) & 0x03) { -+ case 0: -+ p->guard_interval = GUARD_INTERVAL_1_32; -+ break; -+ case 1: -+ p->guard_interval = GUARD_INTERVAL_1_16; -+ break; -+ case 2: -+ p->guard_interval = GUARD_INTERVAL_1_8; -+ break; -+ case 3: -+ p->guard_interval = GUARD_INTERVAL_1_4; -+ break; -+ } -+ switch ((tps[1] >> 1) & 0x03) { -+ case 0: -+ p->transmission_mode = TRANSMISSION_MODE_2K; -+ break; -+ case 1: -+ p->transmission_mode = TRANSMISSION_MODE_8K; -+ break; -+ } -+ -+ return 0; -+} -+ -+static int get_fe_c(struct cxd_state *state) -+{ -+ struct dvb_frontend *fe = &state->frontend; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ u8 qam; -+ -+ freeze_regst(state); -+ readregst_unlocked(state, 0x40, 0x19, &qam, 1); -+ unfreeze_regst(state); -+ p->modulation = qam & 0x07; -+ return 0; -+} -+ -+static int get_frontend(struct dvb_frontend *fe) -+{ -+ struct cxd_state *state = fe->demodulator_priv; -+ -+ if (state->last_status != 0x1f) -+ return 0; -+ -+ switch (state->state) { -+ case ActiveT: -+ get_fe_t(state); -+ break; -+ case ActiveT2: -+ break; -+ case ActiveC: -+ get_fe_c(state); -+ break; -+ case ActiveC2: -+ break; -+ case ActiveIT: -+ break; -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static struct dvb_frontend_ops common_ops_2843 = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, -+ .info = { -+ .name = "CXD2843 DVB-C/C2 DVB-T/T2", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = /* DVB-C */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_FEC_AUTO | -+ /* DVB-T */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .get_tune_settings = get_tune_settings, -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+ .get_frontend = get_frontend, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static struct dvb_frontend_ops common_ops_2837 = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, -+ .info = { -+ .name = "CXD2837 DVB-C DVB-T/T2", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = /* DVB-C */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_FEC_AUTO | -+ /* DVB-T */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .get_tune_settings = get_tune_settings, -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+ .get_frontend = get_frontend, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static struct dvb_frontend_ops common_ops_2838 = { -+ .delsys = { SYS_ISDBT }, -+ .info = { -+ .name = "CXD2838 ISDB-T", -+ .frequency_stepsize = 166667, -+ .frequency_min = 47000000, -+ .frequency_max = 865000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ .set_frontend = set_parameters, -+ -+ .get_tune_settings = get_tune_settings, -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+#ifdef USE_ALGO -+ .get_frontend_algo = get_algo, -+ .search = search, -+ .tune = tune, -+#endif -+}; -+ -+static int probe(struct cxd_state *state) -+{ -+ u8 ChipID = 0x00; -+ int status; -+ -+ status = readregst(state, 0x00, 0xFD, &ChipID, 1); -+ -+ if (status) -+ status = readregsx(state, 0x00, 0xFD, &ChipID, 1); -+ if (status) -+ return status; -+ -+ /*printk("ChipID = %02X\n", ChipID);*/ -+ switch (ChipID) { -+ case 0xa4: -+ state->type = CXD2843; -+ memcpy(&state->frontend.ops, &common_ops_2843, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ case 0xb1: -+ state->type = CXD2837; -+ memcpy(&state->frontend.ops, &common_ops_2837, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ case 0xb0: -+ state->type = CXD2838; -+ memcpy(&state->frontend.ops, &common_ops_2838, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ default: -+ return -1; -+ } -+ state->frontend.demodulator_priv = state; -+ return 0; -+} -+ -+struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg) -+{ -+ struct cxd_state *state = NULL; -+ -+ state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->i2c = i2c; -+ init_state(state, cfg); -+ if (probe(state) == 0) { -+ init(state); -+ return &state->frontend; -+ } -+ pr_err("cxd2843: not found\n"); -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(cxd2843_attach); -+ -+MODULE_DESCRIPTION("CXD2843/37/38 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h -new file mode 100644 -index 0000000..f3e355b ---- /dev/null -+++ b/drivers/media/dvb-frontends/cxd2843.h -@@ -0,0 +1,30 @@ -+#ifndef _CXD2843_H_ -+#define _CXD2843_H_ -+ -+#include -+#include -+ -+struct cxd2843_cfg { -+ u8 adr; -+ u32 ts_clock; -+ u8 parallel; -+}; -+ -+#if defined(CONFIG_DVB_CXD2843) || \ -+ (defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE)) -+ -+extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg); -+ -+#else -+ -+static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, -+ struct cxd2843_cfg *cfg) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif -+ -+#endif -diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c -index d46cf5f..91a7f9f 100644 ---- a/drivers/media/dvb-frontends/drxk_hard.c -+++ b/drivers/media/dvb-frontends/drxk_hard.c -@@ -21,8 +21,6 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- - #include - #include - #include -@@ -30,42 +28,50 @@ - #include - #include - #include --#include - #include - - #include "dvb_frontend.h" - #include "drxk.h" - #include "drxk_hard.h" --#include "dvb_math.h" -- --static int power_down_dvbt(struct drxk_state *state, bool set_power_mode); --static int power_down_qam(struct drxk_state *state); --static int set_dvbt_standard(struct drxk_state *state, -- enum operation_mode o_mode); --static int set_qam_standard(struct drxk_state *state, -- enum operation_mode o_mode); --static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, -- s32 tuner_freq_offset); --static int set_dvbt_standard(struct drxk_state *state, -- enum operation_mode o_mode); --static int dvbt_start(struct drxk_state *state); --static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, -- s32 tuner_freq_offset); --static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status); --static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status); --static int switch_antenna_to_qam(struct drxk_state *state); --static int switch_antenna_to_dvbt(struct drxk_state *state); -- --static bool is_dvbt(struct drxk_state *state) -+ -+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode); -+static int PowerDownQAM(struct drxk_state *state); -+static int SetDVBTStandard(struct drxk_state *state, -+ enum OperationMode oMode); -+static int SetQAMStandard(struct drxk_state *state, -+ enum OperationMode oMode); -+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, -+ s32 tunerFreqOffset); -+static int SetDVBTStandard(struct drxk_state *state, -+ enum OperationMode oMode); -+static int DVBTStart(struct drxk_state *state); -+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, -+ s32 tunerFreqOffset); -+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus); -+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus); -+static int SwitchAntennaToQAM(struct drxk_state *state); -+static int SwitchAntennaToDVBT(struct drxk_state *state); -+ -+static bool IsDVBT(struct drxk_state *state) -+{ -+ return state->m_OperationMode == OM_DVBT; -+} -+ -+static bool IsQAM(struct drxk_state *state) -+{ -+ return state->m_OperationMode == OM_QAM_ITU_A || -+ state->m_OperationMode == OM_QAM_ITU_B || -+ state->m_OperationMode == OM_QAM_ITU_C; -+} -+ -+bool IsA1WithPatchCode(struct drxk_state *state) - { -- return state->m_operation_mode == OM_DVBT; -+ return state->m_DRXK_A1_PATCH_CODE; - } - --static bool is_qam(struct drxk_state *state) -+bool IsA1WithRomCode(struct drxk_state *state) - { -- return state->m_operation_mode == OM_QAM_ITU_A || -- state->m_operation_mode == OM_QAM_ITU_B || -- state->m_operation_mode == OM_QAM_ITU_C; -+ return state->m_DRXK_A1_ROM_CODE; - } - - #define NOA1ROM 0 -@@ -166,9 +172,9 @@ static unsigned int debug; - module_param(debug, int, 0644); - MODULE_PARM_DESC(debug, "enable debug messages"); - --#define dprintk(level, fmt, arg...) do { \ --if (debug >= level) \ -- printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg); \ -+#define dprintk(level, fmt, arg...) do { \ -+if (debug >= level) \ -+ printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg); \ - } while (0) - - -@@ -182,17 +188,15 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c) - return (u32) tmp64; - } - --static inline u32 Frac28a(u32 a, u32 c) -+inline u32 Frac28a(u32 a, u32 c) - { - int i = 0; - u32 Q1 = 0; - u32 R0 = 0; - - R0 = (a % c) << 4; /* 32-28 == 4 shifts possible at max */ -- Q1 = a / c; /* -- * integer part, only the 4 least significant -- * bits will be visible in the result -- */ -+ Q1 = a / c; /* integer part, only the 4 least significant bits -+ will be visible in the result */ - - /* division using radix 16, 7 nibbles in the result */ - for (i = 0; i < 7; i++) { -@@ -206,51 +210,114 @@ static inline u32 Frac28a(u32 a, u32 c) - return Q1; - } - --static inline u32 log10times100(u32 value) -+static u32 Log10Times100(u32 x) - { -- return (100L * intlog10(value)) >> 24; --} -- --/****************************************************************************/ --/* I2C **********************************************************************/ --/****************************************************************************/ -+ static const u8 scale = 15; -+ static const u8 indexWidth = 5; -+ u8 i = 0; -+ u32 y = 0; -+ u32 d = 0; -+ u32 k = 0; -+ u32 r = 0; -+ /* -+ log2lut[n] = (1<i2c); -- state->drxk_i2c_exclusive_lock = true; -+ static const u32 log2lut[] = { -+ 0, /* 0.000000 */ -+ 290941, /* 290941.300628 */ -+ 573196, /* 573196.476418 */ -+ 847269, /* 847269.179851 */ -+ 1113620, /* 1113620.489452 */ -+ 1372674, /* 1372673.576986 */ -+ 1624818, /* 1624817.752104 */ -+ 1870412, /* 1870411.981536 */ -+ 2109788, /* 2109787.962654 */ -+ 2343253, /* 2343252.817465 */ -+ 2571091, /* 2571091.461923 */ -+ 2793569, /* 2793568.696416 */ -+ 3010931, /* 3010931.055901 */ -+ 3223408, /* 3223408.452106 */ -+ 3431216, /* 3431215.635215 */ -+ 3634553, /* 3634553.498355 */ -+ 3833610, /* 3833610.244726 */ -+ 4028562, /* 4028562.434393 */ -+ 4219576, /* 4219575.925308 */ -+ 4406807, /* 4406806.721144 */ -+ 4590402, /* 4590401.736809 */ -+ 4770499, /* 4770499.491025 */ -+ 4947231, /* 4947230.734179 */ -+ 5120719, /* 5120719.018555 */ -+ 5291081, /* 5291081.217197 */ -+ 5458428, /* 5458427.996830 */ -+ 5622864, /* 5622864.249668 */ -+ 5784489, /* 5784489.488298 */ -+ 5943398, /* 5943398.207380 */ -+ 6099680, /* 6099680.215452 */ -+ 6253421, /* 6253420.939751 */ -+ 6404702, /* 6404701.706649 */ -+ 6553600, /* 6553600.000000 */ -+ }; - -- return 0; --} - --static void drxk_i2c_unlock(struct drxk_state *state) --{ -- if (!state->drxk_i2c_exclusive_lock) -- return; -+ if (x == 0) -+ return 0; - -- i2c_unlock_adapter(state->i2c); -- state->drxk_i2c_exclusive_lock = false; -+ /* Scale x (normalize) */ -+ /* computing y in log(x/y) = log(x) - log(y) */ -+ if ((x & ((0xffffffff) << (scale + 1))) == 0) { -+ for (k = scale; k > 0; k--) { -+ if (x & (((u32) 1) << scale)) -+ break; -+ x <<= 1; -+ } -+ } else { -+ for (k = scale; k < 31; k++) { -+ if ((x & (((u32) (-1)) << (scale + 1))) == 0) -+ break; -+ x >>= 1; -+ } -+ } -+ /* -+ Now x has binary point between bit[scale] and bit[scale-1] -+ and 1.0 <= x < 2.0 */ -+ -+ /* correction for divison: log(x) = log(x/y)+log(y) */ -+ y = k * ((((u32) 1) << scale) * 200); -+ -+ /* remove integer part */ -+ x &= ((((u32) 1) << scale) - 1); -+ /* get index */ -+ i = (u8) (x >> (scale - indexWidth)); -+ /* compute delta (x - a) */ -+ d = x & ((((u32) 1) << (scale - indexWidth)) - 1); -+ /* compute log, multiplication (d* (..)) must be within range ! */ -+ y += log2lut[i] + -+ ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth)); -+ /* Conver to log10() */ -+ y /= 108853; /* (log2(10) << scale) */ -+ r = (y >> 1); -+ /* rounding */ -+ if (y & ((u32) 1)) -+ r++; -+ return r; - } - --static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs, -- unsigned len) --{ -- if (state->drxk_i2c_exclusive_lock) -- return __i2c_transfer(state->i2c, msgs, len); -- else -- return i2c_transfer(state->i2c, msgs, len); --} -+/****************************************************************************/ -+/* I2C **********************************************************************/ -+/****************************************************************************/ - --static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val) -+static int i2c_read1(struct i2c_adapter *adapter, u8 adr, u8 *val) - { - struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD, - .buf = val, .len = 1} - }; - -- return drxk_i2c_transfer(state, msgs, 1); -+ return i2c_transfer(adapter, msgs, 1); - } - --static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) - { - int status; - struct i2c_msg msg = { -@@ -260,20 +327,20 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) - if (debug > 2) { - int i; - for (i = 0; i < len; i++) -- pr_cont(" %02x", data[i]); -- pr_cont("\n"); -+ printk(KERN_CONT " %02x", data[i]); -+ printk(KERN_CONT "\n"); - } -- status = drxk_i2c_transfer(state, &msg, 1); -+ status = i2c_transfer(adap, &msg, 1); - if (status >= 0 && status != 1) - status = -EIO; - - if (status < 0) -- pr_err("i2c write error at addr 0x%02x\n", adr); -+ printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr); - - return status; - } - --static int i2c_read(struct drxk_state *state, -+static int i2c_read(struct i2c_adapter *adap, - u8 adr, u8 *msg, int len, u8 *answ, int alen) - { - int status; -@@ -284,25 +351,25 @@ static int i2c_read(struct drxk_state *state, - .buf = answ, .len = alen} - }; - -- status = drxk_i2c_transfer(state, msgs, 2); -+ status = i2c_transfer(adap, msgs, 2); - if (status != 2) { - if (debug > 2) -- pr_cont(": ERROR!\n"); -+ printk(KERN_CONT ": ERROR!\n"); - if (status >= 0) - status = -EIO; - -- pr_err("i2c read error at addr 0x%02x\n", adr); -+ printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr); - return status; - } - if (debug > 2) { - int i; - dprintk(2, ": read from"); - for (i = 0; i < len; i++) -- pr_cont(" %02x", msg[i]); -- pr_cont(", value = "); -+ printk(KERN_CONT " %02x", msg[i]); -+ printk(KERN_CONT ", value = "); - for (i = 0; i < alen; i++) -- pr_cont(" %02x", answ[i]); -- pr_cont("\n"); -+ printk(KERN_CONT " %02x", answ[i]); -+ printk(KERN_CONT "\n"); - } - return 0; - } -@@ -327,7 +394,7 @@ static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags) - len = 2; - } - dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); -- status = i2c_read(state, adr, mm1, len, mm2, 2); -+ status = i2c_read(state->i2c, adr, mm1, len, mm2, 2); - if (status < 0) - return status; - if (data) -@@ -361,7 +428,7 @@ static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags) - len = 2; - } - dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); -- status = i2c_read(state, adr, mm1, len, mm2, 4); -+ status = i2c_read(state->i2c, adr, mm1, len, mm2, 4); - if (status < 0) - return status; - if (data) -@@ -397,7 +464,7 @@ static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags) - mm[len + 1] = (data >> 8) & 0xff; - - dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags); -- return i2c_write(state, adr, mm, len + 2); -+ return i2c_write(state->i2c, adr, mm, len + 2); - } - - static int write16(struct drxk_state *state, u32 reg, u16 data) -@@ -428,7 +495,7 @@ static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags) - mm[len + 3] = (data >> 24) & 0xff; - dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags); - -- return i2c_write(state, adr, mm, len + 4); -+ return i2c_write(state->i2c, adr, mm, len + 4); - } - - static int write32(struct drxk_state *state, u32 reg, u32 data) -@@ -436,55 +503,55 @@ static int write32(struct drxk_state *state, u32 reg, u32 data) - return write32_flags(state, reg, data, 0); - } - --static int write_block(struct drxk_state *state, u32 address, -- const int block_size, const u8 p_block[]) -+static int write_block(struct drxk_state *state, u32 Address, -+ const int BlockSize, const u8 pBlock[]) - { -- int status = 0, blk_size = block_size; -- u8 flags = 0; -+ int status = 0, BlkSize = BlockSize; -+ u8 Flags = 0; - - if (state->single_master) -- flags |= 0xC0; -- -- while (blk_size > 0) { -- int chunk = blk_size > state->m_chunk_size ? -- state->m_chunk_size : blk_size; -- u8 *adr_buf = &state->chunk[0]; -- u32 adr_length = 0; -- -- if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) { -- adr_buf[0] = (((address << 1) & 0xFF) | 0x01); -- adr_buf[1] = ((address >> 16) & 0xFF); -- adr_buf[2] = ((address >> 24) & 0xFF); -- adr_buf[3] = ((address >> 7) & 0xFF); -- adr_buf[2] |= flags; -- adr_length = 4; -- if (chunk == state->m_chunk_size) -- chunk -= 2; -+ Flags |= 0xC0; -+ -+ while (BlkSize > 0) { -+ int Chunk = BlkSize > state->m_ChunkSize ? -+ state->m_ChunkSize : BlkSize; -+ u8 *AdrBuf = &state->Chunk[0]; -+ u32 AdrLength = 0; -+ -+ if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) { -+ AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01); -+ AdrBuf[1] = ((Address >> 16) & 0xFF); -+ AdrBuf[2] = ((Address >> 24) & 0xFF); -+ AdrBuf[3] = ((Address >> 7) & 0xFF); -+ AdrBuf[2] |= Flags; -+ AdrLength = 4; -+ if (Chunk == state->m_ChunkSize) -+ Chunk -= 2; - } else { -- adr_buf[0] = ((address << 1) & 0xFF); -- adr_buf[1] = (((address >> 16) & 0x0F) | -- ((address >> 18) & 0xF0)); -- adr_length = 2; -+ AdrBuf[0] = ((Address << 1) & 0xFF); -+ AdrBuf[1] = (((Address >> 16) & 0x0F) | -+ ((Address >> 18) & 0xF0)); -+ AdrLength = 2; - } -- memcpy(&state->chunk[adr_length], p_block, chunk); -- dprintk(2, "(0x%08x, 0x%02x)\n", address, flags); -+ memcpy(&state->Chunk[AdrLength], pBlock, Chunk); -+ dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags); - if (debug > 1) { - int i; -- if (p_block) -- for (i = 0; i < chunk; i++) -- pr_cont(" %02x", p_block[i]); -- pr_cont("\n"); -+ if (pBlock) -+ for (i = 0; i < Chunk; i++) -+ printk(KERN_CONT " %02x", pBlock[i]); -+ printk(KERN_CONT "\n"); - } -- status = i2c_write(state, state->demod_address, -- &state->chunk[0], chunk + adr_length); -+ status = i2c_write(state->i2c, state->demod_address, -+ &state->Chunk[0], Chunk + AdrLength); - if (status < 0) { -- pr_err("%s: i2c write error at addr 0x%02x\n", -- __func__, address); -+ printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", -+ __func__, Address); - break; - } -- p_block += chunk; -- address += (chunk >> 1); -- blk_size -= chunk; -+ pBlock += Chunk; -+ Address += (Chunk >> 1); -+ BlkSize -= Chunk; - } - return status; - } -@@ -493,29 +560,29 @@ static int write_block(struct drxk_state *state, u32 address, - #define DRXK_MAX_RETRIES_POWERUP 20 - #endif - --static int power_up_device(struct drxk_state *state) -+int PowerUpDevice(struct drxk_state *state) - { - int status; - u8 data = 0; -- u16 retry_count = 0; -+ u16 retryCount = 0; - - dprintk(1, "\n"); - -- status = i2c_read1(state, state->demod_address, &data); -+ status = i2c_read1(state->i2c, state->demod_address, &data); - if (status < 0) { - do { - data = 0; -- status = i2c_write(state, state->demod_address, -+ status = i2c_write(state->i2c, state->demod_address, - &data, 1); -- usleep_range(10000, 11000); -- retry_count++; -+ msleep(10); -+ retryCount++; - if (status < 0) - continue; -- status = i2c_read1(state, state->demod_address, -+ status = i2c_read1(state->i2c, state->demod_address, - &data); - } while (status < 0 && -- (retry_count < DRXK_MAX_RETRIES_POWERUP)); -- if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP) -+ (retryCount < DRXK_MAX_RETRIES_POWERUP)); -+ if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP) - goto error; - } - -@@ -531,11 +598,11 @@ static int power_up_device(struct drxk_state *state) - if (status < 0) - goto error; - -- state->m_current_power_mode = DRX_POWER_UP; -+ state->m_currentPowerMode = DRX_POWER_UP; - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } -@@ -547,106 +614,111 @@ static int init_state(struct drxk_state *state) - * FIXME: most (all?) of the values bellow should be moved into - * struct drxk_config, as they are probably board-specific - */ -- u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO; -- u32 ul_vsb_if_agc_output_level = 0; -- u32 ul_vsb_if_agc_min_level = 0; -- u32 ul_vsb_if_agc_max_level = 0x7FFF; -- u32 ul_vsb_if_agc_speed = 3; -- -- u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO; -- u32 ul_vsb_rf_agc_output_level = 0; -- u32 ul_vsb_rf_agc_min_level = 0; -- u32 ul_vsb_rf_agc_max_level = 0x7FFF; -- u32 ul_vsb_rf_agc_speed = 3; -- u32 ul_vsb_rf_agc_top = 9500; -- u32 ul_vsb_rf_agc_cut_off_current = 4000; -- -- u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO; -- u32 ul_atv_if_agc_output_level = 0; -- u32 ul_atv_if_agc_min_level = 0; -- u32 ul_atv_if_agc_max_level = 0; -- u32 ul_atv_if_agc_speed = 3; -- -- u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF; -- u32 ul_atv_rf_agc_output_level = 0; -- u32 ul_atv_rf_agc_min_level = 0; -- u32 ul_atv_rf_agc_max_level = 0; -- u32 ul_atv_rf_agc_top = 9500; -- u32 ul_atv_rf_agc_cut_off_current = 4000; -- u32 ul_atv_rf_agc_speed = 3; -+ u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO; -+ u32 ulVSBIfAgcOutputLevel = 0; -+ u32 ulVSBIfAgcMinLevel = 0; -+ u32 ulVSBIfAgcMaxLevel = 0x7FFF; -+ u32 ulVSBIfAgcSpeed = 3; -+ -+ u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO; -+ u32 ulVSBRfAgcOutputLevel = 0; -+ u32 ulVSBRfAgcMinLevel = 0; -+ u32 ulVSBRfAgcMaxLevel = 0x7FFF; -+ u32 ulVSBRfAgcSpeed = 3; -+ u32 ulVSBRfAgcTop = 9500; -+ u32 ulVSBRfAgcCutOffCurrent = 4000; -+ -+ u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO; -+ u32 ulATVIfAgcOutputLevel = 0; -+ u32 ulATVIfAgcMinLevel = 0; -+ u32 ulATVIfAgcMaxLevel = 0; -+ u32 ulATVIfAgcSpeed = 3; -+ -+ u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF; -+ u32 ulATVRfAgcOutputLevel = 0; -+ u32 ulATVRfAgcMinLevel = 0; -+ u32 ulATVRfAgcMaxLevel = 0; -+ u32 ulATVRfAgcTop = 9500; -+ u32 ulATVRfAgcCutOffCurrent = 4000; -+ u32 ulATVRfAgcSpeed = 3; - - u32 ulQual83 = DEFAULT_MER_83; - u32 ulQual93 = DEFAULT_MER_93; - -- u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; -- u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; -+ u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; -+ u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; - - /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ - /* io_pad_cfg_mode output mode is drive always */ - /* io_pad_cfg_drive is set to power 2 (23 mA) */ -- u32 ul_gpio_cfg = 0x0113; -- u32 ul_invert_ts_clock = 0; -- u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; -- u32 ul_dvbt_bitrate = 50000000; -- u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; -+ u32 ulGPIOCfg = 0x0113; -+ u32 ulInvertTSClock = 0; -+ u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; -+ u32 ulDVBTBitrate = 50000000; -+ u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; - -- u32 ul_insert_rs_byte = 0; -+ u32 ulInsertRSByte = 0; - -- u32 ul_rf_mirror = 1; -- u32 ul_power_down = 0; -+ u32 ulRfMirror = 1; -+ u32 ulPowerDown = 0; - - dprintk(1, "\n"); - -- state->m_has_lna = false; -- state->m_has_dvbt = false; -- state->m_has_dvbc = false; -- state->m_has_atv = false; -- state->m_has_oob = false; -- state->m_has_audio = false; -+ state->m_hasLNA = false; -+ state->m_hasDVBT = false; -+ state->m_hasDVBC = false; -+ state->m_hasATV = false; -+ state->m_hasOOB = false; -+ state->m_hasAudio = false; - -- if (!state->m_chunk_size) -- state->m_chunk_size = 124; -+ if (!state->m_ChunkSize) -+ state->m_ChunkSize = 124; - -- state->m_osc_clock_freq = 0; -- state->m_smart_ant_inverted = false; -- state->m_b_p_down_open_bridge = false; -+ state->m_oscClockFreq = 0; -+ state->m_smartAntInverted = false; -+ state->m_bPDownOpenBridge = false; - - /* real system clock frequency in kHz */ -- state->m_sys_clock_freq = 151875; -+ state->m_sysClockFreq = 151875; - /* Timing div, 250ns/Psys */ - /* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */ -- state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) * -+ state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) * - HI_I2C_DELAY) / 1000; - /* Clipping */ -- if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) -- state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; -- state->m_hi_cfg_wake_up_key = (state->demod_address << 1); -+ if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) -+ state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; -+ state->m_HICfgWakeUpKey = (state->demod_address << 1); - /* port/bridge/power down ctrl */ -- state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; -+ state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - -- state->m_b_power_down = (ul_power_down != 0); -+ state->m_bPowerDown = (ulPowerDown != 0); - -- state->m_drxk_a3_patch_code = false; -+ state->m_DRXK_A1_PATCH_CODE = false; -+ state->m_DRXK_A1_ROM_CODE = false; -+ state->m_DRXK_A2_ROM_CODE = false; -+ state->m_DRXK_A3_ROM_CODE = false; -+ state->m_DRXK_A2_PATCH_CODE = false; -+ state->m_DRXK_A3_PATCH_CODE = false; - - /* Init AGC and PGA parameters */ - /* VSB IF */ -- state->m_vsb_if_agc_cfg.ctrl_mode = ul_vsb_if_agc_mode; -- state->m_vsb_if_agc_cfg.output_level = ul_vsb_if_agc_output_level; -- state->m_vsb_if_agc_cfg.min_output_level = ul_vsb_if_agc_min_level; -- state->m_vsb_if_agc_cfg.max_output_level = ul_vsb_if_agc_max_level; -- state->m_vsb_if_agc_cfg.speed = ul_vsb_if_agc_speed; -- state->m_vsb_pga_cfg = 140; -+ state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode); -+ state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel); -+ state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel); -+ state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel); -+ state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed); -+ state->m_vsbPgaCfg = 140; - - /* VSB RF */ -- state->m_vsb_rf_agc_cfg.ctrl_mode = ul_vsb_rf_agc_mode; -- state->m_vsb_rf_agc_cfg.output_level = ul_vsb_rf_agc_output_level; -- state->m_vsb_rf_agc_cfg.min_output_level = ul_vsb_rf_agc_min_level; -- state->m_vsb_rf_agc_cfg.max_output_level = ul_vsb_rf_agc_max_level; -- state->m_vsb_rf_agc_cfg.speed = ul_vsb_rf_agc_speed; -- state->m_vsb_rf_agc_cfg.top = ul_vsb_rf_agc_top; -- state->m_vsb_rf_agc_cfg.cut_off_current = ul_vsb_rf_agc_cut_off_current; -- state->m_vsb_pre_saw_cfg.reference = 0x07; -- state->m_vsb_pre_saw_cfg.use_pre_saw = true; -+ state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode); -+ state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel); -+ state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel); -+ state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel); -+ state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed); -+ state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop); -+ state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent); -+ state->m_vsbPreSawCfg.reference = 0x07; -+ state->m_vsbPreSawCfg.usePreSaw = true; - - state->m_Quality83percent = DEFAULT_MER_83; - state->m_Quality93percent = DEFAULT_MER_93; -@@ -656,127 +728,127 @@ static int init_state(struct drxk_state *state) - } - - /* ATV IF */ -- state->m_atv_if_agc_cfg.ctrl_mode = ul_atv_if_agc_mode; -- state->m_atv_if_agc_cfg.output_level = ul_atv_if_agc_output_level; -- state->m_atv_if_agc_cfg.min_output_level = ul_atv_if_agc_min_level; -- state->m_atv_if_agc_cfg.max_output_level = ul_atv_if_agc_max_level; -- state->m_atv_if_agc_cfg.speed = ul_atv_if_agc_speed; -+ state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode); -+ state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel); -+ state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel); -+ state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel); -+ state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed); - - /* ATV RF */ -- state->m_atv_rf_agc_cfg.ctrl_mode = ul_atv_rf_agc_mode; -- state->m_atv_rf_agc_cfg.output_level = ul_atv_rf_agc_output_level; -- state->m_atv_rf_agc_cfg.min_output_level = ul_atv_rf_agc_min_level; -- state->m_atv_rf_agc_cfg.max_output_level = ul_atv_rf_agc_max_level; -- state->m_atv_rf_agc_cfg.speed = ul_atv_rf_agc_speed; -- state->m_atv_rf_agc_cfg.top = ul_atv_rf_agc_top; -- state->m_atv_rf_agc_cfg.cut_off_current = ul_atv_rf_agc_cut_off_current; -- state->m_atv_pre_saw_cfg.reference = 0x04; -- state->m_atv_pre_saw_cfg.use_pre_saw = true; -+ state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode); -+ state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel); -+ state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel); -+ state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel); -+ state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed); -+ state->m_atvRfAgcCfg.top = (ulATVRfAgcTop); -+ state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent); -+ state->m_atvPreSawCfg.reference = 0x04; -+ state->m_atvPreSawCfg.usePreSaw = true; - - - /* DVBT RF */ -- state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; -- state->m_dvbt_rf_agc_cfg.output_level = 0; -- state->m_dvbt_rf_agc_cfg.min_output_level = 0; -- state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF; -- state->m_dvbt_rf_agc_cfg.top = 0x2100; -- state->m_dvbt_rf_agc_cfg.cut_off_current = 4000; -- state->m_dvbt_rf_agc_cfg.speed = 1; -+ state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; -+ state->m_dvbtRfAgcCfg.outputLevel = 0; -+ state->m_dvbtRfAgcCfg.minOutputLevel = 0; -+ state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF; -+ state->m_dvbtRfAgcCfg.top = 0x2100; -+ state->m_dvbtRfAgcCfg.cutOffCurrent = 4000; -+ state->m_dvbtRfAgcCfg.speed = 1; - - - /* DVBT IF */ -- state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; -- state->m_dvbt_if_agc_cfg.output_level = 0; -- state->m_dvbt_if_agc_cfg.min_output_level = 0; -- state->m_dvbt_if_agc_cfg.max_output_level = 9000; -- state->m_dvbt_if_agc_cfg.top = 13424; -- state->m_dvbt_if_agc_cfg.cut_off_current = 0; -- state->m_dvbt_if_agc_cfg.speed = 3; -- state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30; -- state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000; -+ state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; -+ state->m_dvbtIfAgcCfg.outputLevel = 0; -+ state->m_dvbtIfAgcCfg.minOutputLevel = 0; -+ state->m_dvbtIfAgcCfg.maxOutputLevel = 9000; -+ state->m_dvbtIfAgcCfg.top = 13424; -+ state->m_dvbtIfAgcCfg.cutOffCurrent = 0; -+ state->m_dvbtIfAgcCfg.speed = 3; -+ state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30; -+ state->m_dvbtIfAgcCfg.IngainTgtMax = 30000; - /* state->m_dvbtPgaCfg = 140; */ - -- state->m_dvbt_pre_saw_cfg.reference = 4; -- state->m_dvbt_pre_saw_cfg.use_pre_saw = false; -+ state->m_dvbtPreSawCfg.reference = 4; -+ state->m_dvbtPreSawCfg.usePreSaw = false; - - /* QAM RF */ -- state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; -- state->m_qam_rf_agc_cfg.output_level = 0; -- state->m_qam_rf_agc_cfg.min_output_level = 6023; -- state->m_qam_rf_agc_cfg.max_output_level = 27000; -- state->m_qam_rf_agc_cfg.top = 0x2380; -- state->m_qam_rf_agc_cfg.cut_off_current = 4000; -- state->m_qam_rf_agc_cfg.speed = 3; -+ state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; -+ state->m_qamRfAgcCfg.outputLevel = 0; -+ state->m_qamRfAgcCfg.minOutputLevel = 6023; -+ state->m_qamRfAgcCfg.maxOutputLevel = 27000; -+ state->m_qamRfAgcCfg.top = 0x2380; -+ state->m_qamRfAgcCfg.cutOffCurrent = 4000; -+ state->m_qamRfAgcCfg.speed = 3; - - /* QAM IF */ -- state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; -- state->m_qam_if_agc_cfg.output_level = 0; -- state->m_qam_if_agc_cfg.min_output_level = 0; -- state->m_qam_if_agc_cfg.max_output_level = 9000; -- state->m_qam_if_agc_cfg.top = 0x0511; -- state->m_qam_if_agc_cfg.cut_off_current = 0; -- state->m_qam_if_agc_cfg.speed = 3; -- state->m_qam_if_agc_cfg.ingain_tgt_max = 5119; -- state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50; -- -- state->m_qam_pga_cfg = 140; -- state->m_qam_pre_saw_cfg.reference = 4; -- state->m_qam_pre_saw_cfg.use_pre_saw = false; -- -- state->m_operation_mode = OM_NONE; -- state->m_drxk_state = DRXK_UNINITIALIZED; -+ state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; -+ state->m_qamIfAgcCfg.outputLevel = 0; -+ state->m_qamIfAgcCfg.minOutputLevel = 0; -+ state->m_qamIfAgcCfg.maxOutputLevel = 9000; -+ state->m_qamIfAgcCfg.top = 0x0511; -+ state->m_qamIfAgcCfg.cutOffCurrent = 0; -+ state->m_qamIfAgcCfg.speed = 3; -+ state->m_qamIfAgcCfg.IngainTgtMax = 5119; -+ state->m_qamIfAgcCfg.FastClipCtrlDelay = 50; -+ -+ state->m_qamPgaCfg = 140; -+ state->m_qamPreSawCfg.reference = 4; -+ state->m_qamPreSawCfg.usePreSaw = false; -+ -+ state->m_OperationMode = OM_NONE; -+ state->m_DrxkState = DRXK_UNINITIALIZED; - - /* MPEG output configuration */ -- state->m_enable_mpeg_output = true; /* If TRUE; enable MPEG ouput */ -- state->m_insert_rs_byte = false; /* If TRUE; insert RS byte */ -- state->m_invert_data = false; /* If TRUE; invert DATA signals */ -- state->m_invert_err = false; /* If TRUE; invert ERR signal */ -- state->m_invert_str = false; /* If TRUE; invert STR signals */ -- state->m_invert_val = false; /* If TRUE; invert VAL signals */ -- state->m_invert_clk = (ul_invert_ts_clock != 0); /* If TRUE; invert CLK signals */ -+ state->m_enableMPEGOutput = true; /* If TRUE; enable MPEG ouput */ -+ state->m_insertRSByte = false; /* If TRUE; insert RS byte */ -+ state->m_invertDATA = false; /* If TRUE; invert DATA signals */ -+ state->m_invertERR = false; /* If TRUE; invert ERR signal */ -+ state->m_invertSTR = false; /* If TRUE; invert STR signals */ -+ state->m_invertVAL = false; /* If TRUE; invert VAL signals */ -+ state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ - - /* If TRUE; static MPEG clockrate will be used; - otherwise clockrate will adapt to the bitrate of the TS */ - -- state->m_dvbt_bitrate = ul_dvbt_bitrate; -- state->m_dvbc_bitrate = ul_dvbc_bitrate; -+ state->m_DVBTBitrate = ulDVBTBitrate; -+ state->m_DVBCBitrate = ulDVBCBitrate; - -- state->m_ts_data_strength = (ul_ts_data_strength & 0x07); -+ state->m_TSDataStrength = (ulTSDataStrength & 0x07); - - /* Maximum bitrate in b/s in case static clockrate is selected */ -- state->m_mpeg_ts_static_bitrate = 19392658; -- state->m_disable_te_ihandling = false; -+ state->m_mpegTsStaticBitrate = 19392658; -+ state->m_disableTEIhandling = false; - -- if (ul_insert_rs_byte) -- state->m_insert_rs_byte = true; -+ if (ulInsertRSByte) -+ state->m_insertRSByte = true; - -- state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; -- if (ul_mpeg_lock_time_out < 10000) -- state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out; -- state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; -- if (ul_demod_lock_time_out < 10000) -- state->m_demod_lock_time_out = ul_demod_lock_time_out; -+ state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; -+ if (ulMpegLockTimeOut < 10000) -+ state->m_MpegLockTimeOut = ulMpegLockTimeOut; -+ state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; -+ if (ulDemodLockTimeOut < 10000) -+ state->m_DemodLockTimeOut = ulDemodLockTimeOut; - - /* QAM defaults */ -- state->m_constellation = DRX_CONSTELLATION_AUTO; -- state->m_qam_interleave_mode = DRXK_QAM_I12_J17; -- state->m_fec_rs_plen = 204 * 8; /* fecRsPlen annex A */ -- state->m_fec_rs_prescale = 1; -+ state->m_Constellation = DRX_CONSTELLATION_AUTO; -+ state->m_qamInterleaveMode = DRXK_QAM_I12_J17; -+ state->m_fecRsPlen = 204 * 8; /* fecRsPlen annex A */ -+ state->m_fecRsPrescale = 1; - -- state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM; -- state->m_agcfast_clip_ctrl_delay = 0; -+ state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM; -+ state->m_agcFastClipCtrlDelay = 0; - -- state->m_gpio_cfg = ul_gpio_cfg; -+ state->m_GPIOCfg = (ulGPIOCfg); - -- state->m_b_power_down = false; -- state->m_current_power_mode = DRX_POWER_DOWN; -+ state->m_bPowerDown = false; -+ state->m_currentPowerMode = DRX_POWER_DOWN; - -- state->m_rfmirror = (ul_rf_mirror == 0); -- state->m_if_agc_pol = false; -+ state->m_rfmirror = (ulRfMirror == 0); -+ state->m_IfAgcPol = false; - return 0; - } - --static int drxx_open(struct drxk_state *state) -+static int DRXX_Open(struct drxk_state *state) - { - int status = 0; - u32 jtag = 0; -@@ -785,8 +857,7 @@ static int drxx_open(struct drxk_state *state) - - dprintk(1, "\n"); - /* stop lock indicator process */ -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; - /* Check device id */ -@@ -805,14 +876,14 @@ static int drxx_open(struct drxk_state *state) - status = write16(state, SIO_TOP_COMM_KEY__A, key); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int get_device_capabilities(struct drxk_state *state) -+static int GetDeviceCapabilities(struct drxk_state *state) - { -- u16 sio_pdr_ohw_cfg = 0; -- u32 sio_top_jtagid_lo = 0; -+ u16 sioPdrOhwCfg = 0; -+ u32 sioTopJtagidLo = 0; - int status; - const char *spin = ""; - -@@ -820,196 +891,197 @@ static int get_device_capabilities(struct drxk_state *state) - - /* driver 0.9.0 */ - /* stop lock indicator process */ -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; -- status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); -+ status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA); - if (status < 0) - goto error; -- status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg); -+ status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg); - if (status < 0) - goto error; - status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); - if (status < 0) - goto error; - -- switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { -+ switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { - case 0: - /* ignore (bypass ?) */ - break; - case 1: - /* 27 MHz */ -- state->m_osc_clock_freq = 27000; -+ state->m_oscClockFreq = 27000; - break; - case 2: - /* 20.25 MHz */ -- state->m_osc_clock_freq = 20250; -+ state->m_oscClockFreq = 20250; - break; - case 3: - /* 4 MHz */ -- state->m_osc_clock_freq = 20250; -+ state->m_oscClockFreq = 20250; - break; - default: -- pr_err("Clock Frequency is unknown\n"); -+ printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n"); - return -EINVAL; - } - /* - Determine device capabilities - Based on pinning v14 - */ -- status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo); -+ status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo); - if (status < 0) - goto error; - -- pr_info("status = 0x%08x\n", sio_top_jtagid_lo); -+printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo); - - /* driver 0.9.0 */ -- switch ((sio_top_jtagid_lo >> 29) & 0xF) { -+ switch ((sioTopJtagidLo >> 29) & 0xF) { - case 0: -- state->m_device_spin = DRXK_SPIN_A1; -+ state->m_deviceSpin = DRXK_SPIN_A1; - spin = "A1"; - break; - case 2: -- state->m_device_spin = DRXK_SPIN_A2; -+ state->m_deviceSpin = DRXK_SPIN_A2; - spin = "A2"; - break; - case 3: -- state->m_device_spin = DRXK_SPIN_A3; -+ state->m_deviceSpin = DRXK_SPIN_A3; - spin = "A3"; - break; - default: -- state->m_device_spin = DRXK_SPIN_UNKNOWN; -+ state->m_deviceSpin = DRXK_SPIN_UNKNOWN; - status = -EINVAL; -- pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF); -+ printk(KERN_ERR "drxk: Spin %d unknown\n", -+ (sioTopJtagidLo >> 29) & 0xF); - goto error2; - } -- switch ((sio_top_jtagid_lo >> 12) & 0xFF) { -+ switch ((sioTopJtagidLo >> 12) & 0xFF) { - case 0x13: - /* typeId = DRX3913K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = false; -- state->m_has_audio = false; -- state->m_has_dvbt = true; -- state->m_has_dvbc = true; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = false; -- state->m_has_gpio1 = false; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = false; -+ state->m_hasAudio = false; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = true; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = false; -+ state->m_hasGPIO1 = false; -+ state->m_hasIRQN = false; - break; - case 0x15: - /* typeId = DRX3915K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = false; -- state->m_has_dvbt = true; -- state->m_has_dvbc = false; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = false; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = false; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x16: - /* typeId = DRX3916K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = false; -- state->m_has_dvbt = true; -- state->m_has_dvbc = false; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = false; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = false; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x18: - /* typeId = DRX3918K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = true; -- state->m_has_dvbt = true; -- state->m_has_dvbc = false; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = true; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = false; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x21: - /* typeId = DRX3921K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = true; -- state->m_has_dvbt = true; -- state->m_has_dvbc = true; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = true; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = true; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x23: - /* typeId = DRX3923K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = true; -- state->m_has_dvbt = true; -- state->m_has_dvbc = true; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = true; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = true; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x25: - /* typeId = DRX3925K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = true; -- state->m_has_dvbt = true; -- state->m_has_dvbc = true; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = true; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = true; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - case 0x26: - /* typeId = DRX3926K_TYPE_ID */ -- state->m_has_lna = false; -- state->m_has_oob = false; -- state->m_has_atv = true; -- state->m_has_audio = false; -- state->m_has_dvbt = true; -- state->m_has_dvbc = true; -- state->m_has_sawsw = true; -- state->m_has_gpio2 = true; -- state->m_has_gpio1 = true; -- state->m_has_irqn = false; -+ state->m_hasLNA = false; -+ state->m_hasOOB = false; -+ state->m_hasATV = true; -+ state->m_hasAudio = false; -+ state->m_hasDVBT = true; -+ state->m_hasDVBC = true; -+ state->m_hasSAWSW = true; -+ state->m_hasGPIO2 = true; -+ state->m_hasGPIO1 = true; -+ state->m_hasIRQN = false; - break; - default: -- pr_err("DeviceID 0x%02x not supported\n", -- ((sio_top_jtagid_lo >> 12) & 0xFF)); -+ printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n", -+ ((sioTopJtagidLo >> 12) & 0xFF)); - status = -EINVAL; - goto error2; - } - -- pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", -- ((sio_top_jtagid_lo >> 12) & 0xFF), spin, -- state->m_osc_clock_freq / 1000, -- state->m_osc_clock_freq % 1000); -+ printk(KERN_INFO -+ "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", -+ ((sioTopJtagidLo >> 12) & 0xFF), spin, -+ state->m_oscClockFreq / 1000, -+ state->m_oscClockFreq % 1000); - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - error2: - return status; - } - --static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) -+static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) - { - int status; - bool powerdown_cmd; -@@ -1021,37 +1093,37 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) - if (status < 0) - goto error; - if (cmd == SIO_HI_RA_RAM_CMD_RESET) -- usleep_range(1000, 2000); -+ msleep(1); - - powerdown_cmd = - (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) && -- ((state->m_hi_cfg_ctrl) & -+ ((state->m_HICfgCtrl) & - SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == - SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); -- if (!powerdown_cmd) { -+ if (powerdown_cmd == false) { - /* Wait until command rdy */ -- u32 retry_count = 0; -- u16 wait_cmd; -+ u32 retryCount = 0; -+ u16 waitCmd; - - do { -- usleep_range(1000, 2000); -- retry_count += 1; -+ msleep(1); -+ retryCount += 1; - status = read16(state, SIO_HI_RA_RAM_CMD__A, -- &wait_cmd); -- } while ((status < 0) && (retry_count < DRXK_MAX_RETRIES) -- && (wait_cmd != 0)); -+ &waitCmd); -+ } while ((status < 0) && (retryCount < DRXK_MAX_RETRIES) -+ && (waitCmd != 0)); - if (status < 0) - goto error; -- status = read16(state, SIO_HI_RA_RAM_RES__A, p_result); -+ status = read16(state, SIO_HI_RA_RAM_RES__A, pResult); - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static int hi_cfg_command(struct drxk_state *state) -+static int HI_CfgCommand(struct drxk_state *state) - { - int status; - -@@ -1059,77 +1131,70 @@ static int hi_cfg_command(struct drxk_state *state) - - mutex_lock(&state->mutex); - -- status = write16(state, SIO_HI_RA_RAM_PAR_6__A, -- state->m_hi_cfg_timeout); -+ status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout); - if (status < 0) - goto error; -- status = write16(state, SIO_HI_RA_RAM_PAR_5__A, -- state->m_hi_cfg_ctrl); -+ status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl); - if (status < 0) - goto error; -- status = write16(state, SIO_HI_RA_RAM_PAR_4__A, -- state->m_hi_cfg_wake_up_key); -+ status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey); - if (status < 0) - goto error; -- status = write16(state, SIO_HI_RA_RAM_PAR_3__A, -- state->m_hi_cfg_bridge_delay); -+ status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay); - if (status < 0) - goto error; -- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, -- state->m_hi_cfg_timing_div); -+ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv); - if (status < 0) - goto error; -- status = write16(state, SIO_HI_RA_RAM_PAR_1__A, -- SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); -+ status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); - if (status < 0) - goto error; -- status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, NULL); -+ status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); - if (status < 0) - goto error; - -- state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; -+ state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; - error: - mutex_unlock(&state->mutex); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int init_hi(struct drxk_state *state) -+static int InitHI(struct drxk_state *state) - { - dprintk(1, "\n"); - -- state->m_hi_cfg_wake_up_key = (state->demod_address << 1); -- state->m_hi_cfg_timeout = 0x96FF; -+ state->m_HICfgWakeUpKey = (state->demod_address << 1); -+ state->m_HICfgTimeout = 0x96FF; - /* port/bridge/power down ctrl */ -- state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; -+ state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - -- return hi_cfg_command(state); -+ return HI_CfgCommand(state); - } - --static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) -+static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) - { - int status = -1; -- u16 sio_pdr_mclk_cfg = 0; -- u16 sio_pdr_mdx_cfg = 0; -+ u16 sioPdrMclkCfg = 0; -+ u16 sioPdrMdxCfg = 0; - u16 err_cfg = 0; - - dprintk(1, ": mpeg %s, %s mode\n", -- mpeg_enable ? "enable" : "disable", -- state->m_enable_parallel ? "parallel" : "serial"); -+ mpegEnable ? "enable" : "disable", -+ state->m_enableParallel ? "parallel" : "serial"); - - /* stop lock indicator process */ -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; - - /* MPEG TS pad configuration */ -- status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); -+ status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA); - if (status < 0) - goto error; - -- if (!mpeg_enable) { -+ if (mpegEnable == false) { - /* Set MPEG TS pads to inputmode */ - status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); - if (status < 0) -@@ -1169,19 +1234,19 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) - goto error; - } else { - /* Enable MPEG output */ -- sio_pdr_mdx_cfg = -- ((state->m_ts_data_strength << -+ sioPdrMdxCfg = -+ ((state->m_TSDataStrength << - SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); -- sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength << -+ sioPdrMclkCfg = ((state->m_TSClockkStrength << - SIO_PDR_MCLK_CFG_DRIVE__B) | - 0x0003); - -- status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; - - if (state->enable_merr_cfg) -- err_cfg = sio_pdr_mdx_cfg; -+ err_cfg = sioPdrMdxCfg; - - status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); - if (status < 0) -@@ -1190,38 +1255,31 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) - if (status < 0) - goto error; - -- if (state->m_enable_parallel) { -- /* parallel -> enable MD1 to MD7 */ -- status = write16(state, SIO_PDR_MD1_CFG__A, -- sio_pdr_mdx_cfg); -+ if (state->m_enableParallel == true) { -+ /* paralel -> enable MD1 to MD7 */ -+ status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD2_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD3_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD4_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD5_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD6_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD7_CFG__A, -- sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; - } else { -- sio_pdr_mdx_cfg = ((state->m_ts_data_strength << -+ sioPdrMdxCfg = ((state->m_TSDataStrength << - SIO_PDR_MD0_CFG_DRIVE__B) - | 0x0003); - /* serial -> disable MD1 to MD7 */ -@@ -1247,10 +1305,10 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) - if (status < 0) - goto error; - } -- status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg); -+ status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg); -+ status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; - } -@@ -1262,21 +1320,21 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) - status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int mpegts_disable(struct drxk_state *state) -+static int MPEGTSDisable(struct drxk_state *state) - { - dprintk(1, "\n"); - -- return mpegts_configure_pins(state, false); -+ return MPEGTSConfigurePins(state, false); - } - --static int bl_chain_cmd(struct drxk_state *state, -- u16 rom_offset, u16 nr_of_elements, u32 time_out) -+static int BLChainCmd(struct drxk_state *state, -+ u16 romOffset, u16 nrOfElements, u32 timeOut) - { -- u16 bl_status = 0; -+ u16 blStatus = 0; - int status; - unsigned long end; - -@@ -1285,46 +1343,46 @@ static int bl_chain_cmd(struct drxk_state *state, - status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN); - if (status < 0) - goto error; -- status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset); -+ status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset); - if (status < 0) - goto error; -- status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements); -+ status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements); - if (status < 0) - goto error; - status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); - if (status < 0) - goto error; - -- end = jiffies + msecs_to_jiffies(time_out); -+ end = jiffies + msecs_to_jiffies(timeOut); - do { -- usleep_range(1000, 2000); -- status = read16(state, SIO_BL_STATUS__A, &bl_status); -+ msleep(1); -+ status = read16(state, SIO_BL_STATUS__A, &blStatus); - if (status < 0) - goto error; -- } while ((bl_status == 0x1) && -+ } while ((blStatus == 0x1) && - ((time_is_after_jiffies(end)))); - -- if (bl_status == 0x1) { -- pr_err("SIO not ready\n"); -+ if (blStatus == 0x1) { -+ printk(KERN_ERR "drxk: SIO not ready\n"); - status = -EINVAL; - goto error2; - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - error2: - mutex_unlock(&state->mutex); - return status; - } - - --static int download_microcode(struct drxk_state *state, -- const u8 p_mc_image[], u32 length) -+static int DownloadMicrocode(struct drxk_state *state, -+ const u8 pMCImage[], u32 Length) - { -- const u8 *p_src = p_mc_image; -- u32 address; -- u16 n_blocks; -- u16 block_size; -+ const u8 *pSrc = pMCImage; -+ u32 Address; -+ u16 nBlocks; -+ u16 BlockSize; - u32 offset = 0; - u32 i; - int status = 0; -@@ -1334,131 +1392,130 @@ static int download_microcode(struct drxk_state *state, - /* down the drain (we don't care about MAGIC_WORD) */ - #if 0 - /* For future reference */ -- drain = (p_src[0] << 8) | p_src[1]; -+ Drain = (pSrc[0] << 8) | pSrc[1]; - #endif -- p_src += sizeof(u16); -+ pSrc += sizeof(u16); - offset += sizeof(u16); -- n_blocks = (p_src[0] << 8) | p_src[1]; -- p_src += sizeof(u16); -+ nBlocks = (pSrc[0] << 8) | pSrc[1]; -+ pSrc += sizeof(u16); - offset += sizeof(u16); - -- for (i = 0; i < n_blocks; i += 1) { -- address = (p_src[0] << 24) | (p_src[1] << 16) | -- (p_src[2] << 8) | p_src[3]; -- p_src += sizeof(u32); -+ for (i = 0; i < nBlocks; i += 1) { -+ Address = (pSrc[0] << 24) | (pSrc[1] << 16) | -+ (pSrc[2] << 8) | pSrc[3]; -+ pSrc += sizeof(u32); - offset += sizeof(u32); - -- block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16); -- p_src += sizeof(u16); -+ BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); -+ pSrc += sizeof(u16); - offset += sizeof(u16); - - #if 0 - /* For future reference */ -- flags = (p_src[0] << 8) | p_src[1]; -+ Flags = (pSrc[0] << 8) | pSrc[1]; - #endif -- p_src += sizeof(u16); -+ pSrc += sizeof(u16); - offset += sizeof(u16); - - #if 0 - /* For future reference */ -- block_crc = (p_src[0] << 8) | p_src[1]; -+ BlockCRC = (pSrc[0] << 8) | pSrc[1]; - #endif -- p_src += sizeof(u16); -+ pSrc += sizeof(u16); - offset += sizeof(u16); - -- if (offset + block_size > length) { -- pr_err("Firmware is corrupted.\n"); -+ if (offset + BlockSize > Length) { -+ printk(KERN_ERR "drxk: Firmware is corrupted.\n"); - return -EINVAL; - } - -- status = write_block(state, address, block_size, p_src); -+ status = write_block(state, Address, BlockSize, pSrc); - if (status < 0) { -- pr_err("Error %d while loading firmware\n", status); -+ printk(KERN_ERR "drxk: Error %d while loading firmware\n", status); - break; - } -- p_src += block_size; -- offset += block_size; -+ pSrc += BlockSize; -+ offset += BlockSize; - } - return status; - } - --static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) -+static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable) - { - int status; - u16 data = 0; -- u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; -- u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; -+ u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; -+ u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; - unsigned long end; - - dprintk(1, "\n"); - -- if (!enable) { -- desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; -- desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; -+ if (enable == false) { -+ desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; -+ desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; - } - - status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); -- if (status >= 0 && data == desired_status) { -+ if (status >= 0 && data == desiredStatus) { - /* tokenring already has correct status */ - return status; - } - /* Disable/enable dvbt tokenring bridge */ -- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl); -+ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl); - - end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); - do { - status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); -- if ((status >= 0 && data == desired_status) -- || time_is_after_jiffies(end)) -+ if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end)) - break; -- usleep_range(1000, 2000); -+ msleep(1); - } while (1); -- if (data != desired_status) { -- pr_err("SIO not ready\n"); -+ if (data != desiredStatus) { -+ printk(KERN_ERR "drxk: SIO not ready\n"); - return -EINVAL; - } - return status; - } - --static int mpegts_stop(struct drxk_state *state) -+static int MPEGTSStop(struct drxk_state *state) - { - int status = 0; -- u16 fec_oc_snc_mode = 0; -- u16 fec_oc_ipr_mode = 0; -+ u16 fecOcSncMode = 0; -+ u16 fecOcIprMode = 0; - - dprintk(1, "\n"); - -- /* Graceful shutdown (byte boundaries) */ -- status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); -+ /* Gracefull shutdown (byte boundaries) */ -+ status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); - if (status < 0) - goto error; -- fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M; -- status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); -+ fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M; -+ status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); - if (status < 0) - goto error; - - /* Suppress MCLK during absence of data */ -- status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode); -+ status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode); - if (status < 0) - goto error; -- fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; -- status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode); -+ fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; -+ status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode); - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - - static int scu_command(struct drxk_state *state, -- u16 cmd, u8 parameter_len, -- u16 *parameter, u8 result_len, u16 *result) -+ u16 cmd, u8 parameterLen, -+ u16 *parameter, u8 resultLen, u16 *result) - { - #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15 - #error DRXK register mapping no longer compatible with this routine! - #endif -- u16 cur_cmd = 0; -+ u16 curCmd = 0; - int status = -EINVAL; - unsigned long end; - u8 buffer[34]; -@@ -1468,9 +1525,9 @@ static int scu_command(struct drxk_state *state, - - dprintk(1, "\n"); - -- if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) || -- ((result_len > 0) && (result == NULL))) { -- pr_err("Error %d on %s\n", status, __func__); -+ if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) || -+ ((resultLen > 0) && (result == NULL))) { -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -1478,7 +1535,7 @@ static int scu_command(struct drxk_state *state, - - /* assume that the command register is ready - since it is checked afterwards */ -- for (ii = parameter_len - 1; ii >= 0; ii -= 1) { -+ for (ii = parameterLen - 1; ii >= 0; ii -= 1) { - buffer[cnt++] = (parameter[ii] & 0xFF); - buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF); - } -@@ -1486,28 +1543,27 @@ static int scu_command(struct drxk_state *state, - buffer[cnt++] = ((cmd >> 8) & 0xFF); - - write_block(state, SCU_RAM_PARAM_0__A - -- (parameter_len - 1), cnt, buffer); -+ (parameterLen - 1), cnt, buffer); - /* Wait until SCU has processed command */ - end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); - do { -- usleep_range(1000, 2000); -- status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); -+ msleep(1); -+ status = read16(state, SCU_RAM_COMMAND__A, &curCmd); - if (status < 0) - goto error; -- } while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); -- if (cur_cmd != DRX_SCU_READY) { -- pr_err("SCU not ready\n"); -+ } while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); -+ if (curCmd != DRX_SCU_READY) { -+ printk(KERN_ERR "drxk: SCU not ready\n"); - status = -EIO; - goto error2; - } - /* read results */ -- if ((result_len > 0) && (result != NULL)) { -+ if ((resultLen > 0) && (result != NULL)) { - s16 err; - int ii; - -- for (ii = result_len - 1; ii >= 0; ii -= 1) { -- status = read16(state, SCU_RAM_PARAM_0__A - ii, -- &result[ii]); -+ for (ii = resultLen - 1; ii >= 0; ii -= 1) { -+ status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]); - if (status < 0) - goto error; - } -@@ -1535,7 +1591,7 @@ static int scu_command(struct drxk_state *state, - sprintf(errname, "ERROR: %d\n", err); - p = errname; - } -- pr_err("%s while sending cmd 0x%04x with params:", p, cmd); -+ printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd); - print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt); - status = -EINVAL; - goto error2; -@@ -1543,13 +1599,13 @@ static int scu_command(struct drxk_state *state, - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - error2: - mutex_unlock(&state->mutex); - return status; - } - --static int set_iqm_af(struct drxk_state *state, bool active) -+static int SetIqmAf(struct drxk_state *state, bool active) - { - u16 data = 0; - int status; -@@ -1579,14 +1635,14 @@ static int set_iqm_af(struct drxk_state *state, bool active) - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) -+static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) - { - int status = 0; -- u16 sio_cc_pwd_mode = 0; -+ u16 sioCcPwdMode = 0; - - dprintk(1, "\n"); - -@@ -1596,19 +1652,19 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) - - switch (*mode) { - case DRX_POWER_UP: -- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; -+ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE; - break; - case DRXK_POWER_DOWN_OFDM: -- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM; -+ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM; - break; - case DRXK_POWER_DOWN_CORE: -- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; -+ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK; - break; - case DRXK_POWER_DOWN_PLL: -- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; -+ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL; - break; - case DRX_POWER_DOWN: -- sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; -+ sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC; - break; - default: - /* Unknow sleep mode */ -@@ -1616,15 +1672,15 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) - } - - /* If already in requested power mode, do nothing */ -- if (state->m_current_power_mode == *mode) -+ if (state->m_currentPowerMode == *mode) - return 0; - - /* For next steps make sure to start from DRX_POWER_UP mode */ -- if (state->m_current_power_mode != DRX_POWER_UP) { -- status = power_up_device(state); -+ if (state->m_currentPowerMode != DRX_POWER_UP) { -+ status = PowerUpDevice(state); - if (status < 0) - goto error; -- status = dvbt_enable_ofdm_token_ring(state, true); -+ status = DVBTEnableOFDMTokenRing(state, true); - if (status < 0) - goto error; - } -@@ -1641,31 +1697,31 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) - /* Power down device */ - /* stop all comm_exec */ - /* Stop and power down previous standard */ -- switch (state->m_operation_mode) { -+ switch (state->m_OperationMode) { - case OM_DVBT: -- status = mpegts_stop(state); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = power_down_dvbt(state, false); -+ status = PowerDownDVBT(state, false); - if (status < 0) - goto error; - break; - case OM_QAM_ITU_A: - case OM_QAM_ITU_C: -- status = mpegts_stop(state); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = power_down_qam(state); -+ status = PowerDownQAM(state); - if (status < 0) - goto error; - break; - default: - break; - } -- status = dvbt_enable_ofdm_token_ring(state, false); -+ status = DVBTEnableOFDMTokenRing(state, false); - if (status < 0) - goto error; -- status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode); -+ status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode); - if (status < 0) - goto error; - status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); -@@ -1673,26 +1729,26 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) - goto error; - - if (*mode != DRXK_POWER_DOWN_OFDM) { -- state->m_hi_cfg_ctrl |= -+ state->m_HICfgCtrl |= - SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; -- status = hi_cfg_command(state); -+ status = HI_CfgCommand(state); - if (status < 0) - goto error; - } - } -- state->m_current_power_mode = *mode; -+ state->m_currentPowerMode = *mode; - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) -+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) - { -- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; -- u16 cmd_result = 0; -+ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; -+ u16 cmdResult = 0; - u16 data = 0; - int status; - -@@ -1703,17 +1759,11 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) - goto error; - if (data == SCU_COMM_EXEC_ACTIVE) { - /* Send OFDM stop command */ -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - /* Send OFDM reset command */ -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - } -@@ -1730,24 +1780,24 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) - goto error; - - /* powerdown AFE */ -- status = set_iqm_af(state, false); -+ status = SetIqmAf(state, false); - if (status < 0) - goto error; - - /* powerdown to OFDM mode */ -- if (set_power_mode) { -- status = ctrl_power_mode(state, &power_mode); -+ if (setPowerMode) { -+ status = CtrlPowerMode(state, &powerMode); - if (status < 0) - goto error; - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int setoperation_mode(struct drxk_state *state, -- enum operation_mode o_mode) -+static int SetOperationMode(struct drxk_state *state, -+ enum OperationMode oMode) - { - int status = 0; - -@@ -1759,37 +1809,36 @@ static int setoperation_mode(struct drxk_state *state, - */ - - /* disable HW lock indicator */ -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; - - /* Device is already at the required mode */ -- if (state->m_operation_mode == o_mode) -+ if (state->m_OperationMode == oMode) - return 0; - -- switch (state->m_operation_mode) { -+ switch (state->m_OperationMode) { - /* OM_NONE was added for start up */ - case OM_NONE: - break; - case OM_DVBT: -- status = mpegts_stop(state); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = power_down_dvbt(state, true); -+ status = PowerDownDVBT(state, true); - if (status < 0) - goto error; -- state->m_operation_mode = OM_NONE; -+ state->m_OperationMode = OM_NONE; - break; - case OM_QAM_ITU_A: /* fallthrough */ - case OM_QAM_ITU_C: -- status = mpegts_stop(state); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = power_down_qam(state); -+ status = PowerDownQAM(state); - if (status < 0) - goto error; -- state->m_operation_mode = OM_NONE; -+ state->m_OperationMode = OM_NONE; - break; - case OM_QAM_ITU_B: - default: -@@ -1800,20 +1849,20 @@ static int setoperation_mode(struct drxk_state *state, - /* - Power up new standard - */ -- switch (o_mode) { -+ switch (oMode) { - case OM_DVBT: - dprintk(1, ": DVB-T\n"); -- state->m_operation_mode = o_mode; -- status = set_dvbt_standard(state, o_mode); -+ state->m_OperationMode = oMode; -+ status = SetDVBTStandard(state, oMode); - if (status < 0) - goto error; - break; - case OM_QAM_ITU_A: /* fallthrough */ - case OM_QAM_ITU_C: - dprintk(1, ": DVB-C Annex %c\n", -- (state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C'); -- state->m_operation_mode = o_mode; -- status = set_qam_standard(state, o_mode); -+ (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C'); -+ state->m_OperationMode = oMode; -+ status = SetQAMStandard(state, oMode); - if (status < 0) - goto error; - break; -@@ -1823,121 +1872,123 @@ static int setoperation_mode(struct drxk_state *state, - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int start(struct drxk_state *state, s32 offset_freq, -- s32 intermediate_frequency) -+static int Start(struct drxk_state *state, s32 offsetFreq, -+ s32 IntermediateFrequency) - { - int status = -EINVAL; - -- u16 i_freqk_hz; -- s32 offsetk_hz = offset_freq / 1000; -+ u16 IFreqkHz; -+ s32 OffsetkHz = offsetFreq / 1000; - - dprintk(1, "\n"); -- if (state->m_drxk_state != DRXK_STOPPED && -- state->m_drxk_state != DRXK_DTV_STARTED) -+ if (state->m_DrxkState != DRXK_STOPPED && -+ state->m_DrxkState != DRXK_DTV_STARTED) - goto error; - -- state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON); -+ state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON); - -- if (intermediate_frequency < 0) { -- state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect; -- intermediate_frequency = -intermediate_frequency; -+ if (IntermediateFrequency < 0) { -+ state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect; -+ IntermediateFrequency = -IntermediateFrequency; - } - -- switch (state->m_operation_mode) { -+ switch (state->m_OperationMode) { - case OM_QAM_ITU_A: - case OM_QAM_ITU_C: -- i_freqk_hz = (intermediate_frequency / 1000); -- status = set_qam(state, i_freqk_hz, offsetk_hz); -+ IFreqkHz = (IntermediateFrequency / 1000); -+ status = SetQAM(state, IFreqkHz, OffsetkHz); - if (status < 0) - goto error; -- state->m_drxk_state = DRXK_DTV_STARTED; -+ state->m_DrxkState = DRXK_DTV_STARTED; - break; - case OM_DVBT: -- i_freqk_hz = (intermediate_frequency / 1000); -- status = mpegts_stop(state); -+ IFreqkHz = (IntermediateFrequency / 1000); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = set_dvbt(state, i_freqk_hz, offsetk_hz); -+ status = SetDVBT(state, IFreqkHz, OffsetkHz); - if (status < 0) - goto error; -- status = dvbt_start(state); -+ status = DVBTStart(state); - if (status < 0) - goto error; -- state->m_drxk_state = DRXK_DTV_STARTED; -+ state->m_DrxkState = DRXK_DTV_STARTED; - break; - default: - break; - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int shut_down(struct drxk_state *state) -+static int ShutDown(struct drxk_state *state) - { - dprintk(1, "\n"); - -- mpegts_stop(state); -+ MPEGTSStop(state); - return 0; - } - --static int get_lock_status(struct drxk_state *state, u32 *p_lock_status) -+static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus, -+ u32 Time) - { - int status = -EINVAL; - - dprintk(1, "\n"); - -- if (p_lock_status == NULL) -+ if (pLockStatus == NULL) - goto error; - -- *p_lock_status = NOT_LOCKED; -+ *pLockStatus = NOT_LOCKED; - - /* define the SCU command code */ -- switch (state->m_operation_mode) { -+ switch (state->m_OperationMode) { - case OM_QAM_ITU_A: - case OM_QAM_ITU_B: - case OM_QAM_ITU_C: -- status = get_qam_lock_status(state, p_lock_status); -+ status = GetQAMLockStatus(state, pLockStatus); - break; - case OM_DVBT: -- status = get_dvbt_lock_status(state, p_lock_status); -+ status = GetDVBTLockStatus(state, pLockStatus); - break; - default: -+ status = 0; - break; - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int mpegts_start(struct drxk_state *state) -+static int MPEGTSStart(struct drxk_state *state) - { - int status; - -- u16 fec_oc_snc_mode = 0; -+ u16 fecOcSncMode = 0; - - /* Allow OC to sync again */ -- status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); -+ status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); - if (status < 0) - goto error; -- fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; -- status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); -+ fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; -+ status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); - if (status < 0) - goto error; - status = write16(state, FEC_OC_SNC_UNLOCK__A, 1); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int mpegts_dto_init(struct drxk_state *state) -+static int MPEGTSDtoInit(struct drxk_state *state) - { - int status; - -@@ -1979,68 +2030,68 @@ static int mpegts_dto_init(struct drxk_state *state) - status = write16(state, FEC_OC_SNC_HWM__A, 12); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static int mpegts_dto_setup(struct drxk_state *state, -- enum operation_mode o_mode) -+static int MPEGTSDtoSetup(struct drxk_state *state, -+ enum OperationMode oMode) - { - int status; - -- u16 fec_oc_reg_mode = 0; /* FEC_OC_MODE register value */ -- u16 fec_oc_reg_ipr_mode = 0; /* FEC_OC_IPR_MODE register value */ -- u16 fec_oc_dto_mode = 0; /* FEC_OC_IPR_INVERT register value */ -- u16 fec_oc_fct_mode = 0; /* FEC_OC_IPR_INVERT register value */ -- u16 fec_oc_dto_period = 2; /* FEC_OC_IPR_INVERT register value */ -- u16 fec_oc_dto_burst_len = 188; /* FEC_OC_IPR_INVERT register value */ -- u32 fec_oc_rcn_ctl_rate = 0; /* FEC_OC_IPR_INVERT register value */ -- u16 fec_oc_tmd_mode = 0; -- u16 fec_oc_tmd_int_upd_rate = 0; -- u32 max_bit_rate = 0; -- bool static_clk = false; -+ u16 fecOcRegMode = 0; /* FEC_OC_MODE register value */ -+ u16 fecOcRegIprMode = 0; /* FEC_OC_IPR_MODE register value */ -+ u16 fecOcDtoMode = 0; /* FEC_OC_IPR_INVERT register value */ -+ u16 fecOcFctMode = 0; /* FEC_OC_IPR_INVERT register value */ -+ u16 fecOcDtoPeriod = 2; /* FEC_OC_IPR_INVERT register value */ -+ u16 fecOcDtoBurstLen = 188; /* FEC_OC_IPR_INVERT register value */ -+ u32 fecOcRcnCtlRate = 0; /* FEC_OC_IPR_INVERT register value */ -+ u16 fecOcTmdMode = 0; -+ u16 fecOcTmdIntUpdRate = 0; -+ u32 maxBitRate = 0; -+ bool staticCLK = false; - - dprintk(1, "\n"); - - /* Check insertion of the Reed-Solomon parity bytes */ -- status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode); -+ status = read16(state, FEC_OC_MODE__A, &fecOcRegMode); - if (status < 0) - goto error; -- status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode); -+ status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode); - if (status < 0) - goto error; -- fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); -- fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); -- if (state->m_insert_rs_byte) { -+ fecOcRegMode &= (~FEC_OC_MODE_PARITY__M); -+ fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); -+ if (state->m_insertRSByte == true) { - /* enable parity symbol forward */ -- fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; -+ fecOcRegMode |= FEC_OC_MODE_PARITY__M; - /* MVAL disable during parity bytes */ -- fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; -+ fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; - /* TS burst length to 204 */ -- fec_oc_dto_burst_len = 204; -+ fecOcDtoBurstLen = 204; - } - -- /* Check serial or parallel output */ -- fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); -- if (!state->m_enable_parallel) { -+ /* Check serial or parrallel output */ -+ fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); -+ if (state->m_enableParallel == false) { - /* MPEG data output is serial -> set ipr_mode[0] */ -- fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; -+ fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M; - } - -- switch (o_mode) { -+ switch (oMode) { - case OM_DVBT: -- max_bit_rate = state->m_dvbt_bitrate; -- fec_oc_tmd_mode = 3; -- fec_oc_rcn_ctl_rate = 0xC00000; -- static_clk = state->m_dvbt_static_clk; -+ maxBitRate = state->m_DVBTBitrate; -+ fecOcTmdMode = 3; -+ fecOcRcnCtlRate = 0xC00000; -+ staticCLK = state->m_DVBTStaticCLK; - break; - case OM_QAM_ITU_A: /* fallthrough */ - case OM_QAM_ITU_C: -- fec_oc_tmd_mode = 0x0004; -- fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */ -- max_bit_rate = state->m_dvbc_bitrate; -- static_clk = state->m_dvbc_static_clk; -+ fecOcTmdMode = 0x0004; -+ fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ -+ maxBitRate = state->m_DVBCBitrate; -+ staticCLK = state->m_DVBCStaticCLK; - break; - default: - status = -EINVAL; -@@ -2049,84 +2100,83 @@ static int mpegts_dto_setup(struct drxk_state *state, - goto error; - - /* Configure DTO's */ -- if (static_clk) { -- u32 bit_rate = 0; -+ if (staticCLK) { -+ u32 bitRate = 0; - - /* Rational DTO for MCLK source (static MCLK rate), - Dynamic DTO for optimal grouping - (avoid intra-packet gaps), - DTO offset enable to sync TS burst with MSTRT */ -- fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M | -+ fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M | - FEC_OC_DTO_MODE_OFFSET_ENABLE__M); -- fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M | -+ fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M | - FEC_OC_FCT_MODE_VIRT_ENA__M); - - /* Check user defined bitrate */ -- bit_rate = max_bit_rate; -- if (bit_rate > 75900000UL) { /* max is 75.9 Mb/s */ -- bit_rate = 75900000UL; -+ bitRate = maxBitRate; -+ if (bitRate > 75900000UL) { /* max is 75.9 Mb/s */ -+ bitRate = 75900000UL; - } - /* Rational DTO period: - dto_period = (Fsys / bitrate) - 2 - -- result should be floored, -+ Result should be floored, - to make sure >= requested bitrate - */ -- fec_oc_dto_period = (u16) (((state->m_sys_clock_freq) -- * 1000) / bit_rate); -- if (fec_oc_dto_period <= 2) -- fec_oc_dto_period = 0; -+ fecOcDtoPeriod = (u16) (((state->m_sysClockFreq) -+ * 1000) / bitRate); -+ if (fecOcDtoPeriod <= 2) -+ fecOcDtoPeriod = 0; - else -- fec_oc_dto_period -= 2; -- fec_oc_tmd_int_upd_rate = 8; -+ fecOcDtoPeriod -= 2; -+ fecOcTmdIntUpdRate = 8; - } else { -- /* (commonAttr->static_clk == false) => dynamic mode */ -- fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M; -- fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE; -- fec_oc_tmd_int_upd_rate = 5; -+ /* (commonAttr->staticCLK == false) => dynamic mode */ -+ fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M; -+ fecOcFctMode = FEC_OC_FCT_MODE__PRE; -+ fecOcTmdIntUpdRate = 5; - } - - /* Write appropriate registers with requested configuration */ -- status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len); -+ status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period); -+ status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode); -+ status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode); -+ status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode); -+ status = write16(state, FEC_OC_MODE__A, fecOcRegMode); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode); -+ status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode); - if (status < 0) - goto error; - - /* Rate integration settings */ -- status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate); -+ status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, -- fec_oc_tmd_int_upd_rate); -+ status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); -+ status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int mpegts_configure_polarity(struct drxk_state *state) -+static int MPEGTSConfigurePolarity(struct drxk_state *state) - { -- u16 fec_oc_reg_ipr_invert = 0; -+ u16 fecOcRegIprInvert = 0; - - /* Data mask for the output data byte */ -- u16 invert_data_mask = -+ u16 InvertDataMask = - FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | - FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | - FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | -@@ -2135,40 +2185,40 @@ static int mpegts_configure_polarity(struct drxk_state *state) - dprintk(1, "\n"); - - /* Control selective inversion of output bits */ -- fec_oc_reg_ipr_invert &= (~(invert_data_mask)); -- if (state->m_invert_data) -- fec_oc_reg_ipr_invert |= invert_data_mask; -- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); -- if (state->m_invert_err) -- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; -- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); -- if (state->m_invert_str) -- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; -- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); -- if (state->m_invert_val) -- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; -- fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); -- if (state->m_invert_clk) -- fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; -- -- return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); -+ fecOcRegIprInvert &= (~(InvertDataMask)); -+ if (state->m_invertDATA == true) -+ fecOcRegIprInvert |= InvertDataMask; -+ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M)); -+ if (state->m_invertERR == true) -+ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M; -+ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); -+ if (state->m_invertSTR == true) -+ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M; -+ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); -+ if (state->m_invertVAL == true) -+ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M; -+ fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); -+ if (state->m_invertCLK == true) -+ fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M; -+ -+ return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert); - } - - #define SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000 - --static int set_agc_rf(struct drxk_state *state, -- struct s_cfg_agc *p_agc_cfg, bool is_dtv) -+static int SetAgcRf(struct drxk_state *state, -+ struct SCfgAgc *pAgcCfg, bool isDTV) - { - int status = -EINVAL; - u16 data = 0; -- struct s_cfg_agc *p_if_agc_settings; -+ struct SCfgAgc *pIfAgcSettings; - - dprintk(1, "\n"); - -- if (p_agc_cfg == NULL) -+ if (pAgcCfg == NULL) - goto error; - -- switch (p_agc_cfg->ctrl_mode) { -+ switch (pAgcCfg->ctrlMode) { - case DRXK_AGC_CTRL_AUTO: - /* Enable RF AGC DAC */ - status = read16(state, IQM_AF_STDBY__A, &data); -@@ -2186,7 +2236,7 @@ static int set_agc_rf(struct drxk_state *state, - data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; - - /* Polarity */ -- if (state->m_rf_agc_pol) -+ if (state->m_RfAgcPol) - data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; - else - data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; -@@ -2200,7 +2250,7 @@ static int set_agc_rf(struct drxk_state *state, - goto error; - - data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; -- data |= (~(p_agc_cfg->speed << -+ data |= (~(pAgcCfg->speed << - SCU_RAM_AGC_KI_RED_RAGC_RED__B) - & SCU_RAM_AGC_KI_RED_RAGC_RED__M); - -@@ -2208,35 +2258,30 @@ static int set_agc_rf(struct drxk_state *state, - if (status < 0) - goto error; - -- if (is_dvbt(state)) -- p_if_agc_settings = &state->m_dvbt_if_agc_cfg; -- else if (is_qam(state)) -- p_if_agc_settings = &state->m_qam_if_agc_cfg; -+ if (IsDVBT(state)) -+ pIfAgcSettings = &state->m_dvbtIfAgcCfg; -+ else if (IsQAM(state)) -+ pIfAgcSettings = &state->m_qamIfAgcCfg; - else -- p_if_agc_settings = &state->m_atv_if_agc_cfg; -- if (p_if_agc_settings == NULL) { -+ pIfAgcSettings = &state->m_atvIfAgcCfg; -+ if (pIfAgcSettings == NULL) { - status = -EINVAL; - goto error; - } - - /* Set TOP, only if IF-AGC is in AUTO mode */ -- if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) { -- status = write16(state, -- SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, -- p_agc_cfg->top); -+ if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO) -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top); - if (status < 0) - goto error; -- } - - /* Cut-Off current */ -- status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, -- p_agc_cfg->cut_off_current); -+ status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent); - if (status < 0) - goto error; - - /* Max. output level */ -- status = write16(state, SCU_RAM_AGC_RF_MAX__A, -- p_agc_cfg->max_output_level); -+ status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel); - if (status < 0) - goto error; - -@@ -2257,7 +2302,7 @@ static int set_agc_rf(struct drxk_state *state, - if (status < 0) - goto error; - data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; -- if (state->m_rf_agc_pol) -+ if (state->m_RfAgcPol) - data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; - else - data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; -@@ -2271,8 +2316,7 @@ static int set_agc_rf(struct drxk_state *state, - goto error; - - /* Write value to output pin */ -- status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, -- p_agc_cfg->output_level); -+ status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel); - if (status < 0) - goto error; - break; -@@ -2303,22 +2347,22 @@ static int set_agc_rf(struct drxk_state *state, - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - - #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000 - --static int set_agc_if(struct drxk_state *state, -- struct s_cfg_agc *p_agc_cfg, bool is_dtv) -+static int SetAgcIf(struct drxk_state *state, -+ struct SCfgAgc *pAgcCfg, bool isDTV) - { - u16 data = 0; - int status = 0; -- struct s_cfg_agc *p_rf_agc_settings; -+ struct SCfgAgc *pRfAgcSettings; - - dprintk(1, "\n"); - -- switch (p_agc_cfg->ctrl_mode) { -+ switch (pAgcCfg->ctrlMode) { - case DRXK_AGC_CTRL_AUTO: - - /* Enable IF AGC DAC */ -@@ -2338,7 +2382,7 @@ static int set_agc_if(struct drxk_state *state, - data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; - - /* Polarity */ -- if (state->m_if_agc_pol) -+ if (state->m_IfAgcPol) - data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; - else - data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; -@@ -2351,7 +2395,7 @@ static int set_agc_if(struct drxk_state *state, - if (status < 0) - goto error; - data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; -- data |= (~(p_agc_cfg->speed << -+ data |= (~(pAgcCfg->speed << - SCU_RAM_AGC_KI_RED_IAGC_RED__B) - & SCU_RAM_AGC_KI_RED_IAGC_RED__M); - -@@ -2359,15 +2403,14 @@ static int set_agc_if(struct drxk_state *state, - if (status < 0) - goto error; - -- if (is_qam(state)) -- p_rf_agc_settings = &state->m_qam_rf_agc_cfg; -+ if (IsQAM(state)) -+ pRfAgcSettings = &state->m_qamRfAgcCfg; - else -- p_rf_agc_settings = &state->m_atv_rf_agc_cfg; -- if (p_rf_agc_settings == NULL) -+ pRfAgcSettings = &state->m_atvRfAgcCfg; -+ if (pRfAgcSettings == NULL) - return -1; - /* Restore TOP */ -- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, -- p_rf_agc_settings->top); -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top); - if (status < 0) - goto error; - break; -@@ -2391,7 +2434,7 @@ static int set_agc_if(struct drxk_state *state, - data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; - - /* Polarity */ -- if (state->m_if_agc_pol) -+ if (state->m_IfAgcPol) - data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; - else - data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; -@@ -2400,8 +2443,7 @@ static int set_agc_if(struct drxk_state *state, - goto error; - - /* Write value to output pin */ -- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, -- p_agc_cfg->output_level); -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel); - if (status < 0) - goto error; - break; -@@ -2426,181 +2468,207 @@ static int set_agc_if(struct drxk_state *state, - if (status < 0) - goto error; - break; -- } /* switch (agcSettingsIf->ctrl_mode) */ -+ } /* switch (agcSettingsIf->ctrlMode) */ - - /* always set the top to support - configurations without if-loop */ -- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top); -+ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int get_qam_signal_to_noise(struct drxk_state *state, -- s32 *p_signal_to_noise) -+static int ReadIFAgc(struct drxk_state *state, u32 *pValue) -+{ -+ u16 agcDacLvl; -+ int status; -+ u16 Level = 0; -+ -+ dprintk(1, "\n"); -+ -+ status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl); -+ if (status < 0) { -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); -+ return status; -+ } -+ -+ *pValue = 0; -+ -+ if (agcDacLvl > DRXK_AGC_DAC_OFFSET) -+ Level = agcDacLvl - DRXK_AGC_DAC_OFFSET; -+ if (Level < 14000) -+ *pValue = (14000 - Level) / 4; -+ else -+ *pValue = 0; -+ -+ return status; -+} -+ -+static int GetQAMSignalToNoise(struct drxk_state *state, -+ s32 *pSignalToNoise) - { - int status = 0; -- u16 qam_sl_err_power = 0; /* accum. error between -+ u16 qamSlErrPower = 0; /* accum. error between - raw and sliced symbols */ -- u32 qam_sl_sig_power = 0; /* used for MER, depends of -+ u32 qamSlSigPower = 0; /* used for MER, depends of - QAM modulation */ -- u32 qam_sl_mer = 0; /* QAM MER */ -+ u32 qamSlMer = 0; /* QAM MER */ - - dprintk(1, "\n"); - - /* MER calculation */ - - /* get the register value needed for MER */ -- status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); -+ status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower); - if (status < 0) { -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return -EINVAL; - } - - switch (state->props.modulation) { - case QAM_16: -- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; -+ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; - break; - case QAM_32: -- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; -+ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; - break; - case QAM_64: -- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; -+ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; - break; - case QAM_128: -- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; -+ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; - break; - default: - case QAM_256: -- qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; -+ qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; - break; - } - -- if (qam_sl_err_power > 0) { -- qam_sl_mer = log10times100(qam_sl_sig_power) - -- log10times100((u32) qam_sl_err_power); -+ if (qamSlErrPower > 0) { -+ qamSlMer = Log10Times100(qamSlSigPower) - -+ Log10Times100((u32) qamSlErrPower); - } -- *p_signal_to_noise = qam_sl_mer; -+ *pSignalToNoise = qamSlMer; - - return status; - } - --static int get_dvbt_signal_to_noise(struct drxk_state *state, -- s32 *p_signal_to_noise) -+static int GetDVBTSignalToNoise(struct drxk_state *state, -+ s32 *pSignalToNoise) - { - int status; -- u16 reg_data = 0; -- u32 eq_reg_td_sqr_err_i = 0; -- u32 eq_reg_td_sqr_err_q = 0; -- u16 eq_reg_td_sqr_err_exp = 0; -- u16 eq_reg_td_tps_pwr_ofs = 0; -- u16 eq_reg_td_req_smb_cnt = 0; -- u32 tps_cnt = 0; -- u32 sqr_err_iq = 0; -+ u16 regData = 0; -+ u32 EqRegTdSqrErrI = 0; -+ u32 EqRegTdSqrErrQ = 0; -+ u16 EqRegTdSqrErrExp = 0; -+ u16 EqRegTdTpsPwrOfs = 0; -+ u16 EqRegTdReqSmbCnt = 0; -+ u32 tpsCnt = 0; -+ u32 SqrErrIQ = 0; - u32 a = 0; - u32 b = 0; - u32 c = 0; -- u32 i_mer = 0; -- u16 transmission_params = 0; -+ u32 iMER = 0; -+ u16 transmissionParams = 0; - - dprintk(1, "\n"); - -- status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, -- &eq_reg_td_tps_pwr_ofs); -+ status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs); - if (status < 0) - goto error; -- status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, -- &eq_reg_td_req_smb_cnt); -+ status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt); - if (status < 0) - goto error; -- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, -- &eq_reg_td_sqr_err_exp); -+ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp); - if (status < 0) - goto error; -- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, -- ®_data); -+ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®Data); - if (status < 0) - goto error; - /* Extend SQR_ERR_I operational range */ -- eq_reg_td_sqr_err_i = (u32) reg_data; -- if ((eq_reg_td_sqr_err_exp > 11) && -- (eq_reg_td_sqr_err_i < 0x00000FFFUL)) { -- eq_reg_td_sqr_err_i += 0x00010000UL; -+ EqRegTdSqrErrI = (u32) regData; -+ if ((EqRegTdSqrErrExp > 11) && -+ (EqRegTdSqrErrI < 0x00000FFFUL)) { -+ EqRegTdSqrErrI += 0x00010000UL; - } -- status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®_data); -+ status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®Data); - if (status < 0) - goto error; - /* Extend SQR_ERR_Q operational range */ -- eq_reg_td_sqr_err_q = (u32) reg_data; -- if ((eq_reg_td_sqr_err_exp > 11) && -- (eq_reg_td_sqr_err_q < 0x00000FFFUL)) -- eq_reg_td_sqr_err_q += 0x00010000UL; -+ EqRegTdSqrErrQ = (u32) regData; -+ if ((EqRegTdSqrErrExp > 11) && -+ (EqRegTdSqrErrQ < 0x00000FFFUL)) -+ EqRegTdSqrErrQ += 0x00010000UL; - -- status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, -- &transmission_params); -+ status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams); - if (status < 0) - goto error; - - /* Check input data for MER */ - - /* MER calculation (in 0.1 dB) without math.h */ -- if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0)) -- i_mer = 0; -- else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) { -+ if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0)) -+ iMER = 0; -+ else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) { - /* No error at all, this must be the HW reset value - * Apparently no first measurement yet - * Set MER to 0.0 */ -- i_mer = 0; -+ iMER = 0; - } else { -- sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) << -- eq_reg_td_sqr_err_exp; -- if ((transmission_params & -+ SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) << -+ EqRegTdSqrErrExp; -+ if ((transmissionParams & - OFDM_SC_RA_RAM_OP_PARAM_MODE__M) - == OFDM_SC_RA_RAM_OP_PARAM_MODE_2K) -- tps_cnt = 17; -+ tpsCnt = 17; - else -- tps_cnt = 68; -+ tpsCnt = 68; - - /* IMER = 100 * log10 (x) -- where x = (eq_reg_td_tps_pwr_ofs^2 * -- eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq -+ where x = (EqRegTdTpsPwrOfs^2 * -+ EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ - - => IMER = a + b -c -- where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2) -- b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt) -- c = 100 * log10 (sqr_err_iq) -+ where a = 100 * log10 (EqRegTdTpsPwrOfs^2) -+ b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt) -+ c = 100 * log10 (SqrErrIQ) - */ - - /* log(x) x = 9bits * 9bits->18 bits */ -- a = log10times100(eq_reg_td_tps_pwr_ofs * -- eq_reg_td_tps_pwr_ofs); -+ a = Log10Times100(EqRegTdTpsPwrOfs * -+ EqRegTdTpsPwrOfs); - /* log(x) x = 16bits * 7bits->23 bits */ -- b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt); -+ b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt); - /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ -- c = log10times100(sqr_err_iq); -+ c = Log10Times100(SqrErrIQ); - -- i_mer = a + b - c; -+ iMER = a + b; -+ /* No negative MER, clip to zero */ -+ if (iMER > c) -+ iMER -= c; -+ else -+ iMER = 0; - } -- *p_signal_to_noise = i_mer; -+ *pSignalToNoise = iMER; - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) -+static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) - { - dprintk(1, "\n"); - -- *p_signal_to_noise = 0; -- switch (state->m_operation_mode) { -+ *pSignalToNoise = 0; -+ switch (state->m_OperationMode) { - case OM_DVBT: -- return get_dvbt_signal_to_noise(state, p_signal_to_noise); -+ return GetDVBTSignalToNoise(state, pSignalToNoise); - case OM_QAM_ITU_A: - case OM_QAM_ITU_C: -- return get_qam_signal_to_noise(state, p_signal_to_noise); -+ return GetQAMSignalToNoise(state, pSignalToNoise); - default: - break; - } -@@ -2608,7 +2676,7 @@ static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) - } - - #if 0 --static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) -+static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) - { - /* SNR Values for quasi errorfree reception rom Nordig 2.2 */ - int status = 0; -@@ -2633,104 +2701,102 @@ static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) - 225, /* 64-QAM 7/8 */ - }; - -- *p_quality = 0; -+ *pQuality = 0; - - do { -- s32 signal_to_noise = 0; -- u16 constellation = 0; -- u16 code_rate = 0; -- u32 signal_to_noise_rel; -- u32 ber_quality; -+ s32 SignalToNoise = 0; -+ u16 Constellation = 0; -+ u16 CodeRate = 0; -+ u32 SignalToNoiseRel; -+ u32 BERQuality; - -- status = get_dvbt_signal_to_noise(state, &signal_to_noise); -+ status = GetDVBTSignalToNoise(state, &SignalToNoise); - if (status < 0) - break; -- status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, -- &constellation); -+ status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation); - if (status < 0) - break; -- constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; -+ Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; - -- status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, -- &code_rate); -+ status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate); - if (status < 0) - break; -- code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; -+ CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; - -- if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || -- code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) -+ if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || -+ CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) - break; -- signal_to_noise_rel = signal_to_noise - -- QE_SN[constellation * 5 + code_rate]; -- ber_quality = 100; -- -- if (signal_to_noise_rel < -70) -- *p_quality = 0; -- else if (signal_to_noise_rel < 30) -- *p_quality = ((signal_to_noise_rel + 70) * -- ber_quality) / 100; -+ SignalToNoiseRel = SignalToNoise - -+ QE_SN[Constellation * 5 + CodeRate]; -+ BERQuality = 100; -+ -+ if (SignalToNoiseRel < -70) -+ *pQuality = 0; -+ else if (SignalToNoiseRel < 30) -+ *pQuality = ((SignalToNoiseRel + 70) * -+ BERQuality) / 100; - else -- *p_quality = ber_quality; -+ *pQuality = BERQuality; - } while (0); - return 0; - }; - --static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality) -+static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality) - { - int status = 0; -- *p_quality = 0; -+ *pQuality = 0; - - dprintk(1, "\n"); - - do { -- u32 signal_to_noise = 0; -- u32 ber_quality = 100; -- u32 signal_to_noise_rel = 0; -+ u32 SignalToNoise = 0; -+ u32 BERQuality = 100; -+ u32 SignalToNoiseRel = 0; - -- status = get_qam_signal_to_noise(state, &signal_to_noise); -+ status = GetQAMSignalToNoise(state, &SignalToNoise); - if (status < 0) - break; - - switch (state->props.modulation) { - case QAM_16: -- signal_to_noise_rel = signal_to_noise - 200; -+ SignalToNoiseRel = SignalToNoise - 200; - break; - case QAM_32: -- signal_to_noise_rel = signal_to_noise - 230; -+ SignalToNoiseRel = SignalToNoise - 230; - break; /* Not in NorDig */ - case QAM_64: -- signal_to_noise_rel = signal_to_noise - 260; -+ SignalToNoiseRel = SignalToNoise - 260; - break; - case QAM_128: -- signal_to_noise_rel = signal_to_noise - 290; -+ SignalToNoiseRel = SignalToNoise - 290; - break; - default: - case QAM_256: -- signal_to_noise_rel = signal_to_noise - 320; -+ SignalToNoiseRel = SignalToNoise - 320; - break; - } - -- if (signal_to_noise_rel < -70) -- *p_quality = 0; -- else if (signal_to_noise_rel < 30) -- *p_quality = ((signal_to_noise_rel + 70) * -- ber_quality) / 100; -+ if (SignalToNoiseRel < -70) -+ *pQuality = 0; -+ else if (SignalToNoiseRel < 30) -+ *pQuality = ((SignalToNoiseRel + 70) * -+ BERQuality) / 100; - else -- *p_quality = ber_quality; -+ *pQuality = BERQuality; - } while (0); - - return status; - } - --static int get_quality(struct drxk_state *state, s32 *p_quality) -+static int GetQuality(struct drxk_state *state, s32 *pQuality) - { - dprintk(1, "\n"); - -- switch (state->m_operation_mode) { -+ switch (state->m_OperationMode) { - case OM_DVBT: -- return get_dvbt_quality(state, p_quality); -+ return GetDVBTQuality(state, pQuality); - case OM_QAM_ITU_A: -- return get_dvbc_quality(state, p_quality); -+ return GetDVBCQuality(state, pQuality); - default: - break; - } -@@ -2752,68 +2818,65 @@ static int get_quality(struct drxk_state *state, s32 *p_quality) - #define DRXDAP_FASI_ADDR2BANK(addr) (((addr) >> 16) & 0x3F) - #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF) - --static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) -+static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) - { - int status = -EINVAL; - - dprintk(1, "\n"); - -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return 0; -- if (state->m_drxk_state == DRXK_POWERED_DOWN) -+ if (state->m_DrxkState == DRXK_UNINITIALIZED) -+ goto error; -+ if (state->m_DrxkState == DRXK_POWERED_DOWN) - goto error; - - if (state->no_i2c_bridge) - return 0; - -- status = write16(state, SIO_HI_RA_RAM_PAR_1__A, -- SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); -+ status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); - if (status < 0) - goto error; -- if (b_enable_bridge) { -- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, -- SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); -+ if (bEnableBridge) { -+ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); - if (status < 0) - goto error; - } else { -- status = write16(state, SIO_HI_RA_RAM_PAR_2__A, -- SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); -+ status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); - if (status < 0) - goto error; - } - -- status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, NULL); -+ status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int set_pre_saw(struct drxk_state *state, -- struct s_cfg_pre_saw *p_pre_saw_cfg) -+static int SetPreSaw(struct drxk_state *state, -+ struct SCfgPreSaw *pPreSawCfg) - { - int status = -EINVAL; - - dprintk(1, "\n"); - -- if ((p_pre_saw_cfg == NULL) -- || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M)) -+ if ((pPreSawCfg == NULL) -+ || (pPreSawCfg->reference > IQM_AF_PDREF__M)) - goto error; - -- status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference); -+ status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, -- u16 rom_offset, u16 nr_of_elements, u32 time_out) -+static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, -+ u16 romOffset, u16 nrOfElements, u32 timeOut) - { -- u16 bl_status = 0; -- u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF); -- u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF); -+ u16 blStatus = 0; -+ u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF); -+ u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF); - int status; - unsigned long end; - -@@ -2829,44 +2892,44 @@ static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, - status = write16(state, SIO_BL_TGT_ADDR__A, offset); - if (status < 0) - goto error; -- status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset); -+ status = write16(state, SIO_BL_SRC_ADDR__A, romOffset); - if (status < 0) - goto error; -- status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements); -+ status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements); - if (status < 0) - goto error; - status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); - if (status < 0) - goto error; - -- end = jiffies + msecs_to_jiffies(time_out); -+ end = jiffies + msecs_to_jiffies(timeOut); - do { -- status = read16(state, SIO_BL_STATUS__A, &bl_status); -+ status = read16(state, SIO_BL_STATUS__A, &blStatus); - if (status < 0) - goto error; -- } while ((bl_status == 0x1) && time_is_after_jiffies(end)); -- if (bl_status == 0x1) { -- pr_err("SIO not ready\n"); -+ } while ((blStatus == 0x1) && time_is_after_jiffies(end)); -+ if (blStatus == 0x1) { -+ printk(KERN_ERR "drxk: SIO not ready\n"); - status = -EINVAL; - goto error2; - } - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - error2: - mutex_unlock(&state->mutex); - return status; - - } - --static int adc_sync_measurement(struct drxk_state *state, u16 *count) -+static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) - { - u16 data = 0; - int status; - - dprintk(1, "\n"); - -- /* start measurement */ -+ /* Start measurement */ - status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE); - if (status < 0) - goto error; -@@ -2893,42 +2956,42 @@ static int adc_sync_measurement(struct drxk_state *state, u16 *count) - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int adc_synchronization(struct drxk_state *state) -+static int ADCSynchronization(struct drxk_state *state) - { - u16 count = 0; - int status; - - dprintk(1, "\n"); - -- status = adc_sync_measurement(state, &count); -+ status = ADCSyncMeasurement(state, &count); - if (status < 0) - goto error; - - if (count == 1) { -- /* Try sampling on a different edge */ -- u16 clk_neg = 0; -+ /* Try sampling on a diffrent edge */ -+ u16 clkNeg = 0; - -- status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); -+ status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); - if (status < 0) - goto error; -- if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) == -+ if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) == - IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { -- clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); -- clk_neg |= -+ clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); -+ clkNeg |= - IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG; - } else { -- clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); -- clk_neg |= -+ clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); -+ clkNeg |= - IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS; - } -- status = write16(state, IQM_AF_CLKNEG__A, clk_neg); -+ status = write16(state, IQM_AF_CLKNEG__A, clkNeg); - if (status < 0) - goto error; -- status = adc_sync_measurement(state, &count); -+ status = ADCSyncMeasurement(state, &count); - if (status < 0) - goto error; - } -@@ -2937,25 +3000,25 @@ static int adc_synchronization(struct drxk_state *state) - status = -EINVAL; - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int set_frequency_shifter(struct drxk_state *state, -- u16 intermediate_freqk_hz, -- s32 tuner_freq_offset, bool is_dtv) -+static int SetFrequencyShifter(struct drxk_state *state, -+ u16 intermediateFreqkHz, -+ s32 tunerFreqOffset, bool isDTV) - { -- bool select_pos_image = false; -- u32 rf_freq_residual = tuner_freq_offset; -- u32 fm_frequency_shift = 0; -- bool tuner_mirror = !state->m_b_mirror_freq_spect; -- u32 adc_freq; -- bool adc_flip; -+ bool selectPosImage = false; -+ u32 rfFreqResidual = tunerFreqOffset; -+ u32 fmFrequencyShift = 0; -+ bool tunerMirror = !state->m_bMirrorFreqSpect; -+ u32 adcFreq; -+ bool adcFlip; - int status; -- u32 if_freq_actual; -- u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3); -- u32 frequency_shift; -- bool image_to_select; -+ u32 ifFreqActual; -+ u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3); -+ u32 frequencyShift; -+ bool imageToSelect; - - dprintk(1, "\n"); - -@@ -2963,125 +3026,121 @@ static int set_frequency_shifter(struct drxk_state *state, - Program frequency shifter - No need to account for mirroring on RF - */ -- if (is_dtv) { -- if ((state->m_operation_mode == OM_QAM_ITU_A) || -- (state->m_operation_mode == OM_QAM_ITU_C) || -- (state->m_operation_mode == OM_DVBT)) -- select_pos_image = true; -+ if (isDTV) { -+ if ((state->m_OperationMode == OM_QAM_ITU_A) || -+ (state->m_OperationMode == OM_QAM_ITU_C) || -+ (state->m_OperationMode == OM_DVBT)) -+ selectPosImage = true; - else -- select_pos_image = false; -+ selectPosImage = false; - } -- if (tuner_mirror) -+ if (tunerMirror) - /* tuner doesn't mirror */ -- if_freq_actual = intermediate_freqk_hz + -- rf_freq_residual + fm_frequency_shift; -+ ifFreqActual = intermediateFreqkHz + -+ rfFreqResidual + fmFrequencyShift; - else - /* tuner mirrors */ -- if_freq_actual = intermediate_freqk_hz - -- rf_freq_residual - fm_frequency_shift; -- if (if_freq_actual > sampling_frequency / 2) { -+ ifFreqActual = intermediateFreqkHz - -+ rfFreqResidual - fmFrequencyShift; -+ if (ifFreqActual > samplingFrequency / 2) { - /* adc mirrors */ -- adc_freq = sampling_frequency - if_freq_actual; -- adc_flip = true; -+ adcFreq = samplingFrequency - ifFreqActual; -+ adcFlip = true; - } else { - /* adc doesn't mirror */ -- adc_freq = if_freq_actual; -- adc_flip = false; -+ adcFreq = ifFreqActual; -+ adcFlip = false; - } - -- frequency_shift = adc_freq; -- image_to_select = state->m_rfmirror ^ tuner_mirror ^ -- adc_flip ^ select_pos_image; -- state->m_iqm_fs_rate_ofs = -- Frac28a((frequency_shift), sampling_frequency); -+ frequencyShift = adcFreq; -+ imageToSelect = state->m_rfmirror ^ tunerMirror ^ -+ adcFlip ^ selectPosImage; -+ state->m_IqmFsRateOfs = -+ Frac28a((frequencyShift), samplingFrequency); - -- if (image_to_select) -- state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1; -+ if (imageToSelect) -+ state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1; - - /* Program frequency shifter with tuner offset compensation */ -- /* frequency_shift += tuner_freq_offset; TODO */ -+ /* frequencyShift += tunerFreqOffset; TODO */ - status = write32(state, IQM_FS_RATE_OFS_LO__A, -- state->m_iqm_fs_rate_ofs); -+ state->m_IqmFsRateOfs); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int init_agc(struct drxk_state *state, bool is_dtv) -+static int InitAGC(struct drxk_state *state, bool isDTV) - { -- u16 ingain_tgt = 0; -- u16 ingain_tgt_min = 0; -- u16 ingain_tgt_max = 0; -- u16 clp_cyclen = 0; -- u16 clp_sum_min = 0; -- u16 clp_dir_to = 0; -- u16 sns_sum_min = 0; -- u16 sns_sum_max = 0; -- u16 clp_sum_max = 0; -- u16 sns_dir_to = 0; -- u16 ki_innergain_min = 0; -- u16 if_iaccu_hi_tgt = 0; -- u16 if_iaccu_hi_tgt_min = 0; -- u16 if_iaccu_hi_tgt_max = 0; -+ u16 ingainTgt = 0; -+ u16 ingainTgtMin = 0; -+ u16 ingainTgtMax = 0; -+ u16 clpCyclen = 0; -+ u16 clpSumMin = 0; -+ u16 clpDirTo = 0; -+ u16 snsSumMin = 0; -+ u16 snsSumMax = 0; -+ u16 clpSumMax = 0; -+ u16 snsDirTo = 0; -+ u16 kiInnergainMin = 0; -+ u16 ifIaccuHiTgt = 0; -+ u16 ifIaccuHiTgtMin = 0; -+ u16 ifIaccuHiTgtMax = 0; - u16 data = 0; -- u16 fast_clp_ctrl_delay = 0; -- u16 clp_ctrl_mode = 0; -+ u16 fastClpCtrlDelay = 0; -+ u16 clpCtrlMode = 0; - int status = 0; - - dprintk(1, "\n"); - - /* Common settings */ -- sns_sum_max = 1023; -- if_iaccu_hi_tgt_min = 2047; -- clp_cyclen = 500; -- clp_sum_max = 1023; -+ snsSumMax = 1023; -+ ifIaccuHiTgtMin = 2047; -+ clpCyclen = 500; -+ clpSumMax = 1023; - - /* AGCInit() not available for DVBT; init done in microcode */ -- if (!is_qam(state)) { -- pr_err("%s: mode %d is not DVB-C\n", -- __func__, state->m_operation_mode); -+ if (!IsQAM(state)) { -+ printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode); - return -EINVAL; - } - - /* FIXME: Analog TV AGC require different settings */ - - /* Standard specific settings */ -- clp_sum_min = 8; -- clp_dir_to = (u16) -9; -- clp_ctrl_mode = 0; -- sns_sum_min = 8; -- sns_dir_to = (u16) -9; -- ki_innergain_min = (u16) -1030; -- if_iaccu_hi_tgt_max = 0x2380; -- if_iaccu_hi_tgt = 0x2380; -- ingain_tgt_min = 0x0511; -- ingain_tgt = 0x0511; -- ingain_tgt_max = 5119; -- fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay; -+ clpSumMin = 8; -+ clpDirTo = (u16) -9; -+ clpCtrlMode = 0; -+ snsSumMin = 8; -+ snsDirTo = (u16) -9; -+ kiInnergainMin = (u16) -1030; -+ ifIaccuHiTgtMax = 0x2380; -+ ifIaccuHiTgt = 0x2380; -+ ingainTgtMin = 0x0511; -+ ingainTgt = 0x0511; -+ ingainTgtMax = 5119; -+ fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay; - -- status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, -- fast_clp_ctrl_delay); -+ status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay); - if (status < 0) - goto error; - -- status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode); -+ status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt); -+ status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min); -+ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); -+ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, -- if_iaccu_hi_tgt_min); -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, -- if_iaccu_hi_tgt_max); -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax); - if (status < 0) - goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); -@@ -3096,22 +3155,20 @@ static int init_agc(struct drxk_state *state, bool is_dtv) - status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max); -+ status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max); -+ status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax); - if (status < 0) - goto error; - -- status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, -- ki_innergain_min); -+ status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, -- if_iaccu_hi_tgt); -+ status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); -+ status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen); - if (status < 0) - goto error; - -@@ -3128,16 +3185,16 @@ static int init_agc(struct drxk_state *state, bool is_dtv) - status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min); -+ status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min); -+ status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to); -+ status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to); -+ status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo); - if (status < 0) - goto error; - status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff); -@@ -3197,39 +3254,38 @@ static int init_agc(struct drxk_state *state, bool is_dtv) - status = write16(state, SCU_RAM_AGC_KI__A, data); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) -+static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr) - { - int status; - - dprintk(1, "\n"); -- if (packet_err == NULL) -+ if (packetErr == NULL) - status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); - else -- status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, -- packet_err); -+ status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int dvbt_sc_command(struct drxk_state *state, -+static int DVBTScCommand(struct drxk_state *state, - u16 cmd, u16 subcmd, - u16 param0, u16 param1, u16 param2, - u16 param3, u16 param4) - { -- u16 cur_cmd = 0; -- u16 err_code = 0; -- u16 retry_cnt = 0; -- u16 sc_exec = 0; -+ u16 curCmd = 0; -+ u16 errCode = 0; -+ u16 retryCnt = 0; -+ u16 scExec = 0; - int status; - - dprintk(1, "\n"); -- status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec); -- if (sc_exec != 1) { -+ status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec); -+ if (scExec != 1) { - /* SC is not running */ - status = -EINVAL; - } -@@ -3237,13 +3293,13 @@ static int dvbt_sc_command(struct drxk_state *state, - goto error; - - /* Wait until sc is ready to receive command */ -- retry_cnt = 0; -+ retryCnt = 0; - do { -- usleep_range(1000, 2000); -- status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); -- retry_cnt++; -- } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); -- if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) -+ msleep(1); -+ status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); -+ retryCnt++; -+ } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); -+ if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) - goto error; - - /* Write sub-command */ -@@ -3289,25 +3345,25 @@ static int dvbt_sc_command(struct drxk_state *state, - goto error; - - /* Wait until sc is ready processing command */ -- retry_cnt = 0; -+ retryCnt = 0; - do { -- usleep_range(1000, 2000); -- status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); -- retry_cnt++; -- } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); -- if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) -+ msleep(1); -+ status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); -+ retryCnt++; -+ } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); -+ if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) - goto error; - - /* Check for illegal cmd */ -- status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code); -- if (err_code == 0xFFFF) { -+ status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode); -+ if (errCode == 0xFFFF) { - /* illegal command */ - status = -EINVAL; - } - if (status < 0) - goto error; - -- /* Retrieve results parameters from SC */ -+ /* Retreive results parameters from SC */ - switch (cmd) { - /* All commands yielding 5 results */ - /* All commands yielding 4 results */ -@@ -3332,44 +3388,44 @@ static int dvbt_sc_command(struct drxk_state *state, - } /* switch (cmd->cmd) */ - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int power_up_dvbt(struct drxk_state *state) -+static int PowerUpDVBT(struct drxk_state *state) - { -- enum drx_power_mode power_mode = DRX_POWER_UP; -+ enum DRXPowerMode powerMode = DRX_POWER_UP; - int status; - - dprintk(1, "\n"); -- status = ctrl_power_mode(state, &power_mode); -+ status = CtrlPowerMode(state, &powerMode); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) -+static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) - { - int status; - - dprintk(1, "\n"); -- if (*enabled) -+ if (*enabled == true) - status = write16(state, IQM_CF_BYPASSDET__A, 0); - else - status = write16(state, IQM_CF_BYPASSDET__A, 1); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - - #define DEFAULT_FR_THRES_8K 4000 --static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) -+static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) - { - - int status; - - dprintk(1, "\n"); -- if (*enabled) { -+ if (*enabled == true) { - /* write mask to 1 */ - status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, - DEFAULT_FR_THRES_8K); -@@ -3378,13 +3434,13 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) - status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0); - } - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, -- struct drxk_cfg_dvbt_echo_thres_t *echo_thres) -+static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, -+ struct DRXKCfgDvbtEchoThres_t *echoThres) - { - u16 data = 0; - int status; -@@ -3394,16 +3450,16 @@ static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, - if (status < 0) - goto error; - -- switch (echo_thres->fft_mode) { -+ switch (echoThres->fftMode) { - case DRX_FFTMODE_2K: - data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M; -- data |= ((echo_thres->threshold << -+ data |= ((echoThres->threshold << - OFDM_SC_RA_RAM_ECHO_THRES_2K__B) - & (OFDM_SC_RA_RAM_ECHO_THRES_2K__M)); - break; - case DRX_FFTMODE_8K: - data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M; -- data |= ((echo_thres->threshold << -+ data |= ((echoThres->threshold << - OFDM_SC_RA_RAM_ECHO_THRES_8K__B) - & (OFDM_SC_RA_RAM_ECHO_THRES_8K__M)); - break; -@@ -3414,12 +3470,12 @@ static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, - status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, -- enum drxk_cfg_dvbt_sqi_speed *speed) -+static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, -+ enum DRXKCfgDvbtSqiSpeed *speed) - { - int status = -EINVAL; - -@@ -3437,7 +3493,7 @@ static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, - (u16) *speed); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -3451,33 +3507,32 @@ error: - * Called in DVBTSetStandard - * - */ --static int dvbt_activate_presets(struct drxk_state *state) -+static int DVBTActivatePresets(struct drxk_state *state) - { - int status; - bool setincenable = false; - bool setfrenable = true; - -- struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K }; -- struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K }; -+ struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K }; -+ struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K }; - - dprintk(1, "\n"); -- status = dvbt_ctrl_set_inc_enable(state, &setincenable); -+ status = DVBTCtrlSetIncEnable(state, &setincenable); - if (status < 0) - goto error; -- status = dvbt_ctrl_set_fr_enable(state, &setfrenable); -+ status = DVBTCtrlSetFrEnable(state, &setfrenable); - if (status < 0) - goto error; -- status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k); -+ status = DVBTCtrlSetEchoThreshold(state, &echoThres2k); - if (status < 0) - goto error; -- status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k); -+ status = DVBTCtrlSetEchoThreshold(state, &echoThres8k); - if (status < 0) - goto error; -- status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, -- state->m_dvbt_if_agc_cfg.ingain_tgt_max); -+ status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -3491,30 +3546,25 @@ error: - * For ROM code channel filter taps are loaded from the bootloader. For microcode - * the DVB-T taps from the drxk_filters.h are used. - */ --static int set_dvbt_standard(struct drxk_state *state, -- enum operation_mode o_mode) -+static int SetDVBTStandard(struct drxk_state *state, -+ enum OperationMode oMode) - { -- u16 cmd_result = 0; -+ u16 cmdResult = 0; - u16 data = 0; - int status; - - dprintk(1, "\n"); - -- power_up_dvbt(state); -+ PowerUpDVBT(state); - /* added antenna switch */ -- switch_antenna_to_dvbt(state); -+ SwitchAntennaToDVBT(state); - /* send OFDM reset command */ -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - - /* send OFDM setenv command */ -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - -@@ -3546,7 +3596,7 @@ static int set_dvbt_standard(struct drxk_state *state, - status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); - if (status < 0) - goto error; -- status = set_iqm_af(state, true); -+ status = SetIqmAf(state, true); - if (status < 0) - goto error; - -@@ -3568,7 +3618,7 @@ static int set_dvbt_standard(struct drxk_state *state, - status = write16(state, IQM_RC_STRETCH__A, 16); - if (status < 0) - goto error; -- status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ -+ status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ - if (status < 0) - goto error; - status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */ -@@ -3589,8 +3639,7 @@ static int set_dvbt_standard(struct drxk_state *state, - if (status < 0) - goto error; - -- status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, -- DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); -+ status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); - if (status < 0) - goto error; - -@@ -3609,10 +3658,10 @@ static int set_dvbt_standard(struct drxk_state *state, - goto error; - - /* IQM will not be reset from here, sync ADC and update/init AGC */ -- status = adc_synchronization(state); -+ status = ADCSynchronization(state); - if (status < 0) - goto error; -- status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg); -+ status = SetPreSaw(state, &state->m_dvbtPreSawCfg); - if (status < 0) - goto error; - -@@ -3621,10 +3670,10 @@ static int set_dvbt_standard(struct drxk_state *state, - if (status < 0) - goto error; - -- status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true); -+ status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true); - if (status < 0) - goto error; -- status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true); -+ status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true); - if (status < 0) - goto error; - -@@ -3642,10 +3691,9 @@ static int set_dvbt_standard(struct drxk_state *state, - if (status < 0) - goto error; - -- if (!state->m_drxk_a3_rom_code) { -- /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */ -- status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, -- state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); -+ if (!state->m_DRXK_A3_ROM_CODE) { -+ /* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay */ -+ status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay); - if (status < 0) - goto error; - } -@@ -3680,43 +3728,41 @@ static int set_dvbt_standard(struct drxk_state *state, - goto error; - - /* Setup MPEG bus */ -- status = mpegts_dto_setup(state, OM_DVBT); -+ status = MPEGTSDtoSetup(state, OM_DVBT); - if (status < 0) - goto error; - /* Set DVBT Presets */ -- status = dvbt_activate_presets(state); -+ status = DVBTActivatePresets(state); - if (status < 0) - goto error; - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - - /*============================================================================*/ - /** --* \brief start dvbt demodulating for channel. -+* \brief Start dvbt demodulating for channel. - * \param demod instance of demodulator. - * \return DRXStatus_t. - */ --static int dvbt_start(struct drxk_state *state) -+static int DVBTStart(struct drxk_state *state) - { - u16 param1; - int status; -- /* drxk_ofdm_sc_cmd_t scCmd; */ -+ /* DRXKOfdmScCmd_t scCmd; */ - - dprintk(1, "\n"); -- /* start correct processes to get in lock */ -+ /* Start correct processes to get in lock */ - /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */ - param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN; -- status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, -- OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, -- 0, 0, 0); -+ status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); - if (status < 0) - goto error; -- /* start FEC OC */ -- status = mpegts_start(state); -+ /* Start FEC OC */ -+ status = MPEGTSStart(state); - if (status < 0) - goto error; - status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); -@@ -3724,7 +3770,7 @@ static int dvbt_start(struct drxk_state *state) - goto error; - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -3737,23 +3783,20 @@ error: - * \return DRXStatus_t. - * // original DVBTSetChannel() - */ --static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, -- s32 tuner_freq_offset) -+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, -+ s32 tunerFreqOffset) - { -- u16 cmd_result = 0; -- u16 transmission_params = 0; -- u16 operation_mode = 0; -- u32 iqm_rc_rate_ofs = 0; -+ u16 cmdResult = 0; -+ u16 transmissionParams = 0; -+ u16 operationMode = 0; -+ u32 iqmRcRateOfs = 0; - u32 bandwidth = 0; - u16 param1; - int status; - -- dprintk(1, "IF =%d, TFO = %d\n", -- intermediate_freqk_hz, tuner_freq_offset); -+ dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset); - -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - -@@ -3776,19 +3819,19 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - if (status < 0) - goto error; - -- /*== Write channel settings to device ================================*/ -+ /*== Write channel settings to device =====================================*/ - - /* mode */ - switch (state->props.transmission_mode) { - case TRANSMISSION_MODE_AUTO: - default: -- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; -+ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; - /* fall through , try first guess DRX_FFTMODE_8K */ - case TRANSMISSION_MODE_8K: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; - break; - case TRANSMISSION_MODE_2K: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; - break; - } - -@@ -3796,19 +3839,19 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - switch (state->props.guard_interval) { - default: - case GUARD_INTERVAL_AUTO: -- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; -+ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; - /* fall through , try first guess DRX_GUARD_1DIV4 */ - case GUARD_INTERVAL_1_4: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; - break; - case GUARD_INTERVAL_1_32: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; - break; - case GUARD_INTERVAL_1_16: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; - break; - case GUARD_INTERVAL_1_8: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; - break; - } - -@@ -3817,18 +3860,18 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - case HIERARCHY_AUTO: - case HIERARCHY_NONE: - default: -- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; -+ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; - /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ -- /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ -+ /* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ - /* break; */ - case HIERARCHY_1: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; - break; - case HIERARCHY_2: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; - break; - case HIERARCHY_4: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; - break; - } - -@@ -3837,30 +3880,30 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - switch (state->props.modulation) { - case QAM_AUTO: - default: -- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; -+ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; - /* fall through , try first guess DRX_CONSTELLATION_QAM64 */ - case QAM_64: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; - break; - case QPSK: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; - break; - case QAM_16: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; - break; - } - #if 0 -- /* No hierarchical channels support in BDA */ -+ /* No hierachical channels support in BDA */ - /* Priority (only for hierarchical channels) */ - switch (channel->priority) { - case DRX_PRIORITY_LOW: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; -- WR16(dev_addr, OFDM_EC_SB_PRIOR__A, -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; -+ WR16(devAddr, OFDM_EC_SB_PRIOR__A, - OFDM_EC_SB_PRIOR_LO); - break; - case DRX_PRIORITY_HIGH: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; -- WR16(dev_addr, OFDM_EC_SB_PRIOR__A, -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; -+ WR16(devAddr, OFDM_EC_SB_PRIOR__A, - OFDM_EC_SB_PRIOR_HI)); - break; - case DRX_PRIORITY_UNKNOWN: /* fall through */ -@@ -3870,7 +3913,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - } - #else - /* Set Priorty high */ -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; - status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI); - if (status < 0) - goto error; -@@ -3880,111 +3923,90 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - switch (state->props.code_rate_HP) { - case FEC_AUTO: - default: -- operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; -+ operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; - /* fall through , try first guess DRX_CODERATE_2DIV3 */ - case FEC_2_3: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; - break; - case FEC_1_2: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; - break; - case FEC_3_4: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; - break; - case FEC_5_6: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; - break; - case FEC_7_8: -- transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; -+ transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; - break; - } - -- /* -- * SAW filter selection: normaly not necesarry, but if wanted -- * the application can select a SAW filter via the driver by -- * using UIOs -- */ -- -+ /* SAW filter selection: normaly not necesarry, but if wanted -+ the application can select a SAW filter via the driver by using UIOs */ - /* First determine real bandwidth (Hz) */ - /* Also set delay for impulse noise cruncher */ -- /* -- * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is -- * changed by SC for fix for some 8K,1/8 guard but is restored by -- * InitEC and ResetEC functions -- */ -+ /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed -+ by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC -+ functions */ - switch (state->props.bandwidth_hz) { - case 0: - state->props.bandwidth_hz = 8000000; - /* fall though */ - case 8000000: - bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; -- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, -- 3052); -+ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052); - if (status < 0) - goto error; - /* cochannel protection for PAL 8 MHz */ -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, -- 7); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, -- 7); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, -- 7); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, -- 1); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); - if (status < 0) - goto error; - break; - case 7000000: - bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ; -- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, -- 3491); -+ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491); - if (status < 0) - goto error; - /* cochannel protection for PAL 7 MHz */ -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, -- 8); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, -- 8); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, -- 4); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, -- 1); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); - if (status < 0) - goto error; - break; - case 6000000: - bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ; -- status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, -- 4073); -+ status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073); - if (status < 0) - goto error; - /* cochannel protection for NTSC 6 MHz */ -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, -- 19); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, -- 19); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, -- 14); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14); - if (status < 0) - goto error; -- status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, -- 1); -+ status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); - if (status < 0) - goto error; - break; -@@ -3993,50 +4015,46 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - goto error; - } - -- if (iqm_rc_rate_ofs == 0) { -+ if (iqmRcRateOfs == 0) { - /* Now compute IQM_RC_RATE_OFS - (((SysFreq/BandWidth)/2)/2) -1) * 2^23) - => - ((SysFreq / BandWidth) * (2^21)) - (2^23) - */ - /* (SysFreq / BandWidth) * (2^28) */ -- /* -- * assert (MAX(sysClk)/MIN(bandwidth) < 16) -- * => assert(MAX(sysClk) < 16*MIN(bandwidth)) -- * => assert(109714272 > 48000000) = true -- * so Frac 28 can be used -- */ -- iqm_rc_rate_ofs = Frac28a((u32) -- ((state->m_sys_clock_freq * -+ /* assert (MAX(sysClk)/MIN(bandwidth) < 16) -+ => assert(MAX(sysClk) < 16*MIN(bandwidth)) -+ => assert(109714272 > 48000000) = true so Frac 28 can be used */ -+ iqmRcRateOfs = Frac28a((u32) -+ ((state->m_sysClockFreq * - 1000) / 3), bandwidth); -- /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ -- if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40) -- iqm_rc_rate_ofs += 0x80L; -- iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7; -+ /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ -+ if ((iqmRcRateOfs & 0x7fL) >= 0x40) -+ iqmRcRateOfs += 0x80L; -+ iqmRcRateOfs = iqmRcRateOfs >> 7; - /* ((SysFreq / BandWidth) * (2^21)) - (2^23) */ -- iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23); -+ iqmRcRateOfs = iqmRcRateOfs - (1 << 23); - } - -- iqm_rc_rate_ofs &= -+ iqmRcRateOfs &= - ((((u32) IQM_RC_RATE_OFS_HI__M) << - IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M); -- status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs); -+ status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs); - if (status < 0) - goto error; - - /* Bandwidth setting done */ - - #if 0 -- status = dvbt_set_frequency_shift(demod, channel, tuner_offset); -+ status = DVBTSetFrequencyShift(demod, channel, tunerOffset); - if (status < 0) - goto error; - #endif -- status = set_frequency_shifter(state, intermediate_freqk_hz, -- tuner_freq_offset, true); -+ status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); - if (status < 0) - goto error; - -- /*== start SC, write channel settings to SC ==========================*/ -+ /*== Start SC, write channel settings to SC ===============================*/ - - /* Activate SCU to enable SCU commands */ - status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); -@@ -4052,9 +4070,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - goto error; - - -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM -- | SCU_RAM_COMMAND_CMD_DEMOD_START, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - -@@ -4064,16 +4080,16 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, - OFDM_SC_RA_RAM_OP_AUTO_CONST__M | - OFDM_SC_RA_RAM_OP_AUTO_HIER__M | - OFDM_SC_RA_RAM_OP_AUTO_RATE__M); -- status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, -- 0, transmission_params, param1, 0, 0, 0); -+ status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, -+ 0, transmissionParams, param1, 0, 0, 0); - if (status < 0) - goto error; - -- if (!state->m_drxk_a3_rom_code) -- status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed); -+ if (!state->m_DRXK_A3_ROM_CODE) -+ status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } -@@ -4082,13 +4098,13 @@ error: - /*============================================================================*/ - - /** --* \brief Retrieve lock status . -+* \brief Retreive lock status . - * \param demod Pointer to demodulator instance. - * \param lockStat Pointer to lock status structure. - * \return DRXStatus_t. - * - */ --static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) -+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) - { - int status; - const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M | -@@ -4096,58 +4112,58 @@ static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) - const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M); - const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M; - -- u16 sc_ra_ram_lock = 0; -- u16 sc_comm_exec = 0; -+ u16 ScRaRamLock = 0; -+ u16 ScCommExec = 0; - - dprintk(1, "\n"); - -- *p_lock_status = NOT_LOCKED; -+ *pLockStatus = NOT_LOCKED; - /* driver 0.9.0 */ - /* Check if SC is running */ -- status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec); -+ status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec); - if (status < 0) - goto end; -- if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP) -+ if (ScCommExec == OFDM_SC_COMM_EXEC_STOP) - goto end; - -- status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock); -+ status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock); - if (status < 0) - goto end; - -- if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask) -- *p_lock_status = MPEG_LOCK; -- else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask) -- *p_lock_status = FEC_LOCK; -- else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask) -- *p_lock_status = DEMOD_LOCK; -- else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) -- *p_lock_status = NEVER_LOCK; -+ if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) -+ *pLockStatus = MPEG_LOCK; -+ else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) -+ *pLockStatus = FEC_LOCK; -+ else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) -+ *pLockStatus = DEMOD_LOCK; -+ else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) -+ *pLockStatus = NEVER_LOCK; - end: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static int power_up_qam(struct drxk_state *state) -+static int PowerUpQAM(struct drxk_state *state) - { -- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; -+ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; - int status; - - dprintk(1, "\n"); -- status = ctrl_power_mode(state, &power_mode); -+ status = CtrlPowerMode(state, &powerMode); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - - - /** Power Down QAM */ --static int power_down_qam(struct drxk_state *state) -+static int PowerDownQAM(struct drxk_state *state) - { - u16 data = 0; -- u16 cmd_result; -+ u16 cmdResult; - int status = 0; - - dprintk(1, "\n"); -@@ -4163,18 +4179,16 @@ static int power_down_qam(struct drxk_state *state) - status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); - if (status < 0) - goto error; -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_STOP, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - } - /* powerdown AFE */ -- status = set_iqm_af(state, false); -+ status = SetIqmAf(state, false); - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } -@@ -4192,20 +4206,20 @@ error: - * The implementation does not check this. - * - */ --static int set_qam_measurement(struct drxk_state *state, -- enum e_drxk_constellation modulation, -- u32 symbol_rate) -+static int SetQAMMeasurement(struct drxk_state *state, -+ enum EDrxkConstellation modulation, -+ u32 symbolRate) - { -- u32 fec_bits_desired = 0; /* BER accounting period */ -- u32 fec_rs_period_total = 0; /* Total period */ -- u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ -- u16 fec_rs_period = 0; /* Value for corresponding I2C register */ -+ u32 fecBitsDesired = 0; /* BER accounting period */ -+ u32 fecRsPeriodTotal = 0; /* Total period */ -+ u16 fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ -+ u16 fecRsPeriod = 0; /* Value for corresponding I2C register */ - int status = 0; - - dprintk(1, "\n"); - -- fec_rs_prescale = 1; -- /* fec_bits_desired = symbol_rate [kHz] * -+ fecRsPrescale = 1; -+ /* fecBitsDesired = symbolRate [kHz] * - FrameLenght [ms] * - (modulation + 1) * - SyncLoss (== 1) * -@@ -4213,19 +4227,19 @@ static int set_qam_measurement(struct drxk_state *state, - */ - switch (modulation) { - case DRX_CONSTELLATION_QAM16: -- fec_bits_desired = 4 * symbol_rate; -+ fecBitsDesired = 4 * symbolRate; - break; - case DRX_CONSTELLATION_QAM32: -- fec_bits_desired = 5 * symbol_rate; -+ fecBitsDesired = 5 * symbolRate; - break; - case DRX_CONSTELLATION_QAM64: -- fec_bits_desired = 6 * symbol_rate; -+ fecBitsDesired = 6 * symbolRate; - break; - case DRX_CONSTELLATION_QAM128: -- fec_bits_desired = 7 * symbol_rate; -+ fecBitsDesired = 7 * symbolRate; - break; - case DRX_CONSTELLATION_QAM256: -- fec_bits_desired = 8 * symbol_rate; -+ fecBitsDesired = 8 * symbolRate; - break; - default: - status = -EINVAL; -@@ -4233,41 +4247,40 @@ static int set_qam_measurement(struct drxk_state *state, - if (status < 0) - goto error; - -- fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ -- fec_bits_desired *= 500; /* meas. period [ms] */ -+ fecBitsDesired /= 1000; /* symbolRate [Hz] -> symbolRate [kHz] */ -+ fecBitsDesired *= 500; /* meas. period [ms] */ - - /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */ -- /* fec_rs_period_total = fec_bits_desired / 1632 */ -- fec_rs_period_total = (fec_bits_desired / 1632UL) + 1; /* roughly ceil */ -+ /* fecRsPeriodTotal = fecBitsDesired / 1632 */ -+ fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1; /* roughly ceil */ - -- /* fec_rs_period_total = fec_rs_prescale * fec_rs_period */ -- fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16); -- if (fec_rs_prescale == 0) { -+ /* fecRsPeriodTotal = fecRsPrescale * fecRsPeriod */ -+ fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16); -+ if (fecRsPrescale == 0) { - /* Divide by zero (though impossible) */ - status = -EINVAL; - if (status < 0) - goto error; - } -- fec_rs_period = -- ((u16) fec_rs_period_total + -- (fec_rs_prescale >> 1)) / fec_rs_prescale; -+ fecRsPeriod = -+ ((u16) fecRsPeriodTotal + -+ (fecRsPrescale >> 1)) / fecRsPrescale; - - /* write corresponding registers */ -- status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period); -+ status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod); - if (status < 0) - goto error; -- status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, -- fec_rs_prescale); -+ status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale); - if (status < 0) - goto error; -- status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); -+ status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int set_qam16(struct drxk_state *state) -+static int SetQAM16(struct drxk_state *state) - { - int status = 0; - -@@ -4323,8 +4336,7 @@ static int set_qam16(struct drxk_state *state) - goto error; - - /* QAM Slicer Settings */ -- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, -- DRXK_QAM_SL_SIG_POWER_QAM16); -+ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16); - if (status < 0) - goto error; - -@@ -4450,7 +4462,7 @@ static int set_qam16(struct drxk_state *state) - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -4461,7 +4473,7 @@ error: - * \param demod instance of demod. - * \return DRXStatus_t. - */ --static int set_qam32(struct drxk_state *state) -+static int SetQAM32(struct drxk_state *state) - { - int status = 0; - -@@ -4520,8 +4532,7 @@ static int set_qam32(struct drxk_state *state) - - /* QAM Slicer Settings */ - -- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, -- DRXK_QAM_SL_SIG_POWER_QAM32); -+ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32); - if (status < 0) - goto error; - -@@ -4646,7 +4657,7 @@ static int set_qam32(struct drxk_state *state) - status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -4657,7 +4668,7 @@ error: - * \param demod instance of demod. - * \return DRXStatus_t. - */ --static int set_qam64(struct drxk_state *state) -+static int SetQAM64(struct drxk_state *state) - { - int status = 0; - -@@ -4714,8 +4725,7 @@ static int set_qam64(struct drxk_state *state) - goto error; - - /* QAM Slicer Settings */ -- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, -- DRXK_QAM_SL_SIG_POWER_QAM64); -+ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64); - if (status < 0) - goto error; - -@@ -4840,7 +4850,7 @@ static int set_qam64(struct drxk_state *state) - status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } -@@ -4852,7 +4862,7 @@ error: - * \param demod: instance of demod. - * \return DRXStatus_t. - */ --static int set_qam128(struct drxk_state *state) -+static int SetQAM128(struct drxk_state *state) - { - int status = 0; - -@@ -4911,8 +4921,7 @@ static int set_qam128(struct drxk_state *state) - - /* QAM Slicer Settings */ - -- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, -- DRXK_QAM_SL_SIG_POWER_QAM128); -+ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128); - if (status < 0) - goto error; - -@@ -5037,7 +5046,7 @@ static int set_qam128(struct drxk_state *state) - status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } -@@ -5049,7 +5058,7 @@ error: - * \param demod: instance of demod. - * \return DRXStatus_t. - */ --static int set_qam256(struct drxk_state *state) -+static int SetQAM256(struct drxk_state *state) - { - int status = 0; - -@@ -5107,8 +5116,7 @@ static int set_qam256(struct drxk_state *state) - - /* QAM Slicer Settings */ - -- status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, -- DRXK_QAM_SL_SIG_POWER_QAM256); -+ status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256); - if (status < 0) - goto error; - -@@ -5233,7 +5241,7 @@ static int set_qam256(struct drxk_state *state) - status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -5245,10 +5253,10 @@ error: - * \param channel: pointer to channel data. - * \return DRXStatus_t. - */ --static int qam_reset_qam(struct drxk_state *state) -+static int QAMResetQAM(struct drxk_state *state) - { - int status; -- u16 cmd_result; -+ u16 cmdResult; - - dprintk(1, "\n"); - /* Stop QAM comstate->m_exec */ -@@ -5256,12 +5264,10 @@ static int qam_reset_qam(struct drxk_state *state) - if (status < 0) - goto error; - -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_RESET, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -5273,18 +5279,18 @@ error: - * \param channel: pointer to channel data. - * \return DRXStatus_t. - */ --static int qam_set_symbolrate(struct drxk_state *state) -+static int QAMSetSymbolrate(struct drxk_state *state) - { -- u32 adc_frequency = 0; -- u32 symb_freq = 0; -- u32 iqm_rc_rate = 0; -+ u32 adcFrequency = 0; -+ u32 symbFreq = 0; -+ u32 iqmRcRate = 0; - u16 ratesel = 0; -- u32 lc_symb_rate = 0; -+ u32 lcSymbRate = 0; - int status; - - dprintk(1, "\n"); - /* Select & calculate correct IQM rate */ -- adc_frequency = (state->m_sys_clock_freq * 1000) / 3; -+ adcFrequency = (state->m_sysClockFreq * 1000) / 3; - ratesel = 0; - /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */ - if (state->props.symbol_rate <= 1188750) -@@ -5300,38 +5306,38 @@ static int qam_set_symbolrate(struct drxk_state *state) - /* - IqmRcRate = ((Fadc / (symbolrate * (4<props.symbol_rate * (1 << ratesel); -- if (symb_freq == 0) { -+ symbFreq = state->props.symbol_rate * (1 << ratesel); -+ if (symbFreq == 0) { - /* Divide by zero */ - status = -EINVAL; - goto error; - } -- iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) + -- (Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) - -+ iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) + -+ (Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) - - (1 << 23); -- status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate); -+ status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate); - if (status < 0) - goto error; -- state->m_iqm_rc_rate = iqm_rc_rate; -+ state->m_iqmRcRate = iqmRcRate; - /* -- LcSymbFreq = round (.125 * symbolrate / adc_freq * (1<<15)) -+ LcSymbFreq = round (.125 * symbolrate / adcFreq * (1<<15)) - */ -- symb_freq = state->props.symbol_rate; -- if (adc_frequency == 0) { -+ symbFreq = state->props.symbol_rate; -+ if (adcFrequency == 0) { - /* Divide by zero */ - status = -EINVAL; - goto error; - } -- lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) + -- (Frac28a((symb_freq % adc_frequency), adc_frequency) >> -+ lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) + -+ (Frac28a((symbFreq % adcFrequency), adcFrequency) >> - 16); -- if (lc_symb_rate > 511) -- lc_symb_rate = 511; -- status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate); -+ if (lcSymbRate > 511) -+ lcSymbRate = 511; -+ status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate); - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - -@@ -5344,36 +5350,34 @@ error: - * \return DRXStatus_t. - */ - --static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) -+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) - { - int status; -- u16 result[2] = { 0, 0 }; -+ u16 Result[2] = { 0, 0 }; - - dprintk(1, "\n"); -- *p_lock_status = NOT_LOCKED; -+ *pLockStatus = NOT_LOCKED; - status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | - SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, -- result); -+ Result); - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status); - -- if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { -+ if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { - /* 0x0000 NOT LOCKED */ -- } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { -+ } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { - /* 0x4000 DEMOD LOCKED */ -- *p_lock_status = DEMOD_LOCK; -- } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { -+ *pLockStatus = DEMOD_LOCK; -+ } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { - /* 0x8000 DEMOD + FEC LOCKED (system lock) */ -- *p_lock_status = MPEG_LOCK; -+ *pLockStatus = MPEG_LOCK; - } else { - /* 0xC000 NEVER LOCKED */ - /* (system will never be able to lock to the signal) */ -- /* -- * TODO: check this, intermediate & standard specific lock -- * states are not taken into account here -- */ -- *p_lock_status = NEVER_LOCK; -+ /* TODO: check this, intermediate & standard specific lock states are not -+ taken into account here */ -+ *pLockStatus = NEVER_LOCK; - } - return status; - } -@@ -5385,70 +5389,12 @@ static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) - #define QAM_LOCKRANGE__M 0x10 - #define QAM_LOCKRANGE_NORMAL 0x10 - --static int qam_demodulator_command(struct drxk_state *state, -- int number_of_parameters) -+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, -+ s32 tunerFreqOffset) - { - int status; -- u16 cmd_result; -- u16 set_param_parameters[4] = { 0, 0, 0, 0 }; -- -- set_param_parameters[0] = state->m_constellation; /* modulation */ -- set_param_parameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ -- -- if (number_of_parameters == 2) { -- u16 set_env_parameters[1] = { 0 }; -- -- if (state->m_operation_mode == OM_QAM_ITU_C) -- set_env_parameters[0] = QAM_TOP_ANNEX_C; -- else -- set_env_parameters[0] = QAM_TOP_ANNEX_A; -- -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, -- 1, set_env_parameters, 1, &cmd_result); -- if (status < 0) -- goto error; -- -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, -- number_of_parameters, set_param_parameters, -- 1, &cmd_result); -- } else if (number_of_parameters == 4) { -- if (state->m_operation_mode == OM_QAM_ITU_C) -- set_param_parameters[2] = QAM_TOP_ANNEX_C; -- else -- set_param_parameters[2] = QAM_TOP_ANNEX_A; -- -- set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON); -- /* Env parameters */ -- /* check for LOCKRANGE Extented */ -- /* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */ -- -- status = scu_command(state, -- SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, -- number_of_parameters, set_param_parameters, -- 1, &cmd_result); -- } else { -- pr_warn("Unknown QAM demodulator parameter count %d\n", -- number_of_parameters); -- status = -EINVAL; -- } -- --error: -- if (status < 0) -- pr_warn("Warning %d on %s\n", status, __func__); -- return status; --} -- --static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, -- s32 tuner_freq_offset) --{ -- int status; -- u16 cmd_result; -- int qam_demod_param_count = state->qam_demod_parameter_count; -+ u16 setParamParameters[4] = { 0, 0, 0, 0 }; -+ u16 cmdResult; - - dprintk(1, "\n"); - /* -@@ -5463,7 +5409,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP); - if (status < 0) - goto error; -- status = qam_reset_qam(state); -+ status = QAMResetQAM(state); - if (status < 0) - goto error; - -@@ -5472,27 +5418,27 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - * -set params; resets IQM,QAM,FEC HW; initializes some - * SCU variables - */ -- status = qam_set_symbolrate(state); -+ status = QAMSetSymbolrate(state); - if (status < 0) - goto error; - - /* Set params */ - switch (state->props.modulation) { - case QAM_256: -- state->m_constellation = DRX_CONSTELLATION_QAM256; -+ state->m_Constellation = DRX_CONSTELLATION_QAM256; - break; - case QAM_AUTO: - case QAM_64: -- state->m_constellation = DRX_CONSTELLATION_QAM64; -+ state->m_Constellation = DRX_CONSTELLATION_QAM64; - break; - case QAM_16: -- state->m_constellation = DRX_CONSTELLATION_QAM16; -+ state->m_Constellation = DRX_CONSTELLATION_QAM16; - break; - case QAM_32: -- state->m_constellation = DRX_CONSTELLATION_QAM32; -+ state->m_Constellation = DRX_CONSTELLATION_QAM32; - break; - case QAM_128: -- state->m_constellation = DRX_CONSTELLATION_QAM128; -+ state->m_Constellation = DRX_CONSTELLATION_QAM128; - break; - default: - status = -EINVAL; -@@ -5500,60 +5446,50 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - } - if (status < 0) - goto error; -+ setParamParameters[0] = state->m_Constellation; /* modulation */ -+ setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ -+ if (state->m_OperationMode == OM_QAM_ITU_C) -+ setParamParameters[2] = QAM_TOP_ANNEX_C; -+ else -+ setParamParameters[2] = QAM_TOP_ANNEX_A; -+ setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); -+ /* Env parameters */ -+ /* check for LOCKRANGE Extented */ -+ /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ - -- /* Use the 4-parameter if it's requested or we're probing for -- * the correct command. */ -- if (state->qam_demod_parameter_count == 4 -- || !state->qam_demod_parameter_count) { -- qam_demod_param_count = 4; -- status = qam_demodulator_command(state, qam_demod_param_count); -- } -- -- /* Use the 2-parameter command if it was requested or if we're -- * probing for the correct command and the 4-parameter command -- * failed. */ -- if (state->qam_demod_parameter_count == 2 -- || (!state->qam_demod_parameter_count && status < 0)) { -- qam_demod_param_count = 2; -- status = qam_demodulator_command(state, qam_demod_param_count); -- } -- -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult); - if (status < 0) { -- dprintk(1, "Could not set demodulator parameters.\n"); -- dprintk(1, -- "Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n", -- state->qam_demod_parameter_count, -- state->microcode_name); -- goto error; -- } else if (!state->qam_demod_parameter_count) { -- dprintk(1, -- "Auto-probing the QAM command parameters was successful - using %d parameters.\n", -- qam_demod_param_count); -+ /* Fall-back to the simpler call */ -+ if (state->m_OperationMode == OM_QAM_ITU_C) -+ setParamParameters[0] = QAM_TOP_ANNEX_C; -+ else -+ setParamParameters[0] = QAM_TOP_ANNEX_A; -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult); -+ if (status < 0) -+ goto error; - -- /* -- * One of our commands was successful. We don't need to -- * auto-probe anymore, now that we got the correct command. -- */ -- state->qam_demod_parameter_count = qam_demod_param_count; -+ setParamParameters[0] = state->m_Constellation; /* modulation */ -+ setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult); - } -+ if (status < 0) -+ goto error; - - /* - * STEP 3: enable the system in a mode where the ADC provides valid - * signal setup modulation independent registers - */ - #if 0 -- status = set_frequency(channel, tuner_freq_offset)); -+ status = SetFrequency(channel, tunerFreqOffset)); - if (status < 0) - goto error; - #endif -- status = set_frequency_shifter(state, intermediate_freqk_hz, -- tuner_freq_offset, true); -+ status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); - if (status < 0) - goto error; - - /* Setup BER measurement */ -- status = set_qam_measurement(state, state->m_constellation, -- state->props.symbol_rate); -+ status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate); - if (status < 0) - goto error; - -@@ -5626,8 +5562,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - goto error; - - /* Mirroring, QAM-block starting point not inverted */ -- status = write16(state, QAM_SY_SP_INV__A, -- QAM_SY_SP_INV_SPECTRUM_INV_DIS); -+ status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS); - if (status < 0) - goto error; - -@@ -5639,20 +5574,20 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - /* STEP 4: modulation specific setup */ - switch (state->props.modulation) { - case QAM_16: -- status = set_qam16(state); -+ status = SetQAM16(state); - break; - case QAM_32: -- status = set_qam32(state); -+ status = SetQAM32(state); - break; - case QAM_AUTO: - case QAM_64: -- status = set_qam64(state); -+ status = SetQAM64(state); - break; - case QAM_128: -- status = set_qam128(state); -+ status = SetQAM128(state); - break; - case QAM_256: -- status = set_qam256(state); -+ status = SetQAM256(state); - break; - default: - status = -EINVAL; -@@ -5669,12 +5604,12 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - /* Re-configure MPEG output, requires knowledge of channel bitrate */ - /* extAttr->currentChannel.modulation = channel->modulation; */ - /* extAttr->currentChannel.symbolrate = channel->symbolrate; */ -- status = mpegts_dto_setup(state, state->m_operation_mode); -+ status = MPEGTSDtoSetup(state, state->m_OperationMode); - if (status < 0) - goto error; - -- /* start processes */ -- status = mpegts_start(state); -+ /* Start processes */ -+ status = MPEGTSStart(state); - if (status < 0) - goto error; - status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); -@@ -5688,9 +5623,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - goto error; - - /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ -- status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM -- | SCU_RAM_COMMAND_CMD_DEMOD_START, -- 0, NULL, 1, &cmd_result); -+ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); - if (status < 0) - goto error; - -@@ -5699,12 +5632,12 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, - - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int set_qam_standard(struct drxk_state *state, -- enum operation_mode o_mode) -+static int SetQAMStandard(struct drxk_state *state, -+ enum OperationMode oMode) - { - int status; - #ifdef DRXK_QAM_TAPS -@@ -5716,14 +5649,14 @@ static int set_qam_standard(struct drxk_state *state, - dprintk(1, "\n"); - - /* added antenna switch */ -- switch_antenna_to_qam(state); -+ SwitchAntennaToQAM(state); - - /* Ensure correct power-up mode */ -- status = power_up_qam(state); -+ status = PowerUpQAM(state); - if (status < 0) - goto error; - /* Reset QAM block */ -- status = qam_reset_qam(state); -+ status = QAMResetQAM(state); - if (status < 0) - goto error; - -@@ -5738,24 +5671,15 @@ static int set_qam_standard(struct drxk_state *state, - - /* Upload IQM Channel Filter settings by - boot loader from ROM table */ -- switch (o_mode) { -+ switch (oMode) { - case OM_QAM_ITU_A: -- status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, -- DRXK_BLCC_NR_ELEMENTS_TAPS, -- DRXK_BLC_TIMEOUT); -+ status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); - break; - case OM_QAM_ITU_C: -- status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, -- DRXK_BL_ROM_OFFSET_TAPS_ITU_C, -- DRXK_BLDC_NR_ELEMENTS_TAPS, -- DRXK_BLC_TIMEOUT); -+ status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); - if (status < 0) - goto error; -- status = bl_direct_cmd(state, -- IQM_CF_TAP_IM0__A, -- DRXK_BL_ROM_OFFSET_TAPS_ITU_C, -- DRXK_BLDC_NR_ELEMENTS_TAPS, -- DRXK_BLC_TIMEOUT); -+ status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); - break; - default: - status = -EINVAL; -@@ -5763,14 +5687,13 @@ static int set_qam_standard(struct drxk_state *state, - if (status < 0) - goto error; - -- status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B); -+ status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B)); - if (status < 0) - goto error; - status = write16(state, IQM_CF_SYMMETRIC__A, 0); - if (status < 0) - goto error; -- status = write16(state, IQM_CF_MIDTAP__A, -- ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); -+ status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); - if (status < 0) - goto error; - -@@ -5827,7 +5750,7 @@ static int set_qam_standard(struct drxk_state *state, - goto error; - - /* turn on IQMAF. Must be done before setAgc**() */ -- status = set_iqm_af(state, true); -+ status = SetIqmAf(state, true); - if (status < 0) - goto error; - status = write16(state, IQM_AF_START_LOCK__A, 0x01); -@@ -5835,7 +5758,7 @@ static int set_qam_standard(struct drxk_state *state, - goto error; - - /* IQM will not be reset from here, sync ADC and update/init AGC */ -- status = adc_synchronization(state); -+ status = ADCSynchronization(state); - if (status < 0) - goto error; - -@@ -5852,18 +5775,18 @@ static int set_qam_standard(struct drxk_state *state, - /* No more resets of the IQM, current standard correctly set => - now AGCs can be configured. */ - -- status = init_agc(state, true); -+ status = InitAGC(state, true); - if (status < 0) - goto error; -- status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg)); -+ status = SetPreSaw(state, &(state->m_qamPreSawCfg)); - if (status < 0) - goto error; - - /* Configure AGC's */ -- status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true); -+ status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true); - if (status < 0) - goto error; -- status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true); -+ status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true); - if (status < 0) - goto error; - -@@ -5871,19 +5794,18 @@ static int set_qam_standard(struct drxk_state *state, - status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int write_gpio(struct drxk_state *state) -+static int WriteGPIO(struct drxk_state *state) - { - int status; - u16 value = 0; - - dprintk(1, "\n"); - /* stop lock indicator process */ -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; - -@@ -5892,11 +5814,10 @@ static int write_gpio(struct drxk_state *state) - if (status < 0) - goto error; - -- if (state->m_has_sawsw) { -- if (state->uio_mask & 0x0001) { /* UIO-1 */ -+ if (state->m_hasSAWSW) { -+ if (state->UIO_mask & 0x0001) { /* UIO-1 */ - /* write to io pad configuration register - output mode */ -- status = write16(state, SIO_PDR_SMA_TX_CFG__A, -- state->m_gpio_cfg); -+ status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); - if (status < 0) - goto error; - -@@ -5904,7 +5825,7 @@ static int write_gpio(struct drxk_state *state) - status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); - if (status < 0) - goto error; -- if ((state->m_gpio & 0x0001) == 0) -+ if ((state->m_GPIO & 0x0001) == 0) - value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ - else - value |= 0x8000; /* write one to 15th bit - 1st UIO */ -@@ -5913,10 +5834,9 @@ static int write_gpio(struct drxk_state *state) - if (status < 0) - goto error; - } -- if (state->uio_mask & 0x0002) { /* UIO-2 */ -+ if (state->UIO_mask & 0x0002) { /* UIO-2 */ - /* write to io pad configuration register - output mode */ -- status = write16(state, SIO_PDR_SMA_RX_CFG__A, -- state->m_gpio_cfg); -+ status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg); - if (status < 0) - goto error; - -@@ -5924,7 +5844,7 @@ static int write_gpio(struct drxk_state *state) - status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); - if (status < 0) - goto error; -- if ((state->m_gpio & 0x0002) == 0) -+ if ((state->m_GPIO & 0x0002) == 0) - value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ - else - value |= 0x4000; /* write one to 14th bit - 2st UIO */ -@@ -5933,10 +5853,9 @@ static int write_gpio(struct drxk_state *state) - if (status < 0) - goto error; - } -- if (state->uio_mask & 0x0004) { /* UIO-3 */ -+ if (state->UIO_mask & 0x0004) { /* UIO-3 */ - /* write to io pad configuration register - output mode */ -- status = write16(state, SIO_PDR_GPIO_CFG__A, -- state->m_gpio_cfg); -+ status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg); - if (status < 0) - goto error; - -@@ -5944,7 +5863,7 @@ static int write_gpio(struct drxk_state *state) - status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); - if (status < 0) - goto error; -- if ((state->m_gpio & 0x0004) == 0) -+ if ((state->m_GPIO & 0x0004) == 0) - value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ - else - value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ -@@ -5958,11 +5877,11 @@ static int write_gpio(struct drxk_state *state) - status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int switch_antenna_to_qam(struct drxk_state *state) -+static int SwitchAntennaToQAM(struct drxk_state *state) - { - int status = 0; - bool gpio_state; -@@ -5972,22 +5891,22 @@ static int switch_antenna_to_qam(struct drxk_state *state) - if (!state->antenna_gpio) - return 0; - -- gpio_state = state->m_gpio & state->antenna_gpio; -+ gpio_state = state->m_GPIO & state->antenna_gpio; - - if (state->antenna_dvbt ^ gpio_state) { - /* Antenna is on DVB-T mode. Switch */ - if (state->antenna_dvbt) -- state->m_gpio &= ~state->antenna_gpio; -+ state->m_GPIO &= ~state->antenna_gpio; - else -- state->m_gpio |= state->antenna_gpio; -- status = write_gpio(state); -+ state->m_GPIO |= state->antenna_gpio; -+ status = WriteGPIO(state); - } - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - --static int switch_antenna_to_dvbt(struct drxk_state *state) -+static int SwitchAntennaToDVBT(struct drxk_state *state) - { - int status = 0; - bool gpio_state; -@@ -5997,23 +5916,23 @@ static int switch_antenna_to_dvbt(struct drxk_state *state) - if (!state->antenna_gpio) - return 0; - -- gpio_state = state->m_gpio & state->antenna_gpio; -+ gpio_state = state->m_GPIO & state->antenna_gpio; - - if (!(state->antenna_dvbt ^ gpio_state)) { - /* Antenna is on DVB-C mode. Switch */ - if (state->antenna_dvbt) -- state->m_gpio |= state->antenna_gpio; -+ state->m_GPIO |= state->antenna_gpio; - else -- state->m_gpio &= ~state->antenna_gpio; -- status = write_gpio(state); -+ state->m_GPIO &= ~state->antenna_gpio; -+ status = WriteGPIO(state); - } - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - - --static int power_down_device(struct drxk_state *state) -+static int PowerDownDevice(struct drxk_state *state) - { - /* Power down to requested mode */ - /* Backup some register settings */ -@@ -6024,86 +5943,98 @@ static int power_down_device(struct drxk_state *state) - int status; - - dprintk(1, "\n"); -- if (state->m_b_p_down_open_bridge) { -+ if (state->m_bPDownOpenBridge) { - /* Open I2C bridge before power down of DRXK */ - status = ConfigureI2CBridge(state, true); - if (status < 0) - goto error; - } - /* driver 0.9.0 */ -- status = dvbt_enable_ofdm_token_ring(state, false); -+ status = DVBTEnableOFDMTokenRing(state, false); - if (status < 0) - goto error; - -- status = write16(state, SIO_CC_PWD_MODE__A, -- SIO_CC_PWD_MODE_LEVEL_CLOCK); -+ status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK); - if (status < 0) - goto error; - status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); - if (status < 0) - goto error; -- state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; -- status = hi_cfg_command(state); -+ state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; -+ status = HI_CfgCommand(state); - error: - if (status < 0) -- pr_err("Error %d on %s\n", status, __func__); -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - -+static int load_microcode(struct drxk_state *state, const char *mc_name) -+{ -+ const struct firmware *fw = NULL; -+ int err = 0; -+ -+ dprintk(1, "\n"); -+ -+ err = request_firmware(&fw, mc_name, state->i2c->dev.parent); -+ if (err < 0) { -+ printk(KERN_ERR -+ "drxk: Could not load firmware file %s.\n", mc_name); -+ printk(KERN_INFO -+ "drxk: Copy %s to your hotplug directory!\n", mc_name); -+ return err; -+ } -+ err = DownloadMicrocode(state, fw->data, fw->size); -+ release_firmware(fw); -+ return err; -+} -+ - static int init_drxk(struct drxk_state *state) - { -- int status = 0, n = 0; -- enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; -- u16 driver_version; -+ int status = 0; -+ enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; -+ u16 driverVersion; - - dprintk(1, "\n"); -- if ((state->m_drxk_state == DRXK_UNINITIALIZED)) { -- drxk_i2c_lock(state); -- status = power_up_device(state); -+ if ((state->m_DrxkState == DRXK_UNINITIALIZED)) { -+ status = PowerUpDevice(state); - if (status < 0) - goto error; -- status = drxx_open(state); -+ status = DRXX_Open(state); - if (status < 0) - goto error; - /* Soft reset of OFDM-, sys- and osc-clockdomain */ -- status = write16(state, SIO_CC_SOFT_RST__A, -- SIO_CC_SOFT_RST_OFDM__M -- | SIO_CC_SOFT_RST_SYS__M -- | SIO_CC_SOFT_RST_OSC__M); -+ status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M); - if (status < 0) - goto error; - status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); - if (status < 0) - goto error; -- /* -- * TODO is this needed? If yes, how much delay in -- * worst case scenario -- */ -- usleep_range(1000, 2000); -- state->m_drxk_a3_patch_code = true; -- status = get_device_capabilities(state); -+ /* TODO is this needed, if yes how much delay in worst case scenario */ -+ msleep(1); -+ state->m_DRXK_A3_PATCH_CODE = true; -+ status = GetDeviceCapabilities(state); - if (status < 0) - goto error; - - /* Bridge delay, uses oscilator clock */ - /* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */ - /* SDA brdige delay */ -- state->m_hi_cfg_bridge_delay = -- (u16) ((state->m_osc_clock_freq / 1000) * -+ state->m_HICfgBridgeDelay = -+ (u16) ((state->m_oscClockFreq / 1000) * - HI_I2C_BRIDGE_DELAY) / 1000; - /* Clipping */ -- if (state->m_hi_cfg_bridge_delay > -+ if (state->m_HICfgBridgeDelay > - SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) { -- state->m_hi_cfg_bridge_delay = -+ state->m_HICfgBridgeDelay = - SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; - } - /* SCL bridge delay, same as SDA for now */ -- state->m_hi_cfg_bridge_delay += -- state->m_hi_cfg_bridge_delay << -+ state->m_HICfgBridgeDelay += -+ state->m_HICfgBridgeDelay << - SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B; - -- status = init_hi(state); -+ status = InitHI(state); - if (status < 0) - goto error; - /* disable various processes */ -@@ -6112,14 +6043,13 @@ static int init_drxk(struct drxk_state *state) - && !(state->m_DRXK_A2_ROM_CODE)) - #endif - { -- status = write16(state, SCU_RAM_GPIO__A, -- SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); -+ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); - if (status < 0) - goto error; - } - - /* disable MPEG port */ -- status = mpegts_disable(state); -+ status = MPEGTSDisable(state); - if (status < 0) - goto error; - -@@ -6132,30 +6062,23 @@ static int init_drxk(struct drxk_state *state) - goto error; - - /* enable token-ring bus through OFDM block for possible ucode upload */ -- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, -- SIO_OFDM_SH_OFDM_RING_ENABLE_ON); -+ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON); - if (status < 0) - goto error; - - /* include boot loader section */ -- status = write16(state, SIO_BL_COMM_EXEC__A, -- SIO_BL_COMM_EXEC_ACTIVE); -+ status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE); - if (status < 0) - goto error; -- status = bl_chain_cmd(state, 0, 6, 100); -+ status = BLChainCmd(state, 0, 6, 100); - if (status < 0) - goto error; - -- if (state->fw) { -- status = download_microcode(state, state->fw->data, -- state->fw->size); -- if (status < 0) -- goto error; -- } -+ if (state->microcode_name) -+ load_microcode(state, state->microcode_name); - - /* disable token-ring bus through OFDM block for possible ucode upload */ -- status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, -- SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); -+ status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); - if (status < 0) - goto error; - -@@ -6163,55 +6086,50 @@ static int init_drxk(struct drxk_state *state) - status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); - if (status < 0) - goto error; -- status = drxx_open(state); -+ status = DRXX_Open(state); - if (status < 0) - goto error; - /* added for test */ - msleep(30); - -- power_mode = DRXK_POWER_DOWN_OFDM; -- status = ctrl_power_mode(state, &power_mode); -+ powerMode = DRXK_POWER_DOWN_OFDM; -+ status = CtrlPowerMode(state, &powerMode); - if (status < 0) - goto error; - - /* Stamp driver version number in SCU data RAM in BCD code -- Done to enable field application engineers to retrieve drxdriver version -+ Done to enable field application engineers to retreive drxdriver version - via I2C from SCU RAM. - Not using SCU command interface for SCU register access since no - microcode may be present. - */ -- driver_version = -+ driverVersion = - (((DRXK_VERSION_MAJOR / 100) % 10) << 12) + - (((DRXK_VERSION_MAJOR / 10) % 10) << 8) + - ((DRXK_VERSION_MAJOR % 10) << 4) + - (DRXK_VERSION_MINOR % 10); -- status = write16(state, SCU_RAM_DRIVER_VER_HI__A, -- driver_version); -+ status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion); - if (status < 0) - goto error; -- driver_version = -+ driverVersion = - (((DRXK_VERSION_PATCH / 1000) % 10) << 12) + - (((DRXK_VERSION_PATCH / 100) % 10) << 8) + - (((DRXK_VERSION_PATCH / 10) % 10) << 4) + - (DRXK_VERSION_PATCH % 10); -- status = write16(state, SCU_RAM_DRIVER_VER_LO__A, -- driver_version); -+ status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion); - if (status < 0) - goto error; - -- pr_info("DRXK driver version %d.%d.%d\n", -+ printk(KERN_INFO "DRXK driver version %d.%d.%d\n", - DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR, - DRXK_VERSION_PATCH); - -- /* -- * Dirty fix of default values for ROM/PATCH microcode -- * Dirty because this fix makes it impossible to setup -- * suitable values before calling DRX_Open. This solution -- * requires changes to RF AGC speed to be done via the CTRL -- * function after calling DRX_Open -- */ -+ /* Dirty fix of default values for ROM/PATCH microcode -+ Dirty because this fix makes it impossible to setup suitable values -+ before calling DRX_Open. This solution requires changes to RF AGC speed -+ to be done via the CTRL function after calling DRX_Open */ - -- /* m_dvbt_rf_agc_cfg.speed = 3; */ -+ /* m_dvbtRfAgcCfg.speed = 3; */ - - /* Reset driver debug flags to 0 */ - status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0); -@@ -6224,94 +6142,45 @@ static int init_drxk(struct drxk_state *state) - if (status < 0) - goto error; - /* MPEGTS functions are still the same */ -- status = mpegts_dto_init(state); -+ status = MPEGTSDtoInit(state); - if (status < 0) - goto error; -- status = mpegts_stop(state); -+ status = MPEGTSStop(state); - if (status < 0) - goto error; -- status = mpegts_configure_polarity(state); -+ status = MPEGTSConfigurePolarity(state); - if (status < 0) - goto error; -- status = mpegts_configure_pins(state, state->m_enable_mpeg_output); -+ status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput); - if (status < 0) - goto error; - /* added: configure GPIO */ -- status = write_gpio(state); -+ status = WriteGPIO(state); - if (status < 0) - goto error; - -- state->m_drxk_state = DRXK_STOPPED; -+ state->m_DrxkState = DRXK_STOPPED; - -- if (state->m_b_power_down) { -- status = power_down_device(state); -+ if (state->m_bPowerDown) { -+ status = PowerDownDevice(state); - if (status < 0) - goto error; -- state->m_drxk_state = DRXK_POWERED_DOWN; -+ state->m_DrxkState = DRXK_POWERED_DOWN; - } else -- state->m_drxk_state = DRXK_STOPPED; -- -- /* Initialize the supported delivery systems */ -- n = 0; -- if (state->m_has_dvbc) { -- state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; -- state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; -- strlcat(state->frontend.ops.info.name, " DVB-C", -- sizeof(state->frontend.ops.info.name)); -- } -- if (state->m_has_dvbt) { -- state->frontend.ops.delsys[n++] = SYS_DVBT; -- strlcat(state->frontend.ops.info.name, " DVB-T", -- sizeof(state->frontend.ops.info.name)); -- } -- drxk_i2c_unlock(state); -+ state->m_DrxkState = DRXK_STOPPED; - } - error: -- if (status < 0) { -- state->m_drxk_state = DRXK_NO_DEV; -- drxk_i2c_unlock(state); -- pr_err("Error %d on %s\n", status, __func__); -- } -+ if (status < 0) -+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - - return status; - } - --static void load_firmware_cb(const struct firmware *fw, -- void *context) --{ -- struct drxk_state *state = context; -- -- dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded"); -- if (!fw) { -- pr_err("Could not load firmware file %s.\n", -- state->microcode_name); -- pr_info("Copy %s to your hotplug directory!\n", -- state->microcode_name); -- state->microcode_name = NULL; -- -- /* -- * As firmware is now load asynchronous, it is not possible -- * anymore to fail at frontend attach. We might silently -- * return here, and hope that the driver won't crash. -- * We might also change all DVB callbacks to return -ENODEV -- * if the device is not initialized. -- * As the DRX-K devices have their own internal firmware, -- * let's just hope that it will match a firmware revision -- * compatible with this driver and proceed. -- */ -- } -- state->fw = fw; -- -- init_drxk(state); --} -- - static void drxk_release(struct dvb_frontend *fe) - { - struct drxk_state *state = fe->demodulator_priv; - - dprintk(1, "\n"); -- release_firmware(state->fw); -- - kfree(state); - } - -@@ -6320,13 +6189,7 @@ static int drxk_sleep(struct dvb_frontend *fe) - struct drxk_state *state = fe->demodulator_priv; - - dprintk(1, "\n"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return 0; -- -- shut_down(state); -+ ShutDown(state); - return 0; - } - -@@ -6334,11 +6197,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct drxk_state *state = fe->demodulator_priv; - -- dprintk(1, ": %s\n", enable ? "enable" : "disable"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- -+ dprintk(1, "%s\n", enable ? "enable" : "disable"); - return ConfigureI2CBridge(state, enable ? true : false); - } - -@@ -6351,14 +6210,9 @@ static int drxk_set_parameters(struct dvb_frontend *fe) - - dprintk(1, "\n"); - -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- - if (!fe->ops.tuner_ops.get_if_frequency) { -- pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); -+ printk(KERN_ERR -+ "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); - return -EINVAL; - } - -@@ -6373,23 +6227,22 @@ static int drxk_set_parameters(struct dvb_frontend *fe) - state->props = *p; - - if (old_delsys != delsys) { -- shut_down(state); -+ ShutDown(state); - switch (delsys) { - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: -- if (!state->m_has_dvbc) -+ if (!state->m_hasDVBC) - return -EINVAL; -- state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? -- true : false; -+ state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false; - if (state->m_itut_annex_c) -- setoperation_mode(state, OM_QAM_ITU_C); -+ SetOperationMode(state, OM_QAM_ITU_C); - else -- setoperation_mode(state, OM_QAM_ITU_A); -+ SetOperationMode(state, OM_QAM_ITU_A); - break; - case SYS_DVBT: -- if (!state->m_has_dvbt) -+ if (!state->m_hasDVBT) - return -EINVAL; -- setoperation_mode(state, OM_DVBT); -+ SetOperationMode(state, OM_DVBT); - break; - default: - return -EINVAL; -@@ -6397,261 +6250,35 @@ static int drxk_set_parameters(struct dvb_frontend *fe) - } - - fe->ops.tuner_ops.get_if_frequency(fe, &IF); -- start(state, 0, IF); -- -- /* After set_frontend, stats aren't available */ -- p->strength.stat[0].scale = FE_SCALE_RELATIVE; -- p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -+ Start(state, 0, IF); - - /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */ - - return 0; - } - --static int get_strength(struct drxk_state *state, u64 *strength) --{ -- int status; -- struct s_cfg_agc rf_agc, if_agc; -- u32 total_gain = 0; -- u32 atten = 0; -- u32 agc_range = 0; -- u16 scu_lvl = 0; -- u16 scu_coc = 0; -- /* FIXME: those are part of the tuner presets */ -- u16 tuner_rf_gain = 50; /* Default value on az6007 driver */ -- u16 tuner_if_gain = 40; /* Default value on az6007 driver */ -- -- *strength = 0; -- -- if (is_dvbt(state)) { -- rf_agc = state->m_dvbt_rf_agc_cfg; -- if_agc = state->m_dvbt_if_agc_cfg; -- } else if (is_qam(state)) { -- rf_agc = state->m_qam_rf_agc_cfg; -- if_agc = state->m_qam_if_agc_cfg; -- } else { -- rf_agc = state->m_atv_rf_agc_cfg; -- if_agc = state->m_atv_if_agc_cfg; -- } -- -- if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { -- /* SCU output_level */ -- status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); -- if (status < 0) -- return status; -- -- /* SCU c.o.c. */ -- read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc); -- if (status < 0) -- return status; -- -- if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) -- rf_agc.output_level = scu_lvl + scu_coc; -- else -- rf_agc.output_level = 0xffff; -- -- /* Take RF gain into account */ -- total_gain += tuner_rf_gain; -- -- /* clip output value */ -- if (rf_agc.output_level < rf_agc.min_output_level) -- rf_agc.output_level = rf_agc.min_output_level; -- if (rf_agc.output_level > rf_agc.max_output_level) -- rf_agc.output_level = rf_agc.max_output_level; -- -- agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level); -- if (agc_range > 0) { -- atten += 100UL * -- ((u32)(tuner_rf_gain)) * -- ((u32)(rf_agc.output_level - rf_agc.min_output_level)) -- / agc_range; -- } -- } -- -- if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { -- status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, -- &if_agc.output_level); -- if (status < 0) -- return status; -- -- status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, -- &if_agc.top); -- if (status < 0) -- return status; -- -- /* Take IF gain into account */ -- total_gain += (u32) tuner_if_gain; -- -- /* clip output value */ -- if (if_agc.output_level < if_agc.min_output_level) -- if_agc.output_level = if_agc.min_output_level; -- if (if_agc.output_level > if_agc.max_output_level) -- if_agc.output_level = if_agc.max_output_level; -- -- agc_range = (u32)(if_agc.max_output_level - if_agc.min_output_level); -- if (agc_range > 0) { -- atten += 100UL * -- ((u32)(tuner_if_gain)) * -- ((u32)(if_agc.output_level - if_agc.min_output_level)) -- / agc_range; -- } -- } -- -- /* -- * Convert to 0..65535 scale. -- * If it can't be measured (AGC is disabled), just show 100%. -- */ -- if (total_gain > 0) -- *strength = (65535UL * atten / total_gain / 100); -- else -- *strength = 65535; -- -- return 0; --} -- --static int drxk_get_stats(struct dvb_frontend *fe) -+static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) - { -- struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct drxk_state *state = fe->demodulator_priv; -- int status; - u32 stat; -- u16 reg16; -- u32 post_bit_count; -- u32 post_bit_err_count; -- u32 post_bit_error_scale; -- u32 pre_bit_err_count; -- u32 pre_bit_count; -- u32 pkt_count; -- u32 pkt_error_count; -- s32 cnr; -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- -- /* get status */ -- state->fe_status = 0; -- get_lock_status(state, &stat); -+ -+ dprintk(1, "\n"); -+ *status = 0; -+ GetLockStatus(state, &stat, 0); - if (stat == MPEG_LOCK) -- state->fe_status |= 0x1f; -+ *status |= 0x1f; - if (stat == FEC_LOCK) -- state->fe_status |= 0x0f; -+ *status |= 0x0f; - if (stat == DEMOD_LOCK) -- state->fe_status |= 0x07; -- -- /* -- * Estimate signal strength from AGC -- */ -- get_strength(state, &c->strength.stat[0].uvalue); -- c->strength.stat[0].scale = FE_SCALE_RELATIVE; -- -- -- if (stat >= DEMOD_LOCK) { -- get_signal_to_noise(state, &cnr); -- c->cnr.stat[0].svalue = cnr * 100; -- c->cnr.stat[0].scale = FE_SCALE_DECIBEL; -- } else { -- c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- } -- -- if (stat < FEC_LOCK) { -- c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- return 0; -- } -- -- /* Get post BER */ -- -- /* BER measurement is valid if at least FEC lock is achieved */ -- -- /* -- * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be -- * written to set nr of symbols or bits over which to measure -- * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). -- */ -- -- /* Read registers for post/preViterbi BER calculation */ -- status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); -- if (status < 0) -- goto error; -- pre_bit_err_count = reg16; -- -- status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , ®16); -- if (status < 0) -- goto error; -- pre_bit_count = reg16; -- -- /* Number of bit-errors */ -- status = read16(state, FEC_RS_NR_BIT_ERRORS__A, ®16); -- if (status < 0) -- goto error; -- post_bit_err_count = reg16; -- -- status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, ®16); -- if (status < 0) -- goto error; -- post_bit_error_scale = reg16; -- -- status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, ®16); -- if (status < 0) -- goto error; -- pkt_count = reg16; -- -- status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, ®16); -- if (status < 0) -- goto error; -- pkt_error_count = reg16; -- write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); -- -- post_bit_err_count *= post_bit_error_scale; -- -- post_bit_count = pkt_count * 204 * 8; -- -- /* Store the results */ -- c->block_error.stat[0].scale = FE_SCALE_COUNTER; -- c->block_error.stat[0].uvalue += pkt_error_count; -- c->block_count.stat[0].scale = FE_SCALE_COUNTER; -- c->block_count.stat[0].uvalue += pkt_count; -- -- c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; -- c->pre_bit_error.stat[0].uvalue += pre_bit_err_count; -- c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; -- c->pre_bit_count.stat[0].uvalue += pre_bit_count; -- -- c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; -- c->post_bit_error.stat[0].uvalue += post_bit_err_count; -- c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; -- c->post_bit_count.stat[0].uvalue += post_bit_count; -- --error: -- return status; -+ *status |= 0x07; -+ return 0; - } - -- --static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) -+static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber) - { -- struct drxk_state *state = fe->demodulator_priv; -- int rc; -- - dprintk(1, "\n"); - -- rc = drxk_get_stats(fe); -- if (rc < 0) -- return rc; -- -- *status = state->fe_status; -- -+ *ber = 0; - return 0; - } - -@@ -6659,16 +6286,11 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, - u16 *strength) - { - struct drxk_state *state = fe->demodulator_priv; -- struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ u32 val = 0; - - dprintk(1, "\n"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- -- *strength = c->strength.stat[0].uvalue; -+ ReadIFAgc(state, &val); -+ *strength = val & 0xffff; - return 0; - } - -@@ -6678,17 +6300,7 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr) - s32 snr2; - - dprintk(1, "\n"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- -- get_signal_to_noise(state, &snr2); -- -- /* No negative SNR, clip to zero */ -- if (snr2 < 0) -- snr2 = 0; -+ GetSignalToNoise(state, &snr2); - *snr = snr2 & 0xffff; - return 0; - } -@@ -6699,30 +6311,17 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) - u16 err; - - dprintk(1, "\n"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- -- dvbtqam_get_acc_pkt_err(state, &err); -+ DVBTQAMGetAccPktErr(state, &err); - *ucblocks = (u32) err; - return 0; - } - --static int drxk_get_tune_settings(struct dvb_frontend *fe, -- struct dvb_frontend_tune_settings *sets) -+static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings -+ *sets) - { -- struct drxk_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - - dprintk(1, "\n"); -- -- if (state->m_drxk_state == DRXK_NO_DEV) -- return -ENODEV; -- if (state->m_drxk_state == DRXK_UNINITIALIZED) -- return -EAGAIN; -- - switch (p->delivery_system) { - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: -@@ -6764,6 +6363,7 @@ static struct dvb_frontend_ops drxk_ops = { - .get_tune_settings = drxk_get_tune_settings, - - .read_status = drxk_read_status, -+ .read_ber = drxk_read_ber, - .read_signal_strength = drxk_read_signal_strength, - .read_snr = drxk_read_snr, - .read_ucblocks = drxk_read_ucblocks, -@@ -6772,10 +6372,10 @@ static struct dvb_frontend_ops drxk_ops = { - struct dvb_frontend *drxk_attach(const struct drxk_config *config, - struct i2c_adapter *i2c) - { -- struct dtv_frontend_properties *p; -+ int n; -+ - struct drxk_state *state = NULL; - u8 adr = config->adr; -- int status; - - dprintk(1, "\n"); - state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL); -@@ -6786,40 +6386,39 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, - state->demod_address = adr; - state->single_master = config->single_master; - state->microcode_name = config->microcode_name; -- state->qam_demod_parameter_count = config->qam_demod_parameter_count; - state->no_i2c_bridge = config->no_i2c_bridge; - state->antenna_gpio = config->antenna_gpio; - state->antenna_dvbt = config->antenna_dvbt; -- state->m_chunk_size = config->chunk_size; -+ state->m_ChunkSize = config->chunk_size; - state->enable_merr_cfg = config->enable_merr_cfg; - - if (config->dynamic_clk) { -- state->m_dvbt_static_clk = false; -- state->m_dvbc_static_clk = false; -+ state->m_DVBTStaticCLK = 0; -+ state->m_DVBCStaticCLK = 0; - } else { -- state->m_dvbt_static_clk = true; -- state->m_dvbc_static_clk = true; -+ state->m_DVBTStaticCLK = 1; -+ state->m_DVBCStaticCLK = 1; - } - - - if (config->mpeg_out_clk_strength) -- state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07; -+ state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; - else -- state->m_ts_clockk_strength = 0x06; -+ state->m_TSClockkStrength = 0x06; - - if (config->parallel_ts) -- state->m_enable_parallel = true; -+ state->m_enableParallel = true; - else -- state->m_enable_parallel = false; -+ state->m_enableParallel = false; - - /* NOTE: as more UIO bits will be used, add them to the mask */ -- state->uio_mask = config->antenna_gpio; -+ state->UIO_mask = config->antenna_gpio; - - /* Default gpio to DVB-C */ - if (!state->antenna_dvbt && state->antenna_gpio) -- state->m_gpio |= state->antenna_gpio; -+ state->m_GPIO |= state->antenna_gpio; - else -- state->m_gpio &= ~state->antenna_gpio; -+ state->m_GPIO &= ~state->antenna_gpio; - - mutex_init(&state->mutex); - -@@ -6827,45 +6426,28 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, - state->frontend.demodulator_priv = state; - - init_state(state); -- -- /* Load firmware and initialize DRX-K */ -- if (state->microcode_name) { -- const struct firmware *fw = NULL; -- -- status = request_firmware(&fw, state->microcode_name, -- state->i2c->dev.parent); -- if (status < 0) -- fw = NULL; -- load_firmware_cb(fw, state); -- } else if (init_drxk(state) < 0) -+ if (init_drxk(state) < 0) - goto error; - -+ /* Initialize the supported delivery systems */ -+ n = 0; -+ if (state->m_hasDVBC) { -+ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; -+ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; -+ strlcat(state->frontend.ops.info.name, " DVB-C", -+ sizeof(state->frontend.ops.info.name)); -+ } -+ if (state->m_hasDVBT) { -+ state->frontend.ops.delsys[n++] = SYS_DVBT; -+ strlcat(state->frontend.ops.info.name, " DVB-T", -+ sizeof(state->frontend.ops.info.name)); -+ } - -- /* Initialize stats */ -- p = &state->frontend.dtv_property_cache; -- p->strength.len = 1; -- p->cnr.len = 1; -- p->block_error.len = 1; -- p->block_count.len = 1; -- p->pre_bit_error.len = 1; -- p->pre_bit_count.len = 1; -- p->post_bit_error.len = 1; -- p->post_bit_count.len = 1; -- -- p->strength.stat[0].scale = FE_SCALE_RELATIVE; -- p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- -- pr_info("frontend initialized.\n"); -+ printk(KERN_INFO "drxk: frontend initialized.\n"); - return &state->frontend; - - error: -- pr_err("not found\n"); -+ printk(KERN_ERR "drxk: not found\n"); - kfree(state); - return NULL; - } -diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h -index bae9c71..4bbf841 100644 ---- a/drivers/media/dvb-frontends/drxk_hard.h -+++ b/drivers/media/dvb-frontends/drxk_hard.h -@@ -46,7 +46,7 @@ - #define IQM_RC_ADJ_SEL_B_QAM 0x1 - #define IQM_RC_ADJ_SEL_B_VSB 0x2 - --enum operation_mode { -+enum OperationMode { - OM_NONE, - OM_QAM_ITU_A, - OM_QAM_ITU_B, -@@ -54,7 +54,7 @@ enum operation_mode { - OM_DVBT - }; - --enum drx_power_mode { -+enum DRXPowerMode { - DRX_POWER_UP = 0, - DRX_POWER_MODE_1, - DRX_POWER_MODE_2, -@@ -77,38 +77,25 @@ enum drx_power_mode { - }; - - --/* Intermediate power mode for DRXK, power down OFDM clock domain */ -+/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */ - #ifndef DRXK_POWER_DOWN_OFDM - #define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1 - #endif - --/* Intermediate power mode for DRXK, power down core (sysclk) */ -+/** /brief Intermediate power mode for DRXK, power down core (sysclk) */ - #ifndef DRXK_POWER_DOWN_CORE - #define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9 - #endif - --/* Intermediate power mode for DRXK, power down pll (only osc runs) */ -+/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */ - #ifndef DRXK_POWER_DOWN_PLL - #define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10 - #endif - - --enum agc_ctrl_mode { -- DRXK_AGC_CTRL_AUTO = 0, -- DRXK_AGC_CTRL_USER, -- DRXK_AGC_CTRL_OFF --}; -- --enum e_drxk_state { -- DRXK_UNINITIALIZED = 0, -- DRXK_STOPPED, -- DRXK_DTV_STARTED, -- DRXK_ATV_STARTED, -- DRXK_POWERED_DOWN, -- DRXK_NO_DEV /* If drxk init failed */ --}; -- --enum e_drxk_coef_array_index { -+enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; -+enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN }; -+enum EDrxkCoefArrayIndex { - DRXK_COEF_IDX_MN = 0, - DRXK_COEF_IDX_FM , - DRXK_COEF_IDX_L , -@@ -118,13 +105,13 @@ enum e_drxk_coef_array_index { - DRXK_COEF_IDX_I , - DRXK_COEF_IDX_MAX - }; --enum e_drxk_sif_attenuation { -+enum EDrxkSifAttenuation { - DRXK_SIF_ATTENUATION_0DB, - DRXK_SIF_ATTENUATION_3DB, - DRXK_SIF_ATTENUATION_6DB, - DRXK_SIF_ATTENUATION_9DB - }; --enum e_drxk_constellation { -+enum EDrxkConstellation { - DRX_CONSTELLATION_BPSK = 0, - DRX_CONSTELLATION_QPSK, - DRX_CONSTELLATION_PSK8, -@@ -138,7 +125,7 @@ enum e_drxk_constellation { - DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, - DRX_CONSTELLATION_AUTO = DRX_AUTO - }; --enum e_drxk_interleave_mode { -+enum EDrxkInterleaveMode { - DRXK_QAM_I12_J17 = 16, - DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN - }; -@@ -149,14 +136,14 @@ enum { - DRXK_SPIN_UNKNOWN - }; - --enum drxk_cfg_dvbt_sqi_speed { -+enum DRXKCfgDvbtSqiSpeed { - DRXK_DVBT_SQI_SPEED_FAST = 0, - DRXK_DVBT_SQI_SPEED_MEDIUM, - DRXK_DVBT_SQI_SPEED_SLOW, - DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN - } ; - --enum drx_fftmode_t { -+enum DRXFftmode_t { - DRX_FFTMODE_2K = 0, - DRX_FFTMODE_4K, - DRX_FFTMODE_8K, -@@ -164,47 +151,47 @@ enum drx_fftmode_t { - DRX_FFTMODE_AUTO = DRX_AUTO - }; - --enum drxmpeg_str_width_t { -+enum DRXMPEGStrWidth_t { - DRX_MPEG_STR_WIDTH_1, - DRX_MPEG_STR_WIDTH_8 - }; - --enum drx_qam_lock_range_t { -+enum DRXQamLockRange_t { - DRX_QAM_LOCKRANGE_NORMAL, - DRX_QAM_LOCKRANGE_EXTENDED - }; - --struct drxk_cfg_dvbt_echo_thres_t { -+struct DRXKCfgDvbtEchoThres_t { - u16 threshold; -- enum drx_fftmode_t fft_mode; -+ enum DRXFftmode_t fftMode; - } ; - --struct s_cfg_agc { -- enum agc_ctrl_mode ctrl_mode; /* off, user, auto */ -- u16 output_level; /* range dependent on AGC */ -- u16 min_output_level; /* range dependent on AGC */ -- u16 max_output_level; /* range dependent on AGC */ -+struct SCfgAgc { -+ enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */ -+ u16 outputLevel; /* range dependent on AGC */ -+ u16 minOutputLevel; /* range dependent on AGC */ -+ u16 maxOutputLevel; /* range dependent on AGC */ - u16 speed; /* range dependent on AGC */ - u16 top; /* rf-agc take over point */ -- u16 cut_off_current; /* rf-agc is accelerated if output current -+ u16 cutOffCurrent; /* rf-agc is accelerated if output current - is below cut-off current */ -- u16 ingain_tgt_max; -- u16 fast_clip_ctrl_delay; -+ u16 IngainTgtMax; -+ u16 FastClipCtrlDelay; - }; - --struct s_cfg_pre_saw { -+struct SCfgPreSaw { - u16 reference; /* pre SAW reference value, range 0 .. 31 */ -- bool use_pre_saw; /* TRUE algorithms must use pre SAW sense */ -+ bool usePreSaw; /* TRUE algorithms must use pre SAW sense */ - }; - --struct drxk_ofdm_sc_cmd_t { -- u16 cmd; /* Command number */ -- u16 subcmd; /* Sub-command parameter*/ -- u16 param0; /* General purpous param */ -- u16 param1; /* General purpous param */ -- u16 param2; /* General purpous param */ -- u16 param3; /* General purpous param */ -- u16 param4; /* General purpous param */ -+struct DRXKOfdmScCmd_t { -+ u16 cmd; /**< Command number */ -+ u16 subcmd; /**< Sub-command parameter*/ -+ u16 param0; /**< General purpous param */ -+ u16 param1; /**< General purpous param */ -+ u16 param2; /**< General purpous param */ -+ u16 param3; /**< General purpous param */ -+ u16 param4; /**< General purpous param */ - }; - - struct drxk_state { -@@ -218,131 +205,132 @@ struct drxk_state { - - struct mutex mutex; - -- u32 m_instance; /* Channel 1,2,3 or 4 */ -- -- int m_chunk_size; -- u8 chunk[256]; -- -- bool m_has_lna; -- bool m_has_dvbt; -- bool m_has_dvbc; -- bool m_has_audio; -- bool m_has_atv; -- bool m_has_oob; -- bool m_has_sawsw; /* TRUE if mat_tx is available */ -- bool m_has_gpio1; /* TRUE if mat_rx is available */ -- bool m_has_gpio2; /* TRUE if GPIO is available */ -- bool m_has_irqn; /* TRUE if IRQN is available */ -- u16 m_osc_clock_freq; -- u16 m_hi_cfg_timing_div; -- u16 m_hi_cfg_bridge_delay; -- u16 m_hi_cfg_wake_up_key; -- u16 m_hi_cfg_timeout; -- u16 m_hi_cfg_ctrl; -- s32 m_sys_clock_freq; /* system clock frequency in kHz */ -- -- enum e_drxk_state m_drxk_state; /* State of Drxk (init,stopped,started) */ -- enum operation_mode m_operation_mode; /* digital standards */ -- struct s_cfg_agc m_vsb_rf_agc_cfg; /* settings for VSB RF-AGC */ -- struct s_cfg_agc m_vsb_if_agc_cfg; /* settings for VSB IF-AGC */ -- u16 m_vsb_pga_cfg; /* settings for VSB PGA */ -- struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /* settings for pre SAW sense */ -- s32 m_Quality83percent; /* MER level (*0.1 dB) for 83% quality indication */ -- s32 m_Quality93percent; /* MER level (*0.1 dB) for 93% quality indication */ -- bool m_smart_ant_inverted; -- bool m_b_debug_enable_bridge; -- bool m_b_p_down_open_bridge; /* only open DRXK bridge before power-down once it has been accessed */ -- bool m_b_power_down; /* Power down when not used */ -- -- u32 m_iqm_fs_rate_ofs; /* frequency shift as written to DRXK register (28bit fixpoint) */ -- -- bool m_enable_mpeg_output; /* If TRUE, enable MPEG output */ -- bool m_insert_rs_byte; /* If TRUE, insert RS byte */ -- bool m_enable_parallel; /* If TRUE, parallel out otherwise serial */ -- bool m_invert_data; /* If TRUE, invert DATA signals */ -- bool m_invert_err; /* If TRUE, invert ERR signal */ -- bool m_invert_str; /* If TRUE, invert STR signals */ -- bool m_invert_val; /* If TRUE, invert VAL signals */ -- bool m_invert_clk; /* If TRUE, invert CLK signals */ -- bool m_dvbc_static_clk; -- bool m_dvbt_static_clk; /* If TRUE, static MPEG clockrate will -+ u32 m_Instance; /**< Channel 1,2,3 or 4 */ -+ -+ int m_ChunkSize; -+ u8 Chunk[256]; -+ -+ bool m_hasLNA; -+ bool m_hasDVBT; -+ bool m_hasDVBC; -+ bool m_hasAudio; -+ bool m_hasATV; -+ bool m_hasOOB; -+ bool m_hasSAWSW; /**< TRUE if mat_tx is available */ -+ bool m_hasGPIO1; /**< TRUE if mat_rx is available */ -+ bool m_hasGPIO2; /**< TRUE if GPIO is available */ -+ bool m_hasIRQN; /**< TRUE if IRQN is available */ -+ u16 m_oscClockFreq; -+ u16 m_HICfgTimingDiv; -+ u16 m_HICfgBridgeDelay; -+ u16 m_HICfgWakeUpKey; -+ u16 m_HICfgTimeout; -+ u16 m_HICfgCtrl; -+ s32 m_sysClockFreq; /**< system clock frequency in kHz */ -+ -+ enum EDrxkState m_DrxkState; /**< State of Drxk (init,stopped,started) */ -+ enum OperationMode m_OperationMode; /**< digital standards */ -+ struct SCfgAgc m_vsbRfAgcCfg; /**< settings for VSB RF-AGC */ -+ struct SCfgAgc m_vsbIfAgcCfg; /**< settings for VSB IF-AGC */ -+ u16 m_vsbPgaCfg; /**< settings for VSB PGA */ -+ struct SCfgPreSaw m_vsbPreSawCfg; /**< settings for pre SAW sense */ -+ s32 m_Quality83percent; /**< MER level (*0.1 dB) for 83% quality indication */ -+ s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ -+ bool m_smartAntInverted; -+ bool m_bDebugEnableBridge; -+ bool m_bPDownOpenBridge; /**< only open DRXK bridge before power-down once it has been accessed */ -+ bool m_bPowerDown; /**< Power down when not used */ -+ -+ u32 m_IqmFsRateOfs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ -+ -+ bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */ -+ bool m_insertRSByte; /**< If TRUE, insert RS byte */ -+ bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */ -+ bool m_invertDATA; /**< If TRUE, invert DATA signals */ -+ bool m_invertERR; /**< If TRUE, invert ERR signal */ -+ bool m_invertSTR; /**< If TRUE, invert STR signals */ -+ bool m_invertVAL; /**< If TRUE, invert VAL signals */ -+ bool m_invertCLK; /**< If TRUE, invert CLK signals */ -+ bool m_DVBCStaticCLK; -+ bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will - be used, otherwise clockrate will - adapt to the bitrate of the TS */ -- u32 m_dvbt_bitrate; -- u32 m_dvbc_bitrate; -+ u32 m_DVBTBitrate; -+ u32 m_DVBCBitrate; - -- u8 m_ts_data_strength; -- u8 m_ts_clockk_strength; -+ u8 m_TSDataStrength; -+ u8 m_TSClockkStrength; - - bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ - -- enum drxmpeg_str_width_t m_width_str; /* MPEG start width */ -- u32 m_mpeg_ts_static_bitrate; /* Maximum bitrate in b/s in case -+ enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width */ -+ u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case - static clockrate is selected */ - -- /* LARGE_INTEGER m_startTime; */ /* Contains the time of the last demod start */ -- s32 m_mpeg_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ -- s32 m_demod_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ -- -- bool m_disable_te_ihandling; -- -- bool m_rf_agc_pol; -- bool m_if_agc_pol; -- -- struct s_cfg_agc m_atv_rf_agc_cfg; /* settings for ATV RF-AGC */ -- struct s_cfg_agc m_atv_if_agc_cfg; /* settings for ATV IF-AGC */ -- struct s_cfg_pre_saw m_atv_pre_saw_cfg; /* settings for ATV pre SAW sense */ -- bool m_phase_correction_bypass; -- s16 m_atv_top_vid_peak; -- u16 m_atv_top_noise_th; -- enum e_drxk_sif_attenuation m_sif_attenuation; -- bool m_enable_cvbs_output; -- bool m_enable_sif_output; -- bool m_b_mirror_freq_spect; -- enum e_drxk_constellation m_constellation; /* constellation type of the channel */ -- u32 m_curr_symbol_rate; /* Current QAM symbol rate */ -- struct s_cfg_agc m_qam_rf_agc_cfg; /* settings for QAM RF-AGC */ -- struct s_cfg_agc m_qam_if_agc_cfg; /* settings for QAM IF-AGC */ -- u16 m_qam_pga_cfg; /* settings for QAM PGA */ -- struct s_cfg_pre_saw m_qam_pre_saw_cfg; /* settings for QAM pre SAW sense */ -- enum e_drxk_interleave_mode m_qam_interleave_mode; /* QAM Interleave mode */ -- u16 m_fec_rs_plen; -- u16 m_fec_rs_prescale; -- -- enum drxk_cfg_dvbt_sqi_speed m_sqi_speed; -- -- u16 m_gpio; -- u16 m_gpio_cfg; -- -- struct s_cfg_agc m_dvbt_rf_agc_cfg; /* settings for QAM RF-AGC */ -- struct s_cfg_agc m_dvbt_if_agc_cfg; /* settings for QAM IF-AGC */ -- struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /* settings for QAM pre SAW sense */ -- -- u16 m_agcfast_clip_ctrl_delay; -- bool m_adc_comp_passed; -+ /* LARGE_INTEGER m_StartTime; */ /**< Contains the time of the last demod start */ -+ s32 m_MpegLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ -+ s32 m_DemodLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ -+ -+ bool m_disableTEIhandling; -+ -+ bool m_RfAgcPol; -+ bool m_IfAgcPol; -+ -+ struct SCfgAgc m_atvRfAgcCfg; /**< settings for ATV RF-AGC */ -+ struct SCfgAgc m_atvIfAgcCfg; /**< settings for ATV IF-AGC */ -+ struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */ -+ bool m_phaseCorrectionBypass; -+ s16 m_atvTopVidPeak; -+ u16 m_atvTopNoiseTh; -+ enum EDrxkSifAttenuation m_sifAttenuation; -+ bool m_enableCVBSOutput; -+ bool m_enableSIFOutput; -+ bool m_bMirrorFreqSpect; -+ enum EDrxkConstellation m_Constellation; /**< Constellation type of the channel */ -+ u32 m_CurrSymbolRate; /**< Current QAM symbol rate */ -+ struct SCfgAgc m_qamRfAgcCfg; /**< settings for QAM RF-AGC */ -+ struct SCfgAgc m_qamIfAgcCfg; /**< settings for QAM IF-AGC */ -+ u16 m_qamPgaCfg; /**< settings for QAM PGA */ -+ struct SCfgPreSaw m_qamPreSawCfg; /**< settings for QAM pre SAW sense */ -+ enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */ -+ u16 m_fecRsPlen; -+ u16 m_fecRsPrescale; -+ -+ enum DRXKCfgDvbtSqiSpeed m_sqiSpeed; -+ -+ u16 m_GPIO; -+ u16 m_GPIOCfg; -+ -+ struct SCfgAgc m_dvbtRfAgcCfg; /**< settings for QAM RF-AGC */ -+ struct SCfgAgc m_dvbtIfAgcCfg; /**< settings for QAM IF-AGC */ -+ struct SCfgPreSaw m_dvbtPreSawCfg; /**< settings for QAM pre SAW sense */ -+ -+ u16 m_agcFastClipCtrlDelay; -+ bool m_adcCompPassed; - u16 m_adcCompCoef[64]; -- u16 m_adc_state; -+ u16 m_adcState; - - u8 *m_microcode; - int m_microcode_length; -- bool m_drxk_a3_rom_code; -- bool m_drxk_a3_patch_code; -+ bool m_DRXK_A1_PATCH_CODE; -+ bool m_DRXK_A1_ROM_CODE; -+ bool m_DRXK_A2_ROM_CODE; -+ bool m_DRXK_A3_ROM_CODE; -+ bool m_DRXK_A2_PATCH_CODE; -+ bool m_DRXK_A3_PATCH_CODE; - - bool m_rfmirror; -- u8 m_device_spin; -- u32 m_iqm_rc_rate; -- -- enum drx_power_mode m_current_power_mode; -+ u8 m_deviceSpin; -+ u32 m_iqmRcRate; - -- /* when true, avoids other devices to use the I2C bus */ -- bool drxk_i2c_exclusive_lock; -+ enum DRXPowerMode m_currentPowerMode; - - /* - * Configurable parameters at the driver. They stores the values found - * at struct drxk_config. - */ - -- u16 uio_mask; /* Bits used by UIO */ -+ u16 UIO_mask; /* Bits used by UIO */ - - bool enable_merr_cfg; - bool single_master; -@@ -350,13 +338,7 @@ struct drxk_state { - bool antenna_dvbt; - u16 antenna_gpio; - -- fe_status_t fe_status; -- -- /* Firmware */ - const char *microcode_name; -- struct completion fw_wait_load; -- const struct firmware *fw; -- int qam_demod_parameter_count; - }; - - #define NEVER_LOCK 0 -diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h -index 761613f..23e16c1 100644 ---- a/drivers/media/dvb-frontends/drxk_map.h -+++ b/drivers/media/dvb-frontends/drxk_map.h -@@ -10,7 +10,6 @@ - #define FEC_RS_COMM_EXEC_STOP 0x0 - #define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012 - #define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013 --#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014 - #define FEC_OC_MODE__A 0x1C40011 - #define FEC_OC_MODE_PARITY__M 0x1 - #define FEC_OC_DTO_MODE__A 0x1C40014 -@@ -130,8 +129,6 @@ - #define OFDM_EC_SB_PRIOR__A 0x3410013 - #define OFDM_EC_SB_PRIOR_HI 0x0 - #define OFDM_EC_SB_PRIOR_LO 0x1 --#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017 --#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018 - #define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054 - #define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3 - #define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2 -diff --git a/drivers/media/dvb-frontends/lnbh25.c b/drivers/media/dvb-frontends/lnbh25.c -new file mode 100644 -index 0000000..f167e67 ---- /dev/null -+++ b/drivers/media/dvb-frontends/lnbh25.c -@@ -0,0 +1,153 @@ -+/* -+ * Driver for the ST LNBH25 -+ * -+ * Copyright (C) 2014 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "lnbh25.h" -+ -+struct lnbh25 { -+ struct i2c_adapter *i2c; -+ u8 adr; -+ u8 reg[4]; -+ u8 boost; -+}; -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("lnbh25: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len) -+{ -+ u8 d[5]; -+ -+ memcpy(&d[1], &lnbh->reg[reg], len); -+ d[0] = reg + 2; -+ return i2c_write(lnbh->i2c, lnbh->adr, d, len + 1); -+} -+ -+static int lnbh25_set_voltage(struct dvb_frontend *fe, -+ fe_sec_voltage_t voltage) -+{ -+ struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ lnbh->reg[0] = 0x00; -+ lnbh->reg[1] &= ~0x01; /* Disable Tone */ -+ lnbh->reg[2] = 0x00; -+ return lnbh25_write_regs(lnbh, 0, 3); -+ case SEC_VOLTAGE_13: -+ lnbh->reg[0] = lnbh->boost + 1; -+ break; -+ case SEC_VOLTAGE_18: -+ lnbh->reg[0] = lnbh->boost + 8; -+ break; -+ default: -+ return -EINVAL; -+ }; -+ -+ if (lnbh->reg[0] == 0x00) { -+ lnbh->reg[2] = 4; -+ lnbh25_write_regs(lnbh, 2, 2); -+ } else if (lnbh->reg[2] != 0x00) { -+ lnbh->reg[2] = 0; -+ lnbh25_write_regs(lnbh, 2, 2); -+ } -+ lnbh->reg[1] |= 0x01; -+ return lnbh25_write_regs(lnbh, 0, 3); -+} -+ -+static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) -+{ -+ struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; -+ -+ lnbh->boost = arg ? 3 : 0; -+ -+ return 0; -+} -+ -+static int lnbh25_set_tone(struct dvb_frontend *fe, -+ fe_sec_tone_mode_t tone) -+{ -+ /* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */ -+ -+ return 0; -+} -+ -+static int lnbh25_init(struct lnbh25 *lnbh) -+{ -+ return lnbh25_write_regs(lnbh, 0, 2); -+} -+ -+static void lnbh25_release(struct dvb_frontend *fe) -+{ -+ kfree(fe->sec_priv); -+ fe->sec_priv = NULL; -+} -+ -+struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ u8 adr) -+{ -+ struct lnbh25 *lnbh = kzalloc(sizeof(struct lnbh25), GFP_KERNEL); -+ if (!lnbh) -+ return NULL; -+ -+ lnbh->i2c = i2c; -+ lnbh->adr = adr; -+ lnbh->boost = 3; -+ -+ if (lnbh25_init(lnbh)) { -+ kfree(lnbh); -+ return NULL; -+ } -+ fe->sec_priv = lnbh; -+ fe->ops.set_voltage = lnbh25_set_voltage; -+ fe->ops.enable_high_lnb_voltage = lnbh25_enable_high_lnb_voltage; -+ fe->ops.release_sec = lnbh25_release; -+ -+ pr_info("LNB25 on %02x\n", lnbh->adr); -+ -+ return fe; -+} -+EXPORT_SYMBOL(lnbh25_attach); -+ -+MODULE_DESCRIPTION("LNBH25"); -+MODULE_AUTHOR("Ralph Metzler"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/lnbh25.h b/drivers/media/dvb-frontends/lnbh25.h -new file mode 100644 -index 0000000..4e8b3cc ---- /dev/null -+++ b/drivers/media/dvb-frontends/lnbh25.h -@@ -0,0 +1,28 @@ -+/* -+ * lnbh25.h -+ */ -+ -+#ifndef _LNBH25_H -+#define _LNBH25_H -+ -+#include -+ -+#if defined(CONFIG_DVB_LNBH25) || \ -+ (defined(CONFIG_DVB_LNBH25_MODULE) && defined(MODULE)) -+ -+extern struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ u8 i2c_addr); -+#else -+ -+static inline struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ u8 i2c_addr) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif -+ -+#endif -diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c -new file mode 100644 -index 0000000..a9d2e5b ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.c -@@ -0,0 +1,2331 @@ -+/* -+ * stv0367dd: STV0367 DVB-C/T demodulator driver -+ * -+ * Copyright (C) 2011 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "stv0367dd.h" -+#include "stv0367dd_regs.h" -+ -+enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C }; -+enum { QAM_MOD_QAM4 = 0, -+ QAM_MOD_QAM16, -+ QAM_MOD_QAM32, -+ QAM_MOD_QAM64, -+ QAM_MOD_QAM128, -+ QAM_MOD_QAM256, -+ QAM_MOD_QAM512, -+ QAM_MOD_QAM1024 -+}; -+ -+enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED }; -+ -+enum { -+ QAM_FEC_A = 1, /* J83 Annex A */ -+ QAM_FEC_B = (1<<1), /* J83 Annex B */ -+ QAM_FEC_C = (1<<2) /* J83 Annex C */ -+}; -+ -+enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted }; -+ -+struct stv_state { -+#ifdef USE_API3 -+ struct dvb_frontend c_frontend; -+ struct dvb_frontend t_frontend; -+#else -+ struct dvb_frontend frontend; -+#endif -+ fe_modulation_t modulation; -+ u32 symbol_rate; -+ u32 bandwidth; -+ struct device *dev; -+ -+ struct i2c_adapter *i2c; -+ u8 adr; -+ void *priv; -+ -+ struct mutex mutex; -+ struct mutex ctlock; -+ -+ u32 master_clock; -+ u32 adc_clock; -+ u8 ID; -+ u8 I2CRPT; -+ u32 omode; -+ u8 qam_inversion; -+ -+ s32 IF; -+ -+ s32 m_FECTimeOut; -+ s32 m_DemodTimeOut; -+ s32 m_SignalTimeOut; -+ s32 m_DemodLockTime; -+ s32 m_FFTTimeOut; -+ s32 m_TSTimeOut; -+ -+ bool m_bFirstTimeLock; -+ -+ u8 m_Save_QAM_AGC_CTL; -+ -+ enum EDemodState demod_state; -+ -+ u8 m_OFDM_FFTMode; // 0 = 2k, 1 = 8k, 2 = 4k -+ u8 m_OFDM_Modulation; // -+ u8 m_OFDM_FEC; // -+ u8 m_OFDM_Guard; -+ -+ u32 ucblocks; -+ u32 ber; -+}; -+ -+struct init_table { -+ u16 adr; -+ u8 data; -+}; -+ -+struct init_table base_init[] = { -+ { R367_IOCFG0, 0x80 }, -+ { R367_DAC0R, 0x00 }, -+ { R367_IOCFG1, 0x00 }, -+ { R367_DAC1R, 0x00 }, -+ { R367_IOCFG2, 0x00 }, -+ { R367_SDFR, 0x00 }, -+ { R367_AUX_CLK, 0x00 }, -+ { R367_FREESYS1, 0x00 }, -+ { R367_FREESYS2, 0x00 }, -+ { R367_FREESYS3, 0x00 }, -+ { R367_GPIO_CFG, 0x55 }, -+ { R367_GPIO_CMD, 0x01 }, -+ { R367_TSTRES, 0x00 }, -+ { R367_ANACTRL, 0x00 }, -+ { R367_TSTBUS, 0x00 }, -+ { R367_RF_AGC2, 0x20 }, -+ { R367_ANADIGCTRL, 0x0b }, -+ { R367_PLLMDIV, 0x01 }, -+ { R367_PLLNDIV, 0x08 }, -+ { R367_PLLSETUP, 0x18 }, -+ { R367_DUAL_AD12, 0x04 }, -+ { R367_TSTBIST, 0x00 }, -+ { 0x0000, 0x00 } -+}; -+ -+struct init_table qam_init[] = { -+ { R367_QAM_CTRL_1, 0x06 },// Orginal 0x04 -+ { R367_QAM_CTRL_2, 0x03 }, -+ { R367_QAM_IT_STATUS1, 0x2b }, -+ { R367_QAM_IT_STATUS2, 0x08 }, -+ { R367_QAM_IT_EN1, 0x00 }, -+ { R367_QAM_IT_EN2, 0x00 }, -+ { R367_QAM_CTRL_STATUS, 0x04 }, -+ { R367_QAM_TEST_CTL, 0x00 }, -+ { R367_QAM_AGC_CTL, 0x73 }, -+ { R367_QAM_AGC_IF_CFG, 0x50 }, -+ { R367_QAM_AGC_RF_CFG, 0x02 },// RF Freeze -+ { R367_QAM_AGC_PWM_CFG, 0x03 }, -+ { R367_QAM_AGC_PWR_REF_L, 0x5a }, -+ { R367_QAM_AGC_PWR_REF_H, 0x00 }, -+ { R367_QAM_AGC_RF_TH_L, 0xff }, -+ { R367_QAM_AGC_RF_TH_H, 0x07 }, -+ { R367_QAM_AGC_IF_LTH_L, 0x00 }, -+ { R367_QAM_AGC_IF_LTH_H, 0x08 }, -+ { R367_QAM_AGC_IF_HTH_L, 0xff }, -+ { R367_QAM_AGC_IF_HTH_H, 0x07 }, -+ { R367_QAM_AGC_PWR_RD_L, 0xa0 }, -+ { R367_QAM_AGC_PWR_RD_M, 0xe9 }, -+ { R367_QAM_AGC_PWR_RD_H, 0x03 }, -+ { R367_QAM_AGC_PWM_IFCMD_L, 0xe4 }, -+ { R367_QAM_AGC_PWM_IFCMD_H, 0x00 }, -+ { R367_QAM_AGC_PWM_RFCMD_L, 0xff }, -+ { R367_QAM_AGC_PWM_RFCMD_H, 0x07 }, -+ { R367_QAM_IQDEM_CFG, 0x01 }, -+ { R367_QAM_MIX_NCO_LL, 0x22 }, -+ { R367_QAM_MIX_NCO_HL, 0x96 }, -+ { R367_QAM_MIX_NCO_HH, 0x55 }, -+ { R367_QAM_SRC_NCO_LL, 0xff }, -+ { R367_QAM_SRC_NCO_LH, 0x0c }, -+ { R367_QAM_SRC_NCO_HL, 0xf5 }, -+ { R367_QAM_SRC_NCO_HH, 0x20 }, -+ { R367_QAM_IQDEM_GAIN_SRC_L, 0x06 }, -+ { R367_QAM_IQDEM_GAIN_SRC_H, 0x01 }, -+ { R367_QAM_IQDEM_DCRM_CFG_LL, 0xfe }, -+ { R367_QAM_IQDEM_DCRM_CFG_LH, 0xff }, -+ { R367_QAM_IQDEM_DCRM_CFG_HL, 0x0f }, -+ { R367_QAM_IQDEM_DCRM_CFG_HH, 0x00 }, -+ { R367_QAM_IQDEM_ADJ_COEFF0, 0x34 }, -+ { R367_QAM_IQDEM_ADJ_COEFF1, 0xae }, -+ { R367_QAM_IQDEM_ADJ_COEFF2, 0x46 }, -+ { R367_QAM_IQDEM_ADJ_COEFF3, 0x77 }, -+ { R367_QAM_IQDEM_ADJ_COEFF4, 0x96 }, -+ { R367_QAM_IQDEM_ADJ_COEFF5, 0x69 }, -+ { R367_QAM_IQDEM_ADJ_COEFF6, 0xc7 }, -+ { R367_QAM_IQDEM_ADJ_COEFF7, 0x01 }, -+ { R367_QAM_IQDEM_ADJ_EN, 0x04 }, -+ { R367_QAM_IQDEM_ADJ_AGC_REF, 0x94 }, -+ { R367_QAM_ALLPASSFILT1, 0xc9 }, -+ { R367_QAM_ALLPASSFILT2, 0x2d }, -+ { R367_QAM_ALLPASSFILT3, 0xa3 }, -+ { R367_QAM_ALLPASSFILT4, 0xfb }, -+ { R367_QAM_ALLPASSFILT5, 0xf6 }, -+ { R367_QAM_ALLPASSFILT6, 0x45 }, -+ { R367_QAM_ALLPASSFILT7, 0x6f }, -+ { R367_QAM_ALLPASSFILT8, 0x7e }, -+ { R367_QAM_ALLPASSFILT9, 0x05 }, -+ { R367_QAM_ALLPASSFILT10, 0x0a }, -+ { R367_QAM_ALLPASSFILT11, 0x51 }, -+ { R367_QAM_TRL_AGC_CFG, 0x20 }, -+ { R367_QAM_TRL_LPF_CFG, 0x28 }, -+ { R367_QAM_TRL_LPF_ACQ_GAIN, 0x44 }, -+ { R367_QAM_TRL_LPF_TRK_GAIN, 0x22 }, -+ { R367_QAM_TRL_LPF_OUT_GAIN, 0x03 }, -+ { R367_QAM_TRL_LOCKDET_LTH, 0x04 }, -+ { R367_QAM_TRL_LOCKDET_HTH, 0x11 }, -+ { R367_QAM_TRL_LOCKDET_TRGVAL, 0x20 }, -+ { R367_QAM_IQ_QAM, 0x01 }, -+ { R367_QAM_FSM_STATE, 0xa0 }, -+ { R367_QAM_FSM_CTL, 0x08 }, -+ { R367_QAM_FSM_STS, 0x0c }, -+ { R367_QAM_FSM_SNR0_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR2_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR0_LTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_LTH, 0x00 }, -+ { R367_QAM_FSM_EQA1_HTH, 0x00 }, -+ { R367_QAM_FSM_TEMPO, 0x32 }, -+ { R367_QAM_FSM_CONFIG, 0x03 }, -+ { R367_QAM_EQU_I_TESTTAP_L, 0x11 }, -+ { R367_QAM_EQU_I_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_I_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TESTAP_CFG, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_L, 0xff }, -+ { R367_QAM_EQU_Q_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TAP_CTRL, 0x00 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_L, 0x11 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_H, 0x05 }, -+ { R367_QAM_EQU_CTR_HIPOW_L, 0x00 }, -+ { R367_QAM_EQU_CTR_HIPOW_H, 0x00 }, -+ { R367_QAM_EQU_I_EQU_LO, 0xef }, -+ { R367_QAM_EQU_I_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_Q_EQU_LO, 0xee }, -+ { R367_QAM_EQU_Q_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_MAPPER, 0xc5 }, -+ { R367_QAM_EQU_SWEEP_RATE, 0x80 }, -+ { R367_QAM_EQU_SNR_LO, 0x64 }, -+ { R367_QAM_EQU_SNR_HI, 0x03 }, -+ { R367_QAM_EQU_GAMMA_LO, 0x00 }, -+ { R367_QAM_EQU_GAMMA_HI, 0x00 }, -+ { R367_QAM_EQU_ERR_GAIN, 0x36 }, -+ { R367_QAM_EQU_RADIUS, 0xaa }, -+ { R367_QAM_EQU_FFE_MAINTAP, 0x00 }, -+ { R367_QAM_EQU_FFE_LEAKAGE, 0x63 }, -+ { R367_QAM_EQU_FFE_MAINTAP_POS, 0xdf }, -+ { R367_QAM_EQU_GAIN_WIDE, 0x88 }, -+ { R367_QAM_EQU_GAIN_NARROW, 0x41 }, -+ { R367_QAM_EQU_CTR_LPF_GAIN, 0xd1 }, -+ { R367_QAM_EQU_CRL_LPF_GAIN, 0xa7 }, -+ { R367_QAM_EQU_GLOBAL_GAIN, 0x06 }, -+ { R367_QAM_EQU_CRL_LD_SEN, 0x85 }, -+ { R367_QAM_EQU_CRL_LD_VAL, 0xe2 }, -+ { R367_QAM_EQU_CRL_TFR, 0x20 }, -+ { R367_QAM_EQU_CRL_BISTH_LO, 0x00 }, -+ { R367_QAM_EQU_CRL_BISTH_HI, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_LO, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_HI, 0x00 }, -+ { R367_QAM_EQU_CRL_LIMITER, 0x40 }, -+ { R367_QAM_EQU_MODULUS_MAP, 0x90 }, -+ { R367_QAM_EQU_PNT_GAIN, 0xa7 }, -+ { R367_QAM_FEC_AC_CTR_0, 0x16 }, -+ { R367_QAM_FEC_AC_CTR_1, 0x0b }, -+ { R367_QAM_FEC_AC_CTR_2, 0x88 }, -+ { R367_QAM_FEC_AC_CTR_3, 0x02 }, -+ { R367_QAM_FEC_STATUS, 0x12 }, -+ { R367_QAM_RS_COUNTER_0, 0x7d }, -+ { R367_QAM_RS_COUNTER_1, 0xd0 }, -+ { R367_QAM_RS_COUNTER_2, 0x19 }, -+ { R367_QAM_RS_COUNTER_3, 0x0b }, -+ { R367_QAM_RS_COUNTER_4, 0xa3 }, -+ { R367_QAM_RS_COUNTER_5, 0x00 }, -+ { R367_QAM_BERT_0, 0x01 }, -+ { R367_QAM_BERT_1, 0x25 }, -+ { R367_QAM_BERT_2, 0x41 }, -+ { R367_QAM_BERT_3, 0x39 }, -+ { R367_QAM_OUTFORMAT_0, 0xc2 }, -+ { R367_QAM_OUTFORMAT_1, 0x22 }, -+ { R367_QAM_SMOOTHER_2, 0x28 }, -+ { R367_QAM_TSMF_CTRL_0, 0x01 }, -+ { R367_QAM_TSMF_CTRL_1, 0xc6 }, -+ { R367_QAM_TSMF_CTRL_3, 0x43 }, -+ { R367_QAM_TS_ON_ID_0, 0x00 }, -+ { R367_QAM_TS_ON_ID_1, 0x00 }, -+ { R367_QAM_TS_ON_ID_2, 0x00 }, -+ { R367_QAM_TS_ON_ID_3, 0x00 }, -+ { R367_QAM_RE_STATUS_0, 0x00 }, -+ { R367_QAM_RE_STATUS_1, 0x00 }, -+ { R367_QAM_RE_STATUS_2, 0x00 }, -+ { R367_QAM_RE_STATUS_3, 0x00 }, -+ { R367_QAM_TS_STATUS_0, 0x00 }, -+ { R367_QAM_TS_STATUS_1, 0x00 }, -+ { R367_QAM_TS_STATUS_2, 0xa0 }, -+ { R367_QAM_TS_STATUS_3, 0x00 }, -+ { R367_QAM_T_O_ID_0, 0x00 }, -+ { R367_QAM_T_O_ID_1, 0x00 }, -+ { R367_QAM_T_O_ID_2, 0x00 }, -+ { R367_QAM_T_O_ID_3, 0x00 }, -+ { 0x0000, 0x00 } // EOT -+}; -+ -+struct init_table ofdm_init[] = { -+ //{R367_OFDM_ID ,0x60}, -+ //{R367_OFDM_I2CRPT ,0x22}, -+ //{R367_OFDM_TOPCTRL ,0x02}, -+ //{R367_OFDM_IOCFG0 ,0x40}, -+ //{R367_OFDM_DAC0R ,0x00}, -+ //{R367_OFDM_IOCFG1 ,0x00}, -+ //{R367_OFDM_DAC1R ,0x00}, -+ //{R367_OFDM_IOCFG2 ,0x62}, -+ //{R367_OFDM_SDFR ,0x00}, -+ //{R367_OFDM_STATUS ,0xf8}, -+ //{R367_OFDM_AUX_CLK ,0x0a}, -+ //{R367_OFDM_FREESYS1 ,0x00}, -+ //{R367_OFDM_FREESYS2 ,0x00}, -+ //{R367_OFDM_FREESYS3 ,0x00}, -+ //{R367_OFDM_GPIO_CFG ,0x55}, -+ //{R367_OFDM_GPIO_CMD ,0x00}, -+ {R367_OFDM_AGC2MAX ,0xff}, -+ {R367_OFDM_AGC2MIN ,0x00}, -+ {R367_OFDM_AGC1MAX ,0xff}, -+ {R367_OFDM_AGC1MIN ,0x00}, -+ {R367_OFDM_AGCR ,0xbc}, -+ {R367_OFDM_AGC2TH ,0x00}, -+ //{R367_OFDM_AGC12C ,0x01}, //Note: This defines AGC pins, also needed for QAM -+ {R367_OFDM_AGCCTRL1 ,0x85}, -+ {R367_OFDM_AGCCTRL2 ,0x1f}, -+ {R367_OFDM_AGC1VAL1 ,0x00}, -+ {R367_OFDM_AGC1VAL2 ,0x00}, -+ {R367_OFDM_AGC2VAL1 ,0x6f}, -+ {R367_OFDM_AGC2VAL2 ,0x05}, -+ {R367_OFDM_AGC2PGA ,0x00}, -+ {R367_OFDM_OVF_RATE1 ,0x00}, -+ {R367_OFDM_OVF_RATE2 ,0x00}, -+ {R367_OFDM_GAIN_SRC1 ,0x2b}, -+ {R367_OFDM_GAIN_SRC2 ,0x04}, -+ {R367_OFDM_INC_DEROT1 ,0x55}, -+ {R367_OFDM_INC_DEROT2 ,0x55}, -+ {R367_OFDM_PPM_CPAMP_DIR ,0x2c}, -+ {R367_OFDM_PPM_CPAMP_INV ,0x00}, -+ {R367_OFDM_FREESTFE_1 ,0x00}, -+ {R367_OFDM_FREESTFE_2 ,0x1c}, -+ {R367_OFDM_DCOFFSET ,0x00}, -+ {R367_OFDM_EN_PROCESS ,0x05}, -+ {R367_OFDM_SDI_SMOOTHER ,0x80}, -+ {R367_OFDM_FE_LOOP_OPEN ,0x1c}, -+ {R367_OFDM_FREQOFF1 ,0x00}, -+ {R367_OFDM_FREQOFF2 ,0x00}, -+ {R367_OFDM_FREQOFF3 ,0x00}, -+ {R367_OFDM_TIMOFF1 ,0x00}, -+ {R367_OFDM_TIMOFF2 ,0x00}, -+ {R367_OFDM_EPQ ,0x02}, -+ {R367_OFDM_EPQAUTO ,0x01}, -+ {R367_OFDM_SYR_UPDATE ,0xf5}, -+ {R367_OFDM_CHPFREE ,0x00}, -+ {R367_OFDM_PPM_STATE_MAC ,0x23}, -+ {R367_OFDM_INR_THRESHOLD ,0xff}, -+ {R367_OFDM_EPQ_TPS_ID_CELL ,0xf9}, -+ {R367_OFDM_EPQ_CFG ,0x00}, -+ {R367_OFDM_EPQ_STATUS ,0x01}, -+ {R367_OFDM_AUTORELOCK ,0x81}, -+ {R367_OFDM_BER_THR_VMSB ,0x00}, -+ {R367_OFDM_BER_THR_MSB ,0x00}, -+ {R367_OFDM_BER_THR_LSB ,0x00}, -+ {R367_OFDM_CCD ,0x83}, -+ {R367_OFDM_SPECTR_CFG ,0x00}, -+ {R367_OFDM_CHC_DUMMY ,0x18}, -+ {R367_OFDM_INC_CTL ,0x88}, -+ {R367_OFDM_INCTHRES_COR1 ,0xb4}, -+ {R367_OFDM_INCTHRES_COR2 ,0x96}, -+ {R367_OFDM_INCTHRES_DET1 ,0x0e}, -+ {R367_OFDM_INCTHRES_DET2 ,0x11}, -+ {R367_OFDM_IIR_CELLNB ,0x8d}, -+ {R367_OFDM_IIRCX_COEFF1_MSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF1_LSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF2_MSB ,0x09}, -+ {R367_OFDM_IIRCX_COEFF2_LSB ,0x18}, -+ {R367_OFDM_IIRCX_COEFF3_MSB ,0x14}, -+ {R367_OFDM_IIRCX_COEFF3_LSB ,0x9c}, -+ {R367_OFDM_IIRCX_COEFF4_MSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF4_LSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF5_MSB ,0x36}, -+ {R367_OFDM_IIRCX_COEFF5_LSB ,0x42}, -+ {R367_OFDM_FEPATH_CFG ,0x00}, -+ {R367_OFDM_PMC1_FUNC ,0x65}, -+ {R367_OFDM_PMC1_FOR ,0x00}, -+ {R367_OFDM_PMC2_FUNC ,0x00}, -+ {R367_OFDM_STATUS_ERR_DA ,0xe0}, -+ {R367_OFDM_DIG_AGC_R ,0xfe}, -+ {R367_OFDM_COMAGC_TARMSB ,0x0b}, -+ {R367_OFDM_COM_AGC_TAR_ENMODE ,0x41}, -+ {R367_OFDM_COM_AGC_CFG ,0x3e}, -+ {R367_OFDM_COM_AGC_GAIN1 ,0x39}, -+ {R367_OFDM_AUT_AGC_TARGETMSB ,0x0b}, -+ {R367_OFDM_LOCK_DET_MSB ,0x01}, -+ {R367_OFDM_AGCTAR_LOCK_LSBS ,0x40}, -+ {R367_OFDM_AUT_GAIN_EN ,0xf4}, -+ {R367_OFDM_AUT_CFG ,0xf0}, -+ {R367_OFDM_LOCKN ,0x23}, -+ {R367_OFDM_INT_X_3 ,0x00}, -+ {R367_OFDM_INT_X_2 ,0x03}, -+ {R367_OFDM_INT_X_1 ,0x8d}, -+ {R367_OFDM_INT_X_0 ,0xa0}, -+ {R367_OFDM_MIN_ERRX_MSB ,0x00}, -+ {R367_OFDM_COR_CTL ,0x00}, -+ {R367_OFDM_COR_STAT ,0xf6}, -+ {R367_OFDM_COR_INTEN ,0x00}, -+ {R367_OFDM_COR_INTSTAT ,0x3f}, -+ {R367_OFDM_COR_MODEGUARD ,0x03}, -+ {R367_OFDM_AGC_CTL ,0x08}, -+ {R367_OFDM_AGC_MANUAL1 ,0x00}, -+ {R367_OFDM_AGC_MANUAL2 ,0x00}, -+ {R367_OFDM_AGC_TARG ,0x16}, -+ {R367_OFDM_AGC_GAIN1 ,0x53}, -+ {R367_OFDM_AGC_GAIN2 ,0x1d}, -+ {R367_OFDM_RESERVED_1 ,0x00}, -+ {R367_OFDM_RESERVED_2 ,0x00}, -+ {R367_OFDM_RESERVED_3 ,0x00}, -+ {R367_OFDM_CAS_CTL ,0x44}, -+ {R367_OFDM_CAS_FREQ ,0xb3}, -+ {R367_OFDM_CAS_DAGCGAIN ,0x12}, -+ {R367_OFDM_SYR_CTL ,0x04}, -+ {R367_OFDM_SYR_STAT ,0x10}, -+ {R367_OFDM_SYR_NCO1 ,0x00}, -+ {R367_OFDM_SYR_NCO2 ,0x00}, -+ {R367_OFDM_SYR_OFFSET1 ,0x00}, -+ {R367_OFDM_SYR_OFFSET2 ,0x00}, -+ {R367_OFDM_FFT_CTL ,0x00}, -+ {R367_OFDM_SCR_CTL ,0x70}, -+ {R367_OFDM_PPM_CTL1 ,0xf8}, -+ {R367_OFDM_TRL_CTL ,0xac}, -+ {R367_OFDM_TRL_NOMRATE1 ,0x1e}, -+ {R367_OFDM_TRL_NOMRATE2 ,0x58}, -+ {R367_OFDM_TRL_TIME1 ,0x1d}, -+ {R367_OFDM_TRL_TIME2 ,0xfc}, -+ {R367_OFDM_CRL_CTL ,0x24}, -+ {R367_OFDM_CRL_FREQ1 ,0xad}, -+ {R367_OFDM_CRL_FREQ2 ,0x9d}, -+ {R367_OFDM_CRL_FREQ3 ,0xff}, -+ {R367_OFDM_CHC_CTL ,0x01}, -+ {R367_OFDM_CHC_SNR ,0xf0}, -+ {R367_OFDM_BDI_CTL ,0x00}, -+ {R367_OFDM_DMP_CTL ,0x00}, -+ {R367_OFDM_TPS_RCVD1 ,0x30}, -+ {R367_OFDM_TPS_RCVD2 ,0x02}, -+ {R367_OFDM_TPS_RCVD3 ,0x01}, -+ {R367_OFDM_TPS_RCVD4 ,0x00}, -+ {R367_OFDM_TPS_ID_CELL1 ,0x00}, -+ {R367_OFDM_TPS_ID_CELL2 ,0x00}, -+ {R367_OFDM_TPS_RCVD5_SET1 ,0x02}, -+ {R367_OFDM_TPS_SET2 ,0x02}, -+ {R367_OFDM_TPS_SET3 ,0x01}, -+ {R367_OFDM_TPS_CTL ,0x00}, -+ {R367_OFDM_CTL_FFTOSNUM ,0x34}, -+ {R367_OFDM_TESTSELECT ,0x09}, -+ {R367_OFDM_MSC_REV ,0x0a}, -+ {R367_OFDM_PIR_CTL ,0x00}, -+ {R367_OFDM_SNR_CARRIER1 ,0xa1}, -+ {R367_OFDM_SNR_CARRIER2 ,0x9a}, -+ {R367_OFDM_PPM_CPAMP ,0x2c}, -+ {R367_OFDM_TSM_AP0 ,0x00}, -+ {R367_OFDM_TSM_AP1 ,0x00}, -+ {R367_OFDM_TSM_AP2 ,0x00}, -+ {R367_OFDM_TSM_AP3 ,0x00}, -+ {R367_OFDM_TSM_AP4 ,0x00}, -+ {R367_OFDM_TSM_AP5 ,0x00}, -+ {R367_OFDM_TSM_AP6 ,0x00}, -+ {R367_OFDM_TSM_AP7 ,0x00}, -+ //{R367_OFDM_TSTRES ,0x00}, -+ //{R367_OFDM_ANACTRL ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/ -+ //{R367_OFDM_TSTBUS ,0x00}, -+ //{R367_OFDM_TSTRATE ,0x00}, -+ {R367_OFDM_CONSTMODE ,0x01}, -+ {R367_OFDM_CONSTCARR1 ,0x00}, -+ {R367_OFDM_CONSTCARR2 ,0x00}, -+ {R367_OFDM_ICONSTEL ,0x0a}, -+ {R367_OFDM_QCONSTEL ,0x15}, -+ {R367_OFDM_TSTBISTRES0 ,0x00}, -+ {R367_OFDM_TSTBISTRES1 ,0x00}, -+ {R367_OFDM_TSTBISTRES2 ,0x28}, -+ {R367_OFDM_TSTBISTRES3 ,0x00}, -+ //{R367_OFDM_RF_AGC1 ,0xff}, -+ //{R367_OFDM_RF_AGC2 ,0x83}, -+ //{R367_OFDM_ANADIGCTRL ,0x19}, -+ //{R367_OFDM_PLLMDIV ,0x0c}, -+ //{R367_OFDM_PLLNDIV ,0x55}, -+ //{R367_OFDM_PLLSETUP ,0x18}, -+ //{R367_OFDM_DUAL_AD12 ,0x00}, -+ //{R367_OFDM_TSTBIST ,0x00}, -+ //{R367_OFDM_PAD_COMP_CTRL ,0x00}, -+ //{R367_OFDM_PAD_COMP_WR ,0x00}, -+ //{R367_OFDM_PAD_COMP_RD ,0xe0}, -+ {R367_OFDM_SYR_TARGET_FFTADJT_MSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00}, -+ {R367_OFDM_SYR_FLAG ,0x00}, -+ {R367_OFDM_CRL_TARGET1 ,0x00}, -+ {R367_OFDM_CRL_TARGET2 ,0x00}, -+ {R367_OFDM_CRL_TARGET3 ,0x00}, -+ {R367_OFDM_CRL_TARGET4 ,0x00}, -+ {R367_OFDM_CRL_FLAG ,0x00}, -+ {R367_OFDM_TRL_TARGET1 ,0x00}, -+ {R367_OFDM_TRL_TARGET2 ,0x00}, -+ {R367_OFDM_TRL_CHC ,0x00}, -+ {R367_OFDM_CHC_SNR_TARG ,0x00}, -+ {R367_OFDM_TOP_TRACK ,0x00}, -+ {R367_OFDM_TRACKER_FREE1 ,0x00}, -+ {R367_OFDM_ERROR_CRL1 ,0x00}, -+ {R367_OFDM_ERROR_CRL2 ,0x00}, -+ {R367_OFDM_ERROR_CRL3 ,0x00}, -+ {R367_OFDM_ERROR_CRL4 ,0x00}, -+ {R367_OFDM_DEC_NCO1 ,0x2c}, -+ {R367_OFDM_DEC_NCO2 ,0x0f}, -+ {R367_OFDM_DEC_NCO3 ,0x20}, -+ {R367_OFDM_SNR ,0xf1}, -+ {R367_OFDM_SYR_FFTADJ1 ,0x00}, -+ {R367_OFDM_SYR_FFTADJ2 ,0x00}, -+ {R367_OFDM_SYR_CHCADJ1 ,0x00}, -+ {R367_OFDM_SYR_CHCADJ2 ,0x00}, -+ {R367_OFDM_SYR_OFF ,0x00}, -+ {R367_OFDM_PPM_OFFSET1 ,0x00}, -+ {R367_OFDM_PPM_OFFSET2 ,0x03}, -+ {R367_OFDM_TRACKER_FREE2 ,0x00}, -+ {R367_OFDM_DEBG_LT10 ,0x00}, -+ {R367_OFDM_DEBG_LT11 ,0x00}, -+ {R367_OFDM_DEBG_LT12 ,0x00}, -+ {R367_OFDM_DEBG_LT13 ,0x00}, -+ {R367_OFDM_DEBG_LT14 ,0x00}, -+ {R367_OFDM_DEBG_LT15 ,0x00}, -+ {R367_OFDM_DEBG_LT16 ,0x00}, -+ {R367_OFDM_DEBG_LT17 ,0x00}, -+ {R367_OFDM_DEBG_LT18 ,0x00}, -+ {R367_OFDM_DEBG_LT19 ,0x00}, -+ {R367_OFDM_DEBG_LT1A ,0x00}, -+ {R367_OFDM_DEBG_LT1B ,0x00}, -+ {R367_OFDM_DEBG_LT1C ,0x00}, -+ {R367_OFDM_DEBG_LT1D ,0x00}, -+ {R367_OFDM_DEBG_LT1E ,0x00}, -+ {R367_OFDM_DEBG_LT1F ,0x00}, -+ {R367_OFDM_RCCFGH ,0x00}, -+ {R367_OFDM_RCCFGM ,0x00}, -+ {R367_OFDM_RCCFGL ,0x00}, -+ {R367_OFDM_RCINSDELH ,0x00}, -+ {R367_OFDM_RCINSDELM ,0x00}, -+ {R367_OFDM_RCINSDELL ,0x00}, -+ {R367_OFDM_RCSTATUS ,0x00}, -+ {R367_OFDM_RCSPEED ,0x6f}, -+ {R367_OFDM_RCDEBUGM ,0xe7}, -+ {R367_OFDM_RCDEBUGL ,0x9b}, -+ {R367_OFDM_RCOBSCFG ,0x00}, -+ {R367_OFDM_RCOBSM ,0x00}, -+ {R367_OFDM_RCOBSL ,0x00}, -+ {R367_OFDM_RCFECSPY ,0x00}, -+ {R367_OFDM_RCFSPYCFG ,0x00}, -+ {R367_OFDM_RCFSPYDATA ,0x00}, -+ {R367_OFDM_RCFSPYOUT ,0x00}, -+ {R367_OFDM_RCFSTATUS ,0x00}, -+ {R367_OFDM_RCFGOODPACK ,0x00}, -+ {R367_OFDM_RCFPACKCNT ,0x00}, -+ {R367_OFDM_RCFSPYMISC ,0x00}, -+ {R367_OFDM_RCFBERCPT4 ,0x00}, -+ {R367_OFDM_RCFBERCPT3 ,0x00}, -+ {R367_OFDM_RCFBERCPT2 ,0x00}, -+ {R367_OFDM_RCFBERCPT1 ,0x00}, -+ {R367_OFDM_RCFBERCPT0 ,0x00}, -+ {R367_OFDM_RCFBERERR2 ,0x00}, -+ {R367_OFDM_RCFBERERR1 ,0x00}, -+ {R367_OFDM_RCFBERERR0 ,0x00}, -+ {R367_OFDM_RCFSTATESM ,0x00}, -+ {R367_OFDM_RCFSTATESL ,0x00}, -+ {R367_OFDM_RCFSPYBER ,0x00}, -+ {R367_OFDM_RCFSPYDISTM ,0x00}, -+ {R367_OFDM_RCFSPYDISTL ,0x00}, -+ {R367_OFDM_RCFSPYOBS7 ,0x00}, -+ {R367_OFDM_RCFSPYOBS6 ,0x00}, -+ {R367_OFDM_RCFSPYOBS5 ,0x00}, -+ {R367_OFDM_RCFSPYOBS4 ,0x00}, -+ {R367_OFDM_RCFSPYOBS3 ,0x00}, -+ {R367_OFDM_RCFSPYOBS2 ,0x00}, -+ {R367_OFDM_RCFSPYOBS1 ,0x00}, -+ {R367_OFDM_RCFSPYOBS0 ,0x00}, -+ //{R367_OFDM_TSGENERAL ,0x00}, -+ //{R367_OFDM_RC1SPEED ,0x6f}, -+ //{R367_OFDM_TSGSTATUS ,0x18}, -+ {R367_OFDM_FECM ,0x01}, -+ {R367_OFDM_VTH12 ,0xff}, -+ {R367_OFDM_VTH23 ,0xa1}, -+ {R367_OFDM_VTH34 ,0x64}, -+ {R367_OFDM_VTH56 ,0x40}, -+ {R367_OFDM_VTH67 ,0x00}, -+ {R367_OFDM_VTH78 ,0x2c}, -+ {R367_OFDM_VITCURPUN ,0x12}, -+ {R367_OFDM_VERROR ,0x01}, -+ {R367_OFDM_PRVIT ,0x3f}, -+ {R367_OFDM_VAVSRVIT ,0x00}, -+ {R367_OFDM_VSTATUSVIT ,0xbd}, -+ {R367_OFDM_VTHINUSE ,0xa1}, -+ {R367_OFDM_KDIV12 ,0x20}, -+ {R367_OFDM_KDIV23 ,0x40}, -+ {R367_OFDM_KDIV34 ,0x20}, -+ {R367_OFDM_KDIV56 ,0x30}, -+ {R367_OFDM_KDIV67 ,0x00}, -+ {R367_OFDM_KDIV78 ,0x30}, -+ {R367_OFDM_SIGPOWER ,0x54}, -+ {R367_OFDM_DEMAPVIT ,0x40}, -+ {R367_OFDM_VITSCALE ,0x00}, -+ {R367_OFDM_FFEC1PRG ,0x00}, -+ {R367_OFDM_FVITCURPUN ,0x12}, -+ {R367_OFDM_FVERROR ,0x01}, -+ {R367_OFDM_FVSTATUSVIT ,0xbd}, -+ {R367_OFDM_DEBUG_LT1 ,0x00}, -+ {R367_OFDM_DEBUG_LT2 ,0x00}, -+ {R367_OFDM_DEBUG_LT3 ,0x00}, -+ {R367_OFDM_TSTSFMET ,0x00}, -+ {R367_OFDM_SELOUT ,0x00}, -+ {R367_OFDM_TSYNC ,0x00}, -+ {R367_OFDM_TSTERR ,0x00}, -+ {R367_OFDM_TSFSYNC ,0x00}, -+ {R367_OFDM_TSTSFERR ,0x00}, -+ {R367_OFDM_TSTTSSF1 ,0x01}, -+ {R367_OFDM_TSTTSSF2 ,0x1f}, -+ {R367_OFDM_TSTTSSF3 ,0x00}, -+ {R367_OFDM_TSTTS1 ,0x00}, -+ {R367_OFDM_TSTTS2 ,0x1f}, -+ {R367_OFDM_TSTTS3 ,0x01}, -+ {R367_OFDM_TSTTS4 ,0x00}, -+ {R367_OFDM_TSTTSRC ,0x00}, -+ {R367_OFDM_TSTTSRS ,0x00}, -+ {R367_OFDM_TSSTATEM ,0xb0}, -+ {R367_OFDM_TSSTATEL ,0x40}, -+ {R367_OFDM_TSCFGH ,0x80}, -+ {R367_OFDM_TSCFGM ,0x00}, -+ {R367_OFDM_TSCFGL ,0x20}, -+ {R367_OFDM_TSSYNC ,0x00}, -+ {R367_OFDM_TSINSDELH ,0x00}, -+ {R367_OFDM_TSINSDELM ,0x00}, -+ {R367_OFDM_TSINSDELL ,0x00}, -+ {R367_OFDM_TSDIVN ,0x03}, -+ {R367_OFDM_TSDIVPM ,0x00}, -+ {R367_OFDM_TSDIVPL ,0x00}, -+ {R367_OFDM_TSDIVQM ,0x00}, -+ {R367_OFDM_TSDIVQL ,0x00}, -+ {R367_OFDM_TSDILSTKM ,0x00}, -+ {R367_OFDM_TSDILSTKL ,0x00}, -+ {R367_OFDM_TSSPEED ,0x6f}, -+ {R367_OFDM_TSSTATUS ,0x81}, -+ {R367_OFDM_TSSTATUS2 ,0x6a}, -+ {R367_OFDM_TSBITRATEM ,0x0f}, -+ {R367_OFDM_TSBITRATEL ,0xc6}, -+ {R367_OFDM_TSPACKLENM ,0x00}, -+ {R367_OFDM_TSPACKLENL ,0xfc}, -+ {R367_OFDM_TSBLOCLENM ,0x0a}, -+ {R367_OFDM_TSBLOCLENL ,0x80}, -+ {R367_OFDM_TSDLYH ,0x90}, -+ {R367_OFDM_TSDLYM ,0x68}, -+ {R367_OFDM_TSDLYL ,0x01}, -+ {R367_OFDM_TSNPDAV ,0x00}, -+ {R367_OFDM_TSBUFSTATH ,0x00}, -+ {R367_OFDM_TSBUFSTATM ,0x00}, -+ {R367_OFDM_TSBUFSTATL ,0x00}, -+ {R367_OFDM_TSDEBUGM ,0xcf}, -+ {R367_OFDM_TSDEBUGL ,0x1e}, -+ {R367_OFDM_TSDLYSETH ,0x00}, -+ {R367_OFDM_TSDLYSETM ,0x68}, -+ {R367_OFDM_TSDLYSETL ,0x00}, -+ {R367_OFDM_TSOBSCFG ,0x00}, -+ {R367_OFDM_TSOBSM ,0x47}, -+ {R367_OFDM_TSOBSL ,0x1f}, -+ {R367_OFDM_ERRCTRL1 ,0x95}, -+ {R367_OFDM_ERRCNT1H ,0x80}, -+ {R367_OFDM_ERRCNT1M ,0x00}, -+ {R367_OFDM_ERRCNT1L ,0x00}, -+ {R367_OFDM_ERRCTRL2 ,0x95}, -+ {R367_OFDM_ERRCNT2H ,0x00}, -+ {R367_OFDM_ERRCNT2M ,0x00}, -+ {R367_OFDM_ERRCNT2L ,0x00}, -+ {R367_OFDM_FECSPY ,0x88}, -+ {R367_OFDM_FSPYCFG ,0x2c}, -+ {R367_OFDM_FSPYDATA ,0x3a}, -+ {R367_OFDM_FSPYOUT ,0x06}, -+ {R367_OFDM_FSTATUS ,0x61}, -+ {R367_OFDM_FGOODPACK ,0xff}, -+ {R367_OFDM_FPACKCNT ,0xff}, -+ {R367_OFDM_FSPYMISC ,0x66}, -+ {R367_OFDM_FBERCPT4 ,0x00}, -+ {R367_OFDM_FBERCPT3 ,0x00}, -+ {R367_OFDM_FBERCPT2 ,0x36}, -+ {R367_OFDM_FBERCPT1 ,0x36}, -+ {R367_OFDM_FBERCPT0 ,0x14}, -+ {R367_OFDM_FBERERR2 ,0x00}, -+ {R367_OFDM_FBERERR1 ,0x03}, -+ {R367_OFDM_FBERERR0 ,0x28}, -+ {R367_OFDM_FSTATESM ,0x00}, -+ {R367_OFDM_FSTATESL ,0x02}, -+ {R367_OFDM_FSPYBER ,0x00}, -+ {R367_OFDM_FSPYDISTM ,0x01}, -+ {R367_OFDM_FSPYDISTL ,0x9f}, -+ {R367_OFDM_FSPYOBS7 ,0xc9}, -+ {R367_OFDM_FSPYOBS6 ,0x99}, -+ {R367_OFDM_FSPYOBS5 ,0x08}, -+ {R367_OFDM_FSPYOBS4 ,0xec}, -+ {R367_OFDM_FSPYOBS3 ,0x01}, -+ {R367_OFDM_FSPYOBS2 ,0x0f}, -+ {R367_OFDM_FSPYOBS1 ,0xf5}, -+ {R367_OFDM_FSPYOBS0 ,0x08}, -+ {R367_OFDM_SFDEMAP ,0x40}, -+ {R367_OFDM_SFERROR ,0x00}, -+ {R367_OFDM_SFAVSR ,0x30}, -+ {R367_OFDM_SFECSTATUS ,0xcc}, -+ {R367_OFDM_SFKDIV12 ,0x20}, -+ {R367_OFDM_SFKDIV23 ,0x40}, -+ {R367_OFDM_SFKDIV34 ,0x20}, -+ {R367_OFDM_SFKDIV56 ,0x20}, -+ {R367_OFDM_SFKDIV67 ,0x00}, -+ {R367_OFDM_SFKDIV78 ,0x20}, -+ {R367_OFDM_SFDILSTKM ,0x00}, -+ {R367_OFDM_SFDILSTKL ,0x00}, -+ {R367_OFDM_SFSTATUS ,0xb5}, -+ {R367_OFDM_SFDLYH ,0x90}, -+ {R367_OFDM_SFDLYM ,0x60}, -+ {R367_OFDM_SFDLYL ,0x01}, -+ {R367_OFDM_SFDLYSETH ,0xc0}, -+ {R367_OFDM_SFDLYSETM ,0x60}, -+ {R367_OFDM_SFDLYSETL ,0x00}, -+ {R367_OFDM_SFOBSCFG ,0x00}, -+ {R367_OFDM_SFOBSM ,0x47}, -+ {R367_OFDM_SFOBSL ,0x05}, -+ {R367_OFDM_SFECINFO ,0x40}, -+ {R367_OFDM_SFERRCTRL ,0x74}, -+ {R367_OFDM_SFERRCNTH ,0x80}, -+ {R367_OFDM_SFERRCNTM ,0x00}, -+ {R367_OFDM_SFERRCNTL ,0x00}, -+ {R367_OFDM_SYMBRATEM ,0x2f}, -+ {R367_OFDM_SYMBRATEL ,0x50}, -+ {R367_OFDM_SYMBSTATUS ,0x7f}, -+ {R367_OFDM_SYMBCFG ,0x00}, -+ {R367_OFDM_SYMBFIFOM ,0xf4}, -+ {R367_OFDM_SYMBFIFOL ,0x0d}, -+ {R367_OFDM_SYMBOFFSM ,0xf0}, -+ {R367_OFDM_SYMBOFFSL ,0x2d}, -+ //{R367_OFDM_DEBUG_LT4 ,0x00}, -+ //{R367_OFDM_DEBUG_LT5 ,0x00}, -+ //{R367_OFDM_DEBUG_LT6 ,0x00}, -+ //{R367_OFDM_DEBUG_LT7 ,0x00}, -+ //{R367_OFDM_DEBUG_LT8 ,0x00}, -+ //{R367_OFDM_DEBUG_LT9 ,0x00}, -+ { 0x0000, 0x00 } // EOT -+}; -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = -+ {.addr = adr, .flags = 0, .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ printk("stv0367: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+#if 0 -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ printk("stv0367: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+#endif -+ -+static int writereg(struct stv_state *state, u16 reg, u8 dat) -+{ -+ u8 mm[3] = { (reg >> 8), reg & 0xff, dat }; -+ -+ return i2c_write(state->i2c, state->adr, mm, 3); -+} -+ -+static int readreg(struct stv_state *state, u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = state->adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1}}; -+ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int readregs(struct stv_state *state, u16 reg, u8 *val, int count) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = state->adr, .flags = I2C_M_RD, -+ .buf = val, .len = count}}; -+ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int write_init_table(struct stv_state *state, struct init_table *tab) -+{ -+ while (1) { -+ if (!tab->adr) -+ break; -+ if (writereg(state, tab->adr, tab->data) < 0) -+ return -1; -+ tab++; -+ } -+ return 0; -+} -+ -+static int qam_set_modulation(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ switch(state->modulation) { -+ case QAM_16: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x64); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a); -+ break; -+ case QAM_32: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ case QAM_64: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82); /* Set digital AGC reference */ -+ if(state->symbol_rate>4500000) -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); -+ } -+ else -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0x99); -+ break; -+ case QAM_128: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x76); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1); -+ if(state->symbol_rate>4500000) // 45000000 -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); -+ } -+ else -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ case QAM_256: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ if(state->symbol_rate>4500000) // 45000000 -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ } -+ else -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ default: -+ stat = -EINVAL; -+ break; -+ } -+ return stat; -+} -+ -+ -+static int QAM_SetSymbolRate(struct stv_state *state) -+{ -+ int status = 0; -+ u32 sr = state->symbol_rate; -+ u32 Corr = 0; -+ u32 Temp, Temp1, AdpClk; -+ -+ switch(state->modulation) { -+ default: -+ case QAM_16: Corr = 1032; break; -+ case QAM_32: Corr = 954; break; -+ case QAM_64: Corr = 983; break; -+ case QAM_128: Corr = 957; break; -+ case QAM_256: Corr = 948; break; -+ } -+ -+ // Transfer ration -+ Temp = (256*sr) / state->adc_clock; -+ writereg(state, R367_QAM_EQU_CRL_TFR,(Temp)); -+ -+ /* Symbol rate and SRC gain calculation */ -+ AdpClk = (state->master_clock) / 2000; /* TRL works at half the system clock */ -+ -+ Temp = state->symbol_rate; -+ Temp1 = sr; -+ -+ if(sr < 2097152) /* 2097152 = 2^21 */ -+ { -+ Temp = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8; -+ Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000; -+ } -+ else if(sr < 4194304) /* 4194304 = 2**22 */ -+ { -+ Temp = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16; -+ Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000; -+ } -+ else if(sr < 8388608) /* 8388608 = 2**23 */ -+ { -+ Temp = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32; -+ Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000; -+ } -+ else -+ { -+ Temp = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64; -+ Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000; -+ } -+ -+ ///* Filters' coefficients are calculated and written into registers only if the filters are enabled */ -+ //if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init! -+ //{ -+ // FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate); -+ //} -+ ///* AllPass filter is never used on this IC */ -+ //ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init! -+ -+ writereg(state, R367_QAM_SRC_NCO_LL,(Temp)); -+ writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8)); -+ writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16)); -+ writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24)); -+ -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1)); -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8)); -+ return status; -+} -+ -+ -+static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency) -+{ -+ int status = 0; -+ u32 Sampled_IF; -+ -+ do { -+ //if (DerotFrequency < 1000000) -+ // DerotFrequency = state->adc_clock/4; /* ZIF operation */ -+ if (DerotFrequency > state->adc_clock) -+ DerotFrequency = DerotFrequency - state->adc_clock; // User Alias -+ -+ Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256; -+ if(Sampled_IF > 8388607) -+ Sampled_IF = 8388607; -+ -+ writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF)); -+ writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8)); -+ writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16)); -+ } while(0); -+ -+ return status; -+} -+ -+ -+ -+static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u32 AGCTimeOut = 25; -+ u32 TRLTimeOut = 100000000 / state->symbol_rate; -+ u32 CRLSymbols = 0; -+ u32 EQLTimeOut = 100; -+ u32 SearchRange = state->symbol_rate / 25; -+ u32 CRLTimeOut; -+ u8 Temp; -+ -+ if( state->demod_state != QAMSet ) { -+ writereg(state, R367_DEBUG_LT4,0x00); -+ writereg(state, R367_DEBUG_LT5,0x01); -+ writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1 -+ writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2 -+ writereg(state, R367_DEBUG_LT8,0x00); -+ writereg(state, R367_DEBUG_LT9,0x00); -+ -+ // Tuner Setup -+ writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */ -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */ -+ writereg(state, R367_TOPCTRL,0x10); // Set QAM -+ -+ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,232); -+ writereg(state, R367_PLLSETUP,0x18); /* ADC clock is equal to system clock */ -+ -+ msleep(50); -+ writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */ -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ -+ state->demod_state = QAMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ qam_set_modulation(state); -+ QAM_SetSymbolRate(state); -+ -+ // Will make problems on low symbol rates ( < 2500000 ) -+ -+ switch(state->modulation) { -+ default: -+ case QAM_16: CRLSymbols = 150000; break; -+ case QAM_32: CRLSymbols = 250000; break; -+ case QAM_64: CRLSymbols = 200000; break; -+ case QAM_128: CRLSymbols = 250000; break; -+ case QAM_256: CRLSymbols = 250000; break; -+ } -+ -+ CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000); -+ CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate; -+ if( CRLTimeOut < 50 ) CRLTimeOut = 50; -+ -+ state->m_FECTimeOut = 20; -+ state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut; -+ state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut; -+ -+ // QAM_AGC_ACCUMRSTSEL = 0; -+ readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL); -+ writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F); -+ -+ // QAM_MODULUSMAP_EN = 0 -+ readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40); -+ -+ // QAM_SWEEP_EN = 0 -+ readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08); -+ -+ QAM_SetDerotFrequency(state, IntermediateFrequency); -+ -+ // Release TRL -+ writereg(state, R367_QAM_CTRL_1,0x00); -+ -+ state->IF = IntermediateFrequency; -+ state->demod_state = QAMStarted; -+ -+ return status; -+} -+ -+static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u8 GAIN_SRC1; -+ u32 Derot; -+ u8 SYR_CTL; -+ u8 tmp1; -+ u8 tmp2; -+ -+ if ( state->demod_state != OFDMSet ) { -+ // QAM Disable -+ writereg(state, R367_DEBUG_LT4, 0x00); -+ writereg(state, R367_DEBUG_LT5, 0x00); -+ writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1 -+ writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2 -+ writereg(state, R367_DEBUG_LT8, 0x00); -+ writereg(state, R367_DEBUG_LT9, 0x00); -+ -+ // Tuner Setup -+ writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */ -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ -+ writereg(state, R367_TOPCTRL, 0x00); // Set OFDM -+ -+ writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV, 8); -+ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ -+ -+ msleep(50); -+ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ -+ -+ state->master_clock = 54000000; -+ state->adc_clock = 54000000; -+ -+ state->demod_state = OFDMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ // Set inversion in GAIN_SRC1 (fixed from init) -+ // is in GAIN_SRC1, see below -+ -+ GAIN_SRC1 = 0xA0; -+ // Bandwidth -+ -+ // Fixed values for 54 MHz -+ switch(state->bandwidth) { -+ case 0: -+ case 8000000: -+ // Normrate = 44384; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x56); -+ // Gain SRC = 2774 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0xD6); -+ break; -+ case 7000000: -+ // Normrate = 38836; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B); -+ // Gain SRC = 2427 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0x7B); -+ break; -+ case 6000000: -+ // Normrate = 33288; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0x04); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x41); -+ // Gain SRC = 2080 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0x20); -+ break; -+ default: -+ return -EINVAL; -+ break; -+ } -+ -+ Derot = ((IntermediateFrequency / 1000) * 65536) / (state->master_clock / 1000); -+ -+ writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8)); -+ writereg(state, R367_OFDM_INC_DEROT2,(Derot)); -+ -+ readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL); -+ SYR_CTL &= ~0x78; -+ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // EchoPos = 0 -+ -+ -+ writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3 -+ SYR_CTL &= 0x01; -+ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // SYR_TR_DIS = 0 -+ -+ msleep(5); -+ -+ writereg(state, R367_OFDM_COR_CTL,0x20); // Start core -+ -+ // -- Begin M.V. -+ // Reset FEC and Read Solomon -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08); -+ writereg(state, R367_TSGENERAL,tmp2 | 0x01); -+ // -- End M.V. -+ -+ state->m_SignalTimeOut = 200; -+ state->IF = IntermediateFrequency; -+ state->demod_state = OFDMStarted; -+ state->m_DemodTimeOut = 0; -+ state->m_FECTimeOut = 0; -+ state->m_TSTimeOut = 0; -+ -+ return status; -+} -+ -+#if 0 -+static int Stop(struct stv_state *state) -+{ -+ int status = 0; -+ -+ switch(state->demod_state) -+ { -+ case QAMStarted: -+ status = writereg(state, R367_QAM_CTRL_1,0x06); -+ state->demod_state = QAMSet; -+ break; -+ case OFDMStarted: -+ status = writereg(state, R367_OFDM_COR_CTL,0x00); -+ state->demod_state = OFDMSet; -+ break; -+ default: -+ break; -+ } -+ return status; -+} -+#endif -+ -+static s32 Log10x100(u32 x) -+{ -+ static u32 LookupTable[100] = { -+ 101157945, 103514217, 105925373, 108392691, 110917482, -+ 113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5 -+ 127350308, 130316678, 133352143, 136458314, 139636836, -+ 142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5 -+ 160324539, 164058977, 167880402, 171790839, 175792361, -+ 179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5 -+ 201836636, 206538016, 211348904, 216271852, 221309471, -+ 226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5 -+ 254097271, 260015956, 266072506, 272270131, 278612117, -+ 285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5 -+ 319889511, 327340695, 334965439, 342767787, 350751874, -+ 358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5 -+ 402717034, 412097519, 421696503, 431519077, 441570447, -+ 451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5 -+ 506990708, 518800039, 530884444, 543250331, 555904257, -+ 568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5 -+ 638263486, 653130553, 668343918, 683911647, 699841996, -+ 716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5 -+ 803526122, 822242650, 841395142, 860993752, 881048873, -+ 901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5 -+ }; -+ s32 y; -+ int i; -+ -+ if (x == 0) -+ return 0; -+ y = 800; -+ if (x >= 1000000000) { -+ x /= 10; -+ y += 100; -+ } -+ -+ while (x < 100000000) { -+ x *= 10; -+ y -= 100; -+ } -+ i = 0; -+ while (i < 100 && x > LookupTable[i]) -+ i += 1; -+ y += i; -+ return y; -+} -+ -+static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) -+{ -+ u32 RegValAvg = 0; -+ u8 RegVal[2]; -+ int status = 0, i; -+ -+ *pSignalToNoise = 0; -+ for (i = 0; i < 10; i += 1 ) { -+ readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2); -+ RegValAvg += RegVal[0] + 256 * RegVal[1]; -+ } -+ if (RegValAvg != 0) { -+ s32 Power = 1; -+ switch(state->modulation) { -+ case QAM_16: -+ Power = 20480; -+ break; -+ case QAM_32: -+ Power = 23040; -+ break; -+ case QAM_64: -+ Power = 21504; -+ break; -+ case QAM_128: -+ Power = 23616; -+ break; -+ case QAM_256: -+ Power = 21760; -+ break; -+ default: -+ break; -+ } -+ *pSignalToNoise = Log10x100((Power * 320) / RegValAvg); -+ } else { -+ *pSignalToNoise = 380; -+ } -+ return status; -+} -+ -+static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) -+{ -+ u8 CHC_SNR = 0; -+ -+ int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR); -+ if (status >= 0) { -+ // Note: very unclear documentation on this. -+ // Datasheet states snr = CHC_SNR/4 dB -> way to high values! -+ // Software snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values -+ // Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367 -+ // 361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best -+ *pSignalToNoise = ( (s32)CHC_SNR * 10) / 8; -+ } -+ //printk("SNR %d\n", *pSignalToNoise); -+ return status; -+} -+ -+#if 0 -+static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ *pQuality = 100; -+ return 0; -+}; -+ -+static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ static s32 QE_SN[] = { -+ 51, // QPSK 1/2 -+ 69, // QPSK 2/3 -+ 79, // QPSK 3/4 -+ 89, // QPSK 5/6 -+ 97, // QPSK 7/8 -+ 108, // 16-QAM 1/2 -+ 131, // 16-QAM 2/3 -+ 146, // 16-QAM 3/4 -+ 156, // 16-QAM 5/6 -+ 160, // 16-QAM 7/8 -+ 165, // 64-QAM 1/2 -+ 187, // 64-QAM 2/3 -+ 202, // 64-QAM 3/4 -+ 216, // 64-QAM 5/6 -+ 225, // 64-QAM 7/8 -+ }; -+ u8 TPS_Received[2]; -+ int Constellation; -+ int CodeRate; -+ s32 SignalToNoiseRel, BERQuality; -+ -+ *pQuality = 0; -+ readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received)); -+ Constellation = TPS_Received[0] & 0x03; -+ CodeRate = TPS_Received[1] & 0x07; -+ -+ if( Constellation > 2 || CodeRate > 5 ) -+ return -1; -+ SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate]; -+ BERQuality = 100; -+ -+ if( SignalToNoiseRel < -70 ) -+ *pQuality = 0; -+ else if( SignalToNoiseRel < 30 ) { -+ *pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100; -+ } else -+ *pQuality = BERQuality; -+ return 0; -+}; -+ -+static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise) -+{ -+ s32 SignalToNoiseRel = 0; -+ s32 Quality = 0; -+ s32 BERQuality = 100; -+ -+ switch(state->modulation) { -+ case QAM_16: SignalToNoiseRel = SignalToNoise - 200 ; break; -+ case QAM_32: SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig -+ case QAM_64: SignalToNoiseRel = SignalToNoise - 260 ; break; -+ case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break; -+ case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break; -+ } -+ -+ if( SignalToNoiseRel < -70 ) Quality = 0; -+ else if( SignalToNoiseRel < 30 ) -+ { -+ Quality = ((SignalToNoiseRel + 70) * BERQuality)/100; -+ } -+ else -+ Quality = BERQuality; -+ -+ return Quality; -+} -+ -+static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ *pQuality = 0; -+ switch(state->demod_state) -+ { -+ case QAMStarted: -+ *pQuality = DVBCQuality(state, SignalToNoise); -+ break; -+ case OFDMStarted: -+ return DVBT_GetQuality(state, SignalToNoise, pQuality); -+ } -+ return 0; -+}; -+#endif -+ -+static int attach_init(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ stat = readreg(state, R367_ID, &state->ID); -+ if ( stat < 0 || state->ID != 0x60 ) -+ return -ENODEV; -+ printk("stv0367 found\n"); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ write_init_table(state, base_init); -+ write_init_table(state, qam_init); -+ -+ writereg(state, R367_TOPCTRL, 0x00); -+ write_init_table(state, ofdm_init); -+ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x2A); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); -+ writereg(state, R367_OFDM_INC_DEROT1, 0x55); -+ writereg(state, R367_OFDM_INC_DEROT2, 0x55); -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); -+ writereg(state, R367_OFDM_FEPATH_CFG, 0x0); -+ -+ // OFDM TS Setup -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ writereg(state, R367_OFDM_TSCFGM, 0xC0); -+ writereg(state, R367_OFDM_TSCFGL, 0x20); -+ writereg(state, R367_OFDM_TSSPEED, 0x40); // Fixed at 54 MHz -+ //writereg(state, R367_TSTBUS, 0x80); // Invert CLK -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x71); -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ -+ // Also needed for QAM -+ writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup -+ -+ writereg(state, R367_OFDM_AGCCTRL1, 0x8A); // -+ -+ // QAM TS setup, note exact format also depends on descrambler settings -+ writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial -+ // writereg(state, R367_QAM_OUTFORMAT_1, 0x00); // -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ -+ -+ if( state->master_clock == 58000000 ) { -+ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,232); -+ } else { -+ writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,8); -+ } -+ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ -+ -+ // Tuner setup -+ writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */ -+ writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */ -+ writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */ -+ writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */ -+ -+ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ -+ -+ writereg(state, R367_I2CRPT, state->I2CRPT); -+ state->demod_state = QAMSet; -+ return stat; -+} -+ -+#ifdef USE_API3 -+static void c_release(struct dvb_frontend* fe) -+#else -+static void release(struct dvb_frontend* fe) -+#endif -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ printk("%s\n", __FUNCTION__); -+ kfree(state); -+} -+ -+#ifdef USE_API3 -+static int c_init (struct dvb_frontend *fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ -+ if (mutex_trylock(&state->ctlock)==0) -+ return -EBUSY; -+ state->omode = OM_DVBC; -+ return 0; -+} -+ -+static int c_sleep(struct dvb_frontend* fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ -+ mutex_unlock(&state->ctlock); -+ return 0; -+} -+#endif -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 i2crpt = state->I2CRPT & ~0x80; -+ -+ if (enable) -+ i2crpt |= 0x80; -+ if (writereg(state, R367_I2CRPT, i2crpt) < 0) -+ return -1; -+ state->I2CRPT = i2crpt; -+ return 0; -+} -+ -+#if 0 -+static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ return DVBFE_ALGO_SEARCH_AGAIN; -+} -+#endif -+ -+#if 0 -+int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -+int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -+#endif -+ -+static int ofdm_lock(struct stv_state *state) -+{ -+ int status = 0; -+ u8 OFDM_Status; -+ s32 DemodTimeOut = 10; -+ s32 FECTimeOut = 0; -+ s32 TSTimeOut = 0; -+ u8 CPAMPMin = 255; -+ u8 CPAMPValue; -+ u8 SYR_STAT; -+ u8 FFTMode; -+ u8 TSStatus; -+ -+ msleep(state->m_SignalTimeOut); -+ readreg(state, R367_OFDM_STATUS,&OFDM_Status); -+ -+ if (!(OFDM_Status & 0x40)) -+ return -1; -+ //printk("lock 1\n"); -+ -+ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); -+ FFTMode = (SYR_STAT & 0x0C) >> 2; -+ -+ switch(FFTMode) -+ { -+ case 0: // 2K -+ DemodTimeOut = 10; -+ FECTimeOut = 150; -+ TSTimeOut = 125; -+ CPAMPMin = 20; -+ break; -+ case 1: // 8K -+ DemodTimeOut = 55; -+ FECTimeOut = 600; -+ TSTimeOut = 500; -+ CPAMPMin = 80; -+ break; -+ case 2: // 4K -+ DemodTimeOut = 40; -+ FECTimeOut = 300; -+ TSTimeOut = 250; -+ CPAMPMin = 30; -+ break; -+ } -+ state->m_OFDM_FFTMode = FFTMode; -+ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); -+ msleep(DemodTimeOut); -+ { -+ // Release FEC and Read Solomon Reset -+ u8 tmp1; -+ u8 tmp2; -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); -+ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); -+ } -+ msleep(FECTimeOut); -+ if( (OFDM_Status & 0x98) != 0x98 ) -+ ;//return -1; -+ //printk("lock 2\n"); -+ -+ { -+ u8 Guard = (SYR_STAT & 0x03); -+ if(Guard < 2) -+ { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER -+ } else { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER -+ } -+ -+ // apply Sfec workaround if 8K 64QAM CR!=1/2 -+ if( FFTMode == 1) -+ { -+ u8 tmp[2]; -+ readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2); -+ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0xc0); -+ writereg(state, R367_OFDM_SFDLYSETM,0x60); -+ writereg(state, R367_OFDM_SFDLYSETL,0x00); -+ } -+ else -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0x00); -+ } -+ } -+ } -+ msleep(TSTimeOut); -+ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); -+ if( (TSStatus & 0x80) != 0x80 ) -+ return -1; -+ //printk("lock 3\n"); -+ return status; -+} -+ -+ -+#ifdef USE_API3 -+static int set_parameters(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *p) -+{ -+ int stat; -+ struct stv_state *state = fe->demodulator_priv; -+ u32 OF = 0; -+ u32 IF; -+ -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe, p); -+ -+ switch (state->omode) { -+ case OM_DVBC: -+ case OM_QAM_ITU_C: -+ state->modulation = p->u.qam.modulation; -+ state->symbol_rate = p->u.qam.symbol_rate; -+ break; -+ case OM_DVBT: -+ switch (p->u.ofdm.bandwidth) { -+ case BANDWIDTH_AUTO: -+ case BANDWIDTH_8_MHZ: -+ state->bandwidth = 8000000; -+ break; -+ case BANDWIDTH_7_MHZ: -+ state->bandwidth = 7000000; -+ break; -+ case BANDWIDTH_6_MHZ: -+ state->bandwidth = 6000000; -+ break; -+ default: -+ return -EINVAL; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+#else -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat; -+ struct stv_state *state = fe->demodulator_priv; -+ u32 OF = 0; -+ u32 IF; -+ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ state->omode = OM_DVBC; -+ /* symbol rate 0 might cause an oops */ -+ if (fe->dtv_property_cache.symbol_rate == 0) { -+ printk(KERN_ERR "stv0367dd: Invalid symbol rate\n"); -+ return -EINVAL; -+ } -+ break; -+ case SYS_DVBT: -+ state->omode = OM_DVBT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ state->modulation = fe->dtv_property_cache.modulation; -+ state->symbol_rate = fe->dtv_property_cache.symbol_rate; -+ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; -+#endif -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ //fe->ops.tuner_ops.get_frequency(fe, &IF); -+ -+ switch(state->omode) { -+ case OM_DVBT: -+ stat = OFDM_Start(state, OF, IF); -+ ofdm_lock(state); -+ break; -+ case OM_DVBC: -+ case OM_QAM_ITU_C: -+ stat = QAM_Start(state, OF, IF); -+ break; -+ default: -+ stat = -EINVAL; -+ } -+ //printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF); -+ return stat; -+} -+ -+#if 0 -+static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ return 0; -+} -+ -+static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time) -+{ -+ int status = STATUS_SUCCESS; -+ u8 OFDM_Status; -+ s32 DemodTimeOut = 0; -+ s32 FECTimeOut = 0; -+ s32 TSTimeOut = 0; -+ u8 CPAMPMin = 255; -+ u8 CPAMPValue; -+ bool SYRLock; -+ u8 SYR_STAT; -+ u8 FFTMode; -+ u8 TSStatus; -+ -+ readreg(state, R367_OFDM_STATUS,&OFDM_Status); -+ -+ SYRLock = (OFDM_Status & 0x40) != 0; -+ -+ if( Time > m_SignalTimeOut && !SYRLock ) -+ { -+ *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( !SYRLock ) break; -+ -+ *pLockStatus = SIGNAL_PRESENT; -+ -+ // Check Mode -+ -+ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); -+ FFTMode = (SYR_STAT & 0x0C) >> 2; -+ -+ switch(FFTMode) -+ { -+ case 0: // 2K -+ DemodTimeOut = 10; -+ FECTimeOut = 150; -+ TSTimeOut = 125; -+ CPAMPMin = 20; -+ break; -+ case 1: // 8K -+ DemodTimeOut = 55; -+ FECTimeOut = 600; -+ TSTimeOut = 500; -+ CPAMPMin = 80; -+ break; -+ case 2: // 4K -+ DemodTimeOut = 40; -+ FECTimeOut = 300; -+ TSTimeOut = 250; -+ CPAMPMin = 30; -+ break; -+ } -+ -+ m_OFDM_FFTMode = FFTMode; -+ -+ if( m_DemodTimeOut == 0 && m_bFirstTimeLock ) -+ { -+ m_DemodTimeOut = Time + DemodTimeOut; -+ //break; -+ } -+ -+ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); -+ -+ if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin ) -+ { -+ break; -+ } -+ -+ if( CPAMPValue < CPAMPMin && m_bFirstTimeLock ) -+ { -+ // initiate retry -+ *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( CPAMPValue < CPAMPMin ) break; -+ -+ *pLockStatus = DEMOD_LOCK; -+ -+ if( m_FECTimeOut == 0 && m_bFirstTimeLock ) -+ { -+ // Release FEC and Read Solomon Reset -+ u8 tmp1; -+ u8 tmp2; -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); -+ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); -+ -+ m_FECTimeOut = Time + FECTimeOut; -+ } -+ -+ // Wait for TSP_LOCK, LK, PRF -+ if( (OFDM_Status & 0x98) != 0x98 ) -+ { -+ if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( m_bFirstTimeLock && m_TSTimeOut == 0) -+ { -+ u8 Guard = (SYR_STAT & 0x03); -+ if(Guard < 2) -+ { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER -+ } else { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER -+ } -+ -+ // apply Sfec workaround if 8K 64QAM CR!=1/2 -+ if( FFTMode == 1) -+ { -+ u8 tmp[2]; -+ readreg(state, R367_OFDM_TPS_RCVD2,tmp,2); -+ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0xc0); -+ writereg(state, R367_OFDM_SFDLYSETM,0x60); -+ writereg(state, R367_OFDM_SFDLYSETL,0x00); -+ } -+ else -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0x00); -+ } -+ } -+ -+ m_TSTimeOut = Time + TSTimeOut; -+ } -+ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); -+ if( (TSStatus & 0x80) != 0x80 ) -+ { -+ if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ *pLockStatus = MPEG_LOCK; -+ m_bFirstTimeLock = false; -+ return status; -+} -+ -+#endif -+ -+static int read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ *status=0; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ { -+ u8 FEC_Lock; -+ u8 QAM_Lock; -+ -+ readreg(state, R367_QAM_FSM_STS, &QAM_Lock); -+ QAM_Lock &= 0x0F; -+ if (QAM_Lock >10) -+ *status|=0x07; -+ readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock); -+ if (FEC_Lock&2) -+ *status|=0x1f; -+ if (state->m_bFirstTimeLock) { -+ state->m_bFirstTimeLock = false; -+ // QAM_AGC_ACCUMRSTSEL to Tracking; -+ writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL); -+ } -+ break; -+ } -+ case OFDMStarted: -+ { -+ u8 OFDM_Status; -+ u8 TSStatus; -+ -+ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); -+ -+ readreg(state, R367_OFDM_STATUS, &OFDM_Status); -+ if (OFDM_Status & 0x40) -+ *status |= FE_HAS_SIGNAL; -+ -+ if ((OFDM_Status & 0x98) == 0x98) -+ *status|=0x0f; -+ -+ if (TSStatus & 0x80) -+ *status |= 0x1f; -+ break; -+ } -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static int read_ber_ter(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u32 err; -+ u8 cnth, cntm, cntl; -+ -+#if 1 -+ readreg(state, R367_OFDM_SFERRCNTH, &cnth); -+ -+ if (cnth & 0x80) { -+ *ber = state->ber; -+ return 0; -+ } -+ -+ readreg(state, R367_OFDM_SFERRCNTM, &cntm); -+ readreg(state, R367_OFDM_SFERRCNTL, &cntl); -+ -+ err = ((cnth & 0x7f) << 16) | (cntm << 8) | cntl; -+ -+#if 0 -+ { -+ u64 err64; -+ err64 = (u64) err; -+ err64 *= 1000000000ULL; -+ err64 >>= 21; -+ err = err64; -+ } -+#endif -+#else -+ readreg(state, R367_OFDM_ERRCNT1HM, &cnth); -+ -+#endif -+ *ber = state->ber = err; -+ return 0; -+} -+ -+static int read_ber_cab(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u32 err; -+ u8 cntm, cntl, ctrl; -+ -+ readreg(state, R367_QAM_BERT_1, &ctrl); -+ if (!(ctrl & 0x20)) { -+ readreg(state, R367_QAM_BERT_2, &cntl); -+ readreg(state, R367_QAM_BERT_3, &cntm); -+ err = (cntm << 8) | cntl; -+ //printk("err %04x\n", err); -+ state->ber = err; -+ writereg(state, R367_QAM_BERT_1, 0x27); -+ } -+ *ber = (u32) state->ber; -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ -+ if (state->demod_state == QAMStarted) -+ return read_ber_cab(fe, ber); -+ if (state->demod_state == OFDMStarted) -+ return read_ber_ter(fe, ber); -+ *ber = 0; -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ if (fe->ops.tuner_ops.get_rf_strength) -+ fe->ops.tuner_ops.get_rf_strength(fe, strength); -+ else -+ *strength = 0; -+ return 0; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ s32 snr2 = 0; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ QAM_GetSignalToNoise(state, &snr2); -+ break; -+ case OFDMStarted: -+ OFDM_GetSignalToNoise(state, &snr2); -+ break; -+ default: -+ break; -+ } -+ *snr = snr2&0xffff; -+ return 0; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 errl, errm, errh; -+ u8 val; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ readreg(state, R367_QAM_RS_COUNTER_4, &errl); -+ readreg(state, R367_QAM_RS_COUNTER_5, &errm); -+ *ucblocks = (errm << 8) | errl; -+ break; -+ case OFDMStarted: -+ readreg(state, R367_OFDM_SFERRCNTH, &val); -+ if ((val & 0x80) == 0) { -+ readreg(state, R367_OFDM_ERRCNT1H, &errh); -+ readreg(state, R367_OFDM_ERRCNT1M, &errl); -+ readreg(state, R367_OFDM_ERRCNT1L, &errm); -+ state->ucblocks = (errh <<16) | (errm << 8) | errl; -+ } -+ *ucblocks = state->ucblocks; -+ break; -+ default: -+ *ucblocks = 0; -+ break; -+ } -+ return 0; -+} -+ -+static int c_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ sets->min_delay_ms=3000; -+ sets->max_drift=0; -+ sets->step_size=0; -+ return 0; -+} -+ -+#ifndef USE_API3 -+static int get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ case SYS_DVBC_ANNEX_C: -+ return c_get_tune_settings(fe, sets); -+ default: -+ /* DVB-T: Use info.frequency_stepsize. */ -+ return -EINVAL; -+ } -+} -+#endif -+ -+#ifdef USE_API3 -+static void t_release(struct dvb_frontend* fe) -+{ -+ //struct stv_state *state=fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ //kfree(state); -+} -+ -+static int t_init (struct dvb_frontend *fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ if (mutex_trylock(&state->ctlock)==0) -+ return -EBUSY; -+ state->omode = OM_DVBT; -+ return 0; -+} -+ -+static int t_sleep(struct dvb_frontend* fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ mutex_unlock(&state->ctlock); -+ return 0; -+} -+#endif -+ -+#if 0 -+static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ return 0; -+} -+ -+static enum dvbfe_algo algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_CUSTOM; -+} -+#endif -+ -+#ifdef USE_API3 -+static struct dvb_frontend_ops c_ops = { -+ .info = { -+ .name = "STV0367 DVB-C", -+ .type = FE_QAM, -+ .frequency_stepsize = 62500, -+ .frequency_min = 47000000, -+ .frequency_max = 862000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO -+ }, -+ .release = c_release, -+ .init = c_init, -+ .sleep = c_sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .get_tune_settings = c_get_tune_settings, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+ -+#if 1 -+ .set_frontend = set_parameters, -+#else -+ .get_frontend_algo = algo, -+ .search = search, -+#endif -+}; -+ -+static struct dvb_frontend_ops t_ops = { -+ .info = { -+ .name = "STV0367 DVB-T", -+ .type = FE_OFDM, -+ .frequency_min = 47125000, -+ .frequency_max = 865000000, -+ .frequency_stepsize = 166667, -+ .frequency_tolerance = 0, -+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | -+ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | -+ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | -+ FE_CAN_MUTE_TS -+ }, -+ .release = t_release, -+ .init = t_init, -+ .sleep = t_sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+}; -+ -+#else -+ -+static struct dvb_frontend_ops common_ops = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, -+ .info = { -+ .name = "STV0367 DVB-C DVB-T", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = /* DVB-C */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_FEC_AUTO | -+ /* DVB-T */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .get_tune_settings = get_tune_settings, -+ -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+}; -+#endif -+ -+ -+static void init_state(struct stv_state *state, struct stv0367_cfg *cfg) -+{ -+ u32 ulENARPTLEVEL = 5; -+ u32 ulQAMInversion = 2; -+ state->omode = OM_NONE; -+ state->adr = cfg->adr; -+ -+ mutex_init(&state->mutex); -+ mutex_init(&state->ctlock); -+ -+#ifdef USE_API3 -+ memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops)); -+ memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops)); -+ state->c_frontend.demodulator_priv = state; -+ state->t_frontend.demodulator_priv = state; -+#else -+ memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+#endif -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4); -+ state->qam_inversion = ((ulQAMInversion & 3) << 6 ); -+ state->demod_state = Off; -+} -+ -+ -+struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg, -+ struct dvb_frontend **fe_t) -+{ -+ struct stv_state *state = NULL; -+ -+ state = kzalloc(sizeof(struct stv_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->i2c = i2c; -+ init_state(state, cfg); -+ -+ if (attach_init(state)<0) -+ goto error; -+#ifdef USE_API3 -+ *fe_t = &state->t_frontend; -+ return &state->c_frontend; -+#else -+ return &state->frontend; -+#endif -+ -+error: -+ printk("stv0367: not found\n"); -+ kfree(state); -+ return NULL; -+} -+ -+ -+MODULE_DESCRIPTION("STV0367DD driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -+ -+EXPORT_SYMBOL(stv0367_attach); -+ -+ -+ -diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h -new file mode 100644 -index 0000000..665d4c8 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.h -@@ -0,0 +1,17 @@ -+#ifndef _STV0367DD_H_ -+#define _STV0367DD_H_ -+ -+#include -+#include -+ -+struct stv0367_cfg { -+ u8 adr; -+ u32 xtal; -+ u32 ts_mode; -+}; -+ -+ -+extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, -+ struct stv0367_cfg *cfg, -+ struct dvb_frontend **fe_t); -+#endif -diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h -new file mode 100644 -index 0000000..0f02bea ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd_regs.h -@@ -0,0 +1,3431 @@ -+// @DVB-C/DVB-T STMicroelectronics STV0367 register defintions -+// Author Manfred Völkel, Februar 2011 -+// (c) 2010 DigitalDevices GmbH Germany. All rights reserved -+ -+// $Id: DD_STV0367Register.h 357 2011-04-27 02:39:13Z manfred $ -+ -+/* ======================================================================= -+ -- Registers Declaration -+ -- ------------------------- -+ -- Each register (R367_XXXXX) is defined by its address (2 bytes). -+ -- -+ -- Each field (F367_XXXXX)is defined as follow: -+ -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] -+ ======================================================================= */ -+ -+/* ID */ -+#define R367_ID 0xF000 -+#define F367_IDENTIFICATIONREG 0xF00000FF -+ -+/* I2CRPT */ -+#define R367_I2CRPT 0xF001 -+#define F367_I2CT_ON 0xF0010080 -+#define F367_ENARPT_LEVEL 0xF0010070 -+#define F367_SCLT_DELAY 0xF0010008 -+#define F367_SCLT_NOD 0xF0010004 -+#define F367_STOP_ENABLE 0xF0010002 -+#define F367_SDAT_NOD 0xF0010001 -+ -+/* TOPCTRL */ -+#define R367_TOPCTRL 0xF002 -+#define F367_STDBY 0xF0020080 -+#define F367_STDBY_FEC 0xF0020040 -+#define F367_STDBY_CORE 0xF0020020 -+#define F367_QAM_COFDM 0xF0020010 -+#define F367_TS_DIS 0xF0020008 -+#define F367_DIR_CLK_216 0xF0020004 -+#define F367_TUNER_BB 0xF0020002 -+#define F367_DVBT_H 0xF0020001 -+ -+/* IOCFG0 */ -+#define R367_IOCFG0 0xF003 -+#define F367_OP0_SD 0xF0030080 -+#define F367_OP0_VAL 0xF0030040 -+#define F367_OP0_OD 0xF0030020 -+#define F367_OP0_INV 0xF0030010 -+#define F367_OP0_DACVALUE_HI 0xF003000F -+ -+/* DAC0R */ -+#define R367_DAC0R 0xF004 -+#define F367_OP0_DACVALUE_LO 0xF00400FF -+ -+/* IOCFG1 */ -+#define R367_IOCFG1 0xF005 -+#define F367_IP0 0xF0050040 -+#define F367_OP1_OD 0xF0050020 -+#define F367_OP1_INV 0xF0050010 -+#define F367_OP1_DACVALUE_HI 0xF005000F -+ -+/* DAC1R */ -+#define R367_DAC1R 0xF006 -+#define F367_OP1_DACVALUE_LO 0xF00600FF -+ -+/* IOCFG2 */ -+#define R367_IOCFG2 0xF007 -+#define F367_OP2_LOCK_CONF 0xF00700E0 -+#define F367_OP2_OD 0xF0070010 -+#define F367_OP2_VAL 0xF0070008 -+#define F367_OP1_LOCK_CONF 0xF0070007 -+ -+/* SDFR */ -+#define R367_SDFR 0xF008 -+#define F367_OP0_FREQ 0xF00800F0 -+#define F367_OP1_FREQ 0xF008000F -+ -+/* STATUS */ -+#define R367_OFDM_STATUS 0xF009 -+#define F367_TPS_LOCK 0xF0090080 -+#define F367_SYR_LOCK 0xF0090040 -+#define F367_AGC_LOCK 0xF0090020 -+#define F367_PRF 0xF0090010 -+#define F367_LK 0xF0090008 -+#define F367_PR 0xF0090007 -+ -+/* AUX_CLK */ -+#define R367_AUX_CLK 0xF00A -+#define F367_AUXFEC_CTL 0xF00A00C0 -+#define F367_DIS_CKX4 0xF00A0020 -+#define F367_CKSEL 0xF00A0018 -+#define F367_CKDIV_PROG 0xF00A0006 -+#define F367_AUXCLK_ENA 0xF00A0001 -+ -+/* FREESYS1 */ -+#define R367_FREESYS1 0xF00B -+#define F367_FREE_SYS1 0xF00B00FF -+ -+/* FREESYS2 */ -+#define R367_FREESYS2 0xF00C -+#define F367_FREE_SYS2 0xF00C00FF -+ -+/* FREESYS3 */ -+#define R367_FREESYS3 0xF00D -+#define F367_FREE_SYS3 0xF00D00FF -+ -+/* GPIO_CFG */ -+#define R367_GPIO_CFG 0xF00E -+#define F367_GPIO7_NOD 0xF00E0080 -+#define F367_GPIO7_CFG 0xF00E0040 -+#define F367_GPIO6_NOD 0xF00E0020 -+#define F367_GPIO6_CFG 0xF00E0010 -+#define F367_GPIO5_NOD 0xF00E0008 -+#define F367_GPIO5_CFG 0xF00E0004 -+#define F367_GPIO4_NOD 0xF00E0002 -+#define F367_GPIO4_CFG 0xF00E0001 -+ -+/* GPIO_CMD */ -+#define R367_GPIO_CMD 0xF00F -+#define F367_GPIO7_VAL 0xF00F0008 -+#define F367_GPIO6_VAL 0xF00F0004 -+#define F367_GPIO5_VAL 0xF00F0002 -+#define F367_GPIO4_VAL 0xF00F0001 -+ -+/* AGC2MAX */ -+#define R367_OFDM_AGC2MAX 0xF010 -+#define F367_OFDM_AGC2_MAX 0xF01000FF -+ -+/* AGC2MIN */ -+#define R367_OFDM_AGC2MIN 0xF011 -+#define F367_OFDM_AGC2_MIN 0xF01100FF -+ -+/* AGC1MAX */ -+#define R367_OFDM_AGC1MAX 0xF012 -+#define F367_OFDM_AGC1_MAX 0xF01200FF -+ -+/* AGC1MIN */ -+#define R367_OFDM_AGC1MIN 0xF013 -+#define F367_OFDM_AGC1_MIN 0xF01300FF -+ -+/* AGCR */ -+#define R367_OFDM_AGCR 0xF014 -+#define F367_OFDM_RATIO_A 0xF01400E0 -+#define F367_OFDM_RATIO_B 0xF0140018 -+#define F367_OFDM_RATIO_C 0xF0140007 -+ -+/* AGC2TH */ -+#define R367_OFDM_AGC2TH 0xF015 -+#define F367_OFDM_AGC2_THRES 0xF01500FF -+ -+/* AGC12C */ -+#define R367_OFDM_AGC12C 0xF016 -+#define F367_OFDM_AGC1_IV 0xF0160080 -+#define F367_OFDM_AGC1_OD 0xF0160040 -+#define F367_OFDM_AGC1_LOAD 0xF0160020 -+#define F367_OFDM_AGC2_IV 0xF0160010 -+#define F367_OFDM_AGC2_OD 0xF0160008 -+#define F367_OFDM_AGC2_LOAD 0xF0160004 -+#define F367_OFDM_AGC12_MODE 0xF0160003 -+ -+/* AGCCTRL1 */ -+#define R367_OFDM_AGCCTRL1 0xF017 -+#define F367_OFDM_DAGC_ON 0xF0170080 -+#define F367_OFDM_INVERT_AGC12 0xF0170040 -+#define F367_OFDM_AGC1_MODE 0xF0170008 -+#define F367_OFDM_AGC2_MODE 0xF0170007 -+ -+/* AGCCTRL2 */ -+#define R367_OFDM_AGCCTRL2 0xF018 -+#define F367_OFDM_FRZ2_CTRL 0xF0180060 -+#define F367_OFDM_FRZ1_CTRL 0xF0180018 -+#define F367_OFDM_TIME_CST 0xF0180007 -+ -+/* AGC1VAL1 */ -+#define R367_OFDM_AGC1VAL1 0xF019 -+#define F367_OFDM_AGC1_VAL_LO 0xF01900FF -+ -+/* AGC1VAL2 */ -+#define R367_OFDM_AGC1VAL2 0xF01A -+#define F367_OFDM_AGC1_VAL_HI 0xF01A000F -+ -+/* AGC2VAL1 */ -+#define R367_OFDM_AGC2VAL1 0xF01B -+#define F367_OFDM_AGC2_VAL_LO 0xF01B00FF -+ -+/* AGC2VAL2 */ -+#define R367_OFDM_AGC2VAL2 0xF01C -+#define F367_OFDM_AGC2_VAL_HI 0xF01C000F -+ -+/* AGC2PGA */ -+#define R367_OFDM_AGC2PGA 0xF01D -+#define F367_OFDM_AGC2_PGA 0xF01D00FF -+ -+/* OVF_RATE1 */ -+#define R367_OFDM_OVF_RATE1 0xF01E -+#define F367_OFDM_OVF_RATE_HI 0xF01E000F -+ -+/* OVF_RATE2 */ -+#define R367_OFDM_OVF_RATE2 0xF01F -+#define F367_OFDM_OVF_RATE_LO 0xF01F00FF -+ -+/* GAIN_SRC1 */ -+#define R367_OFDM_GAIN_SRC1 0xF020 -+#define F367_OFDM_INV_SPECTR 0xF0200080 -+#define F367_OFDM_IQ_INVERT 0xF0200040 -+#define F367_OFDM_INR_BYPASS 0xF0200020 -+#define F367_OFDM_STATUS_INV_SPECRUM 0xF0200010 -+#define F367_OFDM_GAIN_SRC_HI 0xF020000F -+ -+/* GAIN_SRC2 */ -+#define R367_OFDM_GAIN_SRC2 0xF021 -+#define F367_OFDM_GAIN_SRC_LO 0xF02100FF -+ -+/* INC_DEROT1 */ -+#define R367_OFDM_INC_DEROT1 0xF022 -+#define F367_OFDM_INC_DEROT_HI 0xF02200FF -+ -+/* INC_DEROT2 */ -+#define R367_OFDM_INC_DEROT2 0xF023 -+#define F367_OFDM_INC_DEROT_LO 0xF02300FF -+ -+/* PPM_CPAMP_DIR */ -+#define R367_OFDM_PPM_CPAMP_DIR 0xF024 -+#define F367_OFDM_PPM_CPAMP_DIRECT 0xF02400FF -+ -+/* PPM_CPAMP_INV */ -+#define R367_OFDM_PPM_CPAMP_INV 0xF025 -+#define F367_OFDM_PPM_CPAMP_INVER 0xF02500FF -+ -+/* FREESTFE_1 */ -+#define R367_OFDM_FREESTFE_1 0xF026 -+#define F367_OFDM_SYMBOL_NUMBER_INC 0xF02600C0 -+#define F367_OFDM_SEL_LSB 0xF0260004 -+#define F367_OFDM_AVERAGE_ON 0xF0260002 -+#define F367_OFDM_DC_ADJ 0xF0260001 -+ -+/* FREESTFE_2 */ -+#define R367_OFDM_FREESTFE_2 0xF027 -+#define F367_OFDM_SEL_SRCOUT 0xF02700C0 -+#define F367_OFDM_SEL_SYRTHR 0xF027001F -+ -+/* DCOFFSET */ -+#define R367_OFDM_DCOFFSET 0xF028 -+#define F367_OFDM_SELECT_I_Q 0xF0280080 -+#define F367_OFDM_DC_OFFSET 0xF028007F -+ -+/* EN_PROCESS */ -+#define R367_OFDM_EN_PROCESS 0xF029 -+#define F367_OFDM_FREE 0xF02900F0 -+#define F367_OFDM_ENAB_MANUAL 0xF0290001 -+ -+/* SDI_SMOOTHER */ -+#define R367_OFDM_SDI_SMOOTHER 0xF02A -+#define F367_OFDM_DIS_SMOOTH 0xF02A0080 -+#define F367_OFDM_SDI_INC_SMOOTHER 0xF02A007F -+ -+/* FE_LOOP_OPEN */ -+#define R367_OFDM_FE_LOOP_OPEN 0xF02B -+#define F367_OFDM_TRL_LOOP_OP 0xF02B0002 -+#define F367_OFDM_CRL_LOOP_OP 0xF02B0001 -+ -+/* FREQOFF1 */ -+#define R367_OFDM_FREQOFF1 0xF02C -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI 0xF02C00FF -+ -+/* FREQOFF2 */ -+#define R367_OFDM_FREQOFF2 0xF02D -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI 0xF02D00FF -+ -+/* FREQOFF3 */ -+#define R367_OFDM_FREQOFF3 0xF02E -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO 0xF02E00FF -+ -+/* TIMOFF1 */ -+#define R367_OFDM_TIMOFF1 0xF02F -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI 0xF02F00FF -+ -+/* TIMOFF2 */ -+#define R367_OFDM_TIMOFF2 0xF030 -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO 0xF03000FF -+ -+/* EPQ */ -+#define R367_OFDM_EPQ 0xF031 -+#define F367_OFDM_EPQ1 0xF03100FF -+ -+/* EPQAUTO */ -+#define R367_OFDM_EPQAUTO 0xF032 -+#define F367_OFDM_EPQ2 0xF03200FF -+ -+/* SYR_UPDATE */ -+#define R367_OFDM_SYR_UPDATE 0xF033 -+#define F367_OFDM_SYR_PROTV 0xF0330080 -+#define F367_OFDM_SYR_PROTV_GAIN 0xF0330060 -+#define F367_OFDM_SYR_FILTER 0xF0330010 -+#define F367_OFDM_SYR_TRACK_THRES 0xF033000C -+ -+/* CHPFREE */ -+#define R367_OFDM_CHPFREE 0xF034 -+#define F367_OFDM_CHP_FREE 0xF03400FF -+ -+/* PPM_STATE_MAC */ -+#define R367_OFDM_PPM_STATE_MAC 0xF035 -+#define F367_OFDM_PPM_STATE_MACHINE_DECODER 0xF035003F -+ -+/* INR_THRESHOLD */ -+#define R367_OFDM_INR_THRESHOLD 0xF036 -+#define F367_OFDM_INR_THRESH 0xF03600FF -+ -+/* EPQ_TPS_ID_CELL */ -+#define R367_OFDM_EPQ_TPS_ID_CELL 0xF037 -+#define F367_OFDM_ENABLE_LGTH_TO_CF 0xF0370080 -+#define F367_OFDM_DIS_TPS_RSVD 0xF0370040 -+#define F367_OFDM_DIS_BCH 0xF0370020 -+#define F367_OFDM_DIS_ID_CEL 0xF0370010 -+#define F367_OFDM_TPS_ADJUST_SYM 0xF037000F -+ -+/* EPQ_CFG */ -+#define R367_OFDM_EPQ_CFG 0xF038 -+#define F367_OFDM_EPQ_RANGE 0xF0380002 -+#define F367_OFDM_EPQ_SOFT 0xF0380001 -+ -+/* EPQ_STATUS */ -+#define R367_OFDM_EPQ_STATUS 0xF039 -+#define F367_OFDM_SLOPE_INC 0xF03900FC -+#define F367_OFDM_TPS_FIELD 0xF0390003 -+ -+/* AUTORELOCK */ -+#define R367_OFDM_AUTORELOCK 0xF03A -+#define F367_OFDM_BYPASS_BER_TEMPO 0xF03A0080 -+#define F367_OFDM_BER_TEMPO 0xF03A0070 -+#define F367_OFDM_BYPASS_COFDM_TEMPO 0xF03A0008 -+#define F367_OFDM_COFDM_TEMPO 0xF03A0007 -+ -+/* BER_THR_VMSB */ -+#define R367_OFDM_BER_THR_VMSB 0xF03B -+#define F367_OFDM_BER_THRESHOLD_HI 0xF03B00FF -+ -+/* BER_THR_MSB */ -+#define R367_OFDM_BER_THR_MSB 0xF03C -+#define F367_OFDM_BER_THRESHOLD_MID 0xF03C00FF -+ -+/* BER_THR_LSB */ -+#define R367_OFDM_BER_THR_LSB 0xF03D -+#define F367_OFDM_BER_THRESHOLD_LO 0xF03D00FF -+ -+/* CCD */ -+#define R367_OFDM_CCD 0xF03E -+#define F367_OFDM_CCD_DETECTED 0xF03E0080 -+#define F367_OFDM_CCD_RESET 0xF03E0040 -+#define F367_OFDM_CCD_THRESHOLD 0xF03E000F -+ -+/* SPECTR_CFG */ -+#define R367_OFDM_SPECTR_CFG 0xF03F -+#define F367_OFDM_SPECT_CFG 0xF03F0003 -+ -+/* CONSTMU_MSB */ -+#define R367_OFDM_CONSTMU_MSB 0xF040 -+#define F367_OFDM_CONSTMU_FREEZE 0xF0400080 -+#define F367_OFDM_CONSTNU_FORCE_EN 0xF0400040 -+#define F367_OFDM_CONST_MU_MSB 0xF040003F -+ -+/* CONSTMU_LSB */ -+#define R367_OFDM_CONSTMU_LSB 0xF041 -+#define F367_OFDM_CONST_MU_LSB 0xF04100FF -+ -+/* CONSTMU_MAX_MSB */ -+#define R367_OFDM_CONSTMU_MAX_MSB 0xF042 -+#define F367_OFDM_CONST_MU_MAX_MSB 0xF042003F -+ -+/* CONSTMU_MAX_LSB */ -+#define R367_OFDM_CONSTMU_MAX_LSB 0xF043 -+#define F367_OFDM_CONST_MU_MAX_LSB 0xF04300FF -+ -+/* ALPHANOISE */ -+#define R367_OFDM_ALPHANOISE 0xF044 -+#define F367_OFDM_USE_ALLFILTER 0xF0440080 -+#define F367_OFDM_INTER_ON 0xF0440040 -+#define F367_OFDM_ALPHA_NOISE 0xF044001F -+ -+/* MAXGP_MSB */ -+#define R367_OFDM_MAXGP_MSB 0xF045 -+#define F367_OFDM_MUFILTER_LENGTH 0xF04500F0 -+#define F367_OFDM_MAX_GP_MSB 0xF045000F -+ -+/* MAXGP_LSB */ -+#define R367_OFDM_MAXGP_LSB 0xF046 -+#define F367_OFDM_MAX_GP_LSB 0xF04600FF -+ -+/* ALPHAMSB */ -+#define R367_OFDM_ALPHAMSB 0xF047 -+#define F367_OFDM_CHC_DATARATE 0xF04700C0 -+#define F367_OFDM_ALPHA_MSB 0xF047003F -+ -+/* ALPHALSB */ -+#define R367_OFDM_ALPHALSB 0xF048 -+#define F367_OFDM_ALPHA_LSB 0xF04800FF -+ -+/* PILOT_ACCU */ -+#define R367_OFDM_PILOT_ACCU 0xF049 -+#define F367_OFDM_USE_SCAT4ADDAPT 0xF0490080 -+#define F367_OFDM_PILOT_ACC 0xF049001F -+ -+/* PILOTMU_ACCU */ -+#define R367_OFDM_PILOTMU_ACCU 0xF04A -+#define F367_OFDM_DISCARD_BAD_SP 0xF04A0080 -+#define F367_OFDM_DISCARD_BAD_CP 0xF04A0040 -+#define F367_OFDM_PILOT_MU_ACCU 0xF04A001F -+ -+/* FILT_CHANNEL_EST */ -+#define R367_OFDM_FILT_CHANNEL_EST 0xF04B -+#define F367_OFDM_USE_FILT_PILOT 0xF04B0080 -+#define F367_OFDM_FILT_CHANNEL 0xF04B007F -+ -+/* ALPHA_NOPISE_FREQ */ -+#define R367_OFDM_ALPHA_NOPISE_FREQ 0xF04C -+#define F367_OFDM_NOISE_FREQ_FILT 0xF04C0040 -+#define F367_OFDM_ALPHA_NOISE_FREQ 0xF04C003F -+ -+/* RATIO_PILOT */ -+#define R367_OFDM_RATIO_PILOT 0xF04D -+#define F367_OFDM_RATIO_MEAN_SP 0xF04D00F0 -+#define F367_OFDM_RATIO_MEAN_CP 0xF04D000F -+ -+/* CHC_CTL */ -+#define R367_OFDM_CHC_CTL 0xF04E -+#define F367_OFDM_TRACK_EN 0xF04E0080 -+#define F367_OFDM_NOISE_NORM_EN 0xF04E0040 -+#define F367_OFDM_FORCE_CHC_RESET 0xF04E0020 -+#define F367_OFDM_SHORT_TIME 0xF04E0010 -+#define F367_OFDM_FORCE_STATE_EN 0xF04E0008 -+#define F367_OFDM_FORCE_STATE 0xF04E0007 -+ -+/* EPQ_ADJUST */ -+#define R367_OFDM_EPQ_ADJUST 0xF04F -+#define F367_OFDM_ADJUST_SCAT_IND 0xF04F00C0 -+#define F367_OFDM_ONE_SYMBOL 0xF04F0010 -+#define F367_OFDM_EPQ_DECAY 0xF04F000E -+#define F367_OFDM_HOLD_SLOPE 0xF04F0001 -+ -+/* EPQ_THRES */ -+#define R367_OFDM_EPQ_THRES 0xF050 -+#define F367_OFDM_EPQ_THR 0xF05000FF -+ -+/* OMEGA_CTL */ -+#define R367_OFDM_OMEGA_CTL 0xF051 -+#define F367_OFDM_OMEGA_RST 0xF0510080 -+#define F367_OFDM_FREEZE_OMEGA 0xF0510040 -+#define F367_OFDM_OMEGA_SEL 0xF051003F -+ -+/* GP_CTL */ -+#define R367_OFDM_GP_CTL 0xF052 -+#define F367_OFDM_CHC_STATE 0xF05200E0 -+#define F367_OFDM_FREEZE_GP 0xF0520010 -+#define F367_OFDM_GP_SEL 0xF052000F -+ -+/* MUMSB */ -+#define R367_OFDM_MUMSB 0xF053 -+#define F367_OFDM_MU_MSB 0xF053007F -+ -+/* MULSB */ -+#define R367_OFDM_MULSB 0xF054 -+#define F367_OFDM_MU_LSB 0xF05400FF -+ -+/* GPMSB */ -+#define R367_OFDM_GPMSB 0xF055 -+#define F367_OFDM_CSI_THRESHOLD 0xF05500E0 -+#define F367_OFDM_GP_MSB 0xF055000F -+ -+/* GPLSB */ -+#define R367_OFDM_GPLSB 0xF056 -+#define F367_OFDM_GP_LSB 0xF05600FF -+ -+/* OMEGAMSB */ -+#define R367_OFDM_OMEGAMSB 0xF057 -+#define F367_OFDM_OMEGA_MSB 0xF057007F -+ -+/* OMEGALSB */ -+#define R367_OFDM_OMEGALSB 0xF058 -+#define F367_OFDM_OMEGA_LSB 0xF05800FF -+ -+/* SCAT_NB */ -+#define R367_OFDM_SCAT_NB 0xF059 -+#define F367_OFDM_CHC_TEST 0xF05900F8 -+#define F367_OFDM_SCAT_NUMB 0xF0590003 -+ -+/* CHC_DUMMY */ -+#define R367_OFDM_CHC_DUMMY 0xF05A -+#define F367_OFDM_CHC_DUM 0xF05A00FF -+ -+/* INC_CTL */ -+#define R367_OFDM_INC_CTL 0xF05B -+#define F367_OFDM_INC_BYPASS 0xF05B0080 -+#define F367_OFDM_INC_NDEPTH 0xF05B000C -+#define F367_OFDM_INC_MADEPTH 0xF05B0003 -+ -+/* INCTHRES_COR1 */ -+#define R367_OFDM_INCTHRES_COR1 0xF05C -+#define F367_OFDM_INC_THRES_COR1 0xF05C00FF -+ -+/* INCTHRES_COR2 */ -+#define R367_OFDM_INCTHRES_COR2 0xF05D -+#define F367_OFDM_INC_THRES_COR2 0xF05D00FF -+ -+/* INCTHRES_DET1 */ -+#define R367_OFDM_INCTHRES_DET1 0xF05E -+#define F367_OFDM_INC_THRES_DET1 0xF05E003F -+ -+/* INCTHRES_DET2 */ -+#define R367_OFDM_INCTHRES_DET2 0xF05F -+#define F367_OFDM_INC_THRES_DET2 0xF05F003F -+ -+/* IIR_CELLNB */ -+#define R367_OFDM_IIR_CELLNB 0xF060 -+#define F367_OFDM_NRST_IIR 0xF0600080 -+#define F367_OFDM_IIR_CELL_NB 0xF0600007 -+ -+/* IIRCX_COEFF1_MSB */ -+#define R367_OFDM_IIRCX_COEFF1_MSB 0xF061 -+#define F367_OFDM_IIR_CX_COEFF1_MSB 0xF06100FF -+ -+/* IIRCX_COEFF1_LSB */ -+#define R367_OFDM_IIRCX_COEFF1_LSB 0xF062 -+#define F367_OFDM_IIR_CX_COEFF1_LSB 0xF06200FF -+ -+/* IIRCX_COEFF2_MSB */ -+#define R367_OFDM_IIRCX_COEFF2_MSB 0xF063 -+#define F367_OFDM_IIR_CX_COEFF2_MSB 0xF06300FF -+ -+/* IIRCX_COEFF2_LSB */ -+#define R367_OFDM_IIRCX_COEFF2_LSB 0xF064 -+#define F367_OFDM_IIR_CX_COEFF2_LSB 0xF06400FF -+ -+/* IIRCX_COEFF3_MSB */ -+#define R367_OFDM_IIRCX_COEFF3_MSB 0xF065 -+#define F367_OFDM_IIR_CX_COEFF3_MSB 0xF06500FF -+ -+/* IIRCX_COEFF3_LSB */ -+#define R367_OFDM_IIRCX_COEFF3_LSB 0xF066 -+#define F367_OFDM_IIR_CX_COEFF3_LSB 0xF06600FF -+ -+/* IIRCX_COEFF4_MSB */ -+#define R367_OFDM_IIRCX_COEFF4_MSB 0xF067 -+#define F367_OFDM_IIR_CX_COEFF4_MSB 0xF06700FF -+ -+/* IIRCX_COEFF4_LSB */ -+#define R367_OFDM_IIRCX_COEFF4_LSB 0xF068 -+#define F367_OFDM_IIR_CX_COEFF4_LSB 0xF06800FF -+ -+/* IIRCX_COEFF5_MSB */ -+#define R367_OFDM_IIRCX_COEFF5_MSB 0xF069 -+#define F367_OFDM_IIR_CX_COEFF5_MSB 0xF06900FF -+ -+/* IIRCX_COEFF5_LSB */ -+#define R367_OFDM_IIRCX_COEFF5_LSB 0xF06A -+#define F367_OFDM_IIR_CX_COEFF5_LSB 0xF06A00FF -+ -+/* FEPATH_CFG */ -+#define R367_OFDM_FEPATH_CFG 0xF06B -+#define F367_OFDM_DEMUX_SWAP 0xF06B0004 -+#define F367_OFDM_DIGAGC_SWAP 0xF06B0002 -+#define F367_OFDM_LONGPATH_IF 0xF06B0001 -+ -+/* PMC1_FUNC */ -+#define R367_OFDM_PMC1_FUNC 0xF06C -+#define F367_OFDM_SOFT_RSTN 0xF06C0080 -+#define F367_OFDM_PMC1_AVERAGE_TIME 0xF06C0078 -+#define F367_OFDM_PMC1_WAIT_TIME 0xF06C0006 -+#define F367_OFDM_PMC1_2N_SEL 0xF06C0001 -+ -+/* PMC1_FOR */ -+#define R367_OFDM_PMC1_FOR 0xF06D -+#define F367_OFDM_PMC1_FORCE 0xF06D0080 -+#define F367_OFDM_PMC1_FORCE_VALUE 0xF06D007C -+ -+/* PMC2_FUNC */ -+#define R367_OFDM_PMC2_FUNC 0xF06E -+#define F367_OFDM_PMC2_SOFT_STN 0xF06E0080 -+#define F367_OFDM_PMC2_ACCU_TIME 0xF06E0070 -+#define F367_OFDM_PMC2_CMDP_MN 0xF06E0008 -+#define F367_OFDM_PMC2_SWAP 0xF06E0004 -+ -+/* STATUS_ERR_DA */ -+#define R367_OFDM_STATUS_ERR_DA 0xF06F -+#define F367_OFDM_COM_USEGAINTRK 0xF06F0080 -+#define F367_OFDM_COM_AGCLOCK 0xF06F0040 -+#define F367_OFDM_AUT_AGCLOCK 0xF06F0020 -+#define F367_OFDM_MIN_ERR_X_LSB 0xF06F000F -+ -+/* DIG_AGC_R */ -+#define R367_OFDM_DIG_AGC_R 0xF070 -+#define F367_OFDM_COM_SOFT_RSTN 0xF0700080 -+#define F367_OFDM_COM_AGC_ON 0xF0700040 -+#define F367_OFDM_COM_EARLY 0xF0700020 -+#define F367_OFDM_AUT_SOFT_RESETN 0xF0700010 -+#define F367_OFDM_AUT_AGC_ON 0xF0700008 -+#define F367_OFDM_AUT_EARLY 0xF0700004 -+#define F367_OFDM_AUT_ROT_EN 0xF0700002 -+#define F367_OFDM_LOCK_SOFT_RESETN 0xF0700001 -+ -+/* COMAGC_TARMSB */ -+#define R367_OFDM_COMAGC_TARMSB 0xF071 -+#define F367_OFDM_COM_AGC_TARGET_MSB 0xF07100FF -+ -+/* COM_AGC_TAR_ENMODE */ -+#define R367_OFDM_COM_AGC_TAR_ENMODE 0xF072 -+#define F367_OFDM_COM_AGC_TARGET_LSB 0xF07200F0 -+#define F367_OFDM_COM_ENMODE 0xF072000F -+ -+/* COM_AGC_CFG */ -+#define R367_OFDM_COM_AGC_CFG 0xF073 -+#define F367_OFDM_COM_N 0xF07300F8 -+#define F367_OFDM_COM_STABMODE 0xF0730006 -+#define F367_OFDM_ERR_SEL 0xF0730001 -+ -+/* COM_AGC_GAIN1 */ -+#define R367_OFDM_COM_AGC_GAIN1 0xF074 -+#define F367_OFDM_COM_GAIN1ACK 0xF07400F0 -+#define F367_OFDM_COM_GAIN1TRK 0xF074000F -+ -+/* AUT_AGC_TARGETMSB */ -+#define R367_OFDM_AUT_AGC_TARGETMSB 0xF075 -+#define F367_OFDM_AUT_AGC_TARGET_MSB 0xF07500FF -+ -+/* LOCK_DET_MSB */ -+#define R367_OFDM_LOCK_DET_MSB 0xF076 -+#define F367_OFDM_LOCK_DETECT_MSB 0xF07600FF -+ -+/* AGCTAR_LOCK_LSBS */ -+#define R367_OFDM_AGCTAR_LOCK_LSBS 0xF077 -+#define F367_OFDM_AUT_AGC_TARGET_LSB 0xF07700F0 -+#define F367_OFDM_LOCK_DETECT_LSB 0xF077000F -+ -+/* AUT_GAIN_EN */ -+#define R367_OFDM_AUT_GAIN_EN 0xF078 -+#define F367_OFDM_AUT_ENMODE 0xF07800F0 -+#define F367_OFDM_AUT_GAIN2 0xF078000F -+ -+/* AUT_CFG */ -+#define R367_OFDM_AUT_CFG 0xF079 -+#define F367_OFDM_AUT_N 0xF07900F8 -+#define F367_OFDM_INT_CHOICE 0xF0790006 -+#define F367_OFDM_INT_LOAD 0xF0790001 -+ -+/* LOCKN */ -+#define R367_OFDM_LOCKN 0xF07A -+#define F367_OFDM_LOCK_N 0xF07A00F8 -+#define F367_OFDM_SEL_IQNTAR 0xF07A0004 -+#define F367_OFDM_LOCK_DETECT_CHOICE 0xF07A0003 -+ -+/* INT_X_3 */ -+#define R367_OFDM_INT_X_3 0xF07B -+#define F367_OFDM_INT_X3 0xF07B00FF -+ -+/* INT_X_2 */ -+#define R367_OFDM_INT_X_2 0xF07C -+#define F367_OFDM_INT_X2 0xF07C00FF -+ -+/* INT_X_1 */ -+#define R367_OFDM_INT_X_1 0xF07D -+#define F367_OFDM_INT_X1 0xF07D00FF -+ -+/* INT_X_0 */ -+#define R367_OFDM_INT_X_0 0xF07E -+#define F367_OFDM_INT_X0 0xF07E00FF -+ -+/* MIN_ERRX_MSB */ -+#define R367_OFDM_MIN_ERRX_MSB 0xF07F -+#define F367_OFDM_MIN_ERR_X_MSB 0xF07F00FF -+ -+/* COR_CTL */ -+#define R367_OFDM_COR_CTL 0xF080 -+#define F367_OFDM_CORE_ACTIVE 0xF0800020 -+#define F367_OFDM_HOLD 0xF0800010 -+#define F367_OFDM_CORE_STATE_CTL 0xF080000F -+ -+/* COR_STAT */ -+#define R367_OFDM_COR_STAT 0xF081 -+#define F367_OFDM_SCATT_LOCKED 0xF0810080 -+#define F367_OFDM_TPS_LOCKED 0xF0810040 -+#define F367_OFDM_SYR_LOCKED_COR 0xF0810020 -+#define F367_OFDM_AGC_LOCKED_STAT 0xF0810010 -+#define F367_OFDM_CORE_STATE_STAT 0xF081000F -+ -+/* COR_INTEN */ -+#define R367_OFDM_COR_INTEN 0xF082 -+#define F367_OFDM_INTEN 0xF0820080 -+#define F367_OFDM_INTEN_SYR 0xF0820020 -+#define F367_OFDM_INTEN_FFT 0xF0820010 -+#define F367_OFDM_INTEN_AGC 0xF0820008 -+#define F367_OFDM_INTEN_TPS1 0xF0820004 -+#define F367_OFDM_INTEN_TPS2 0xF0820002 -+#define F367_OFDM_INTEN_TPS3 0xF0820001 -+ -+/* COR_INTSTAT */ -+#define R367_OFDM_COR_INTSTAT 0xF083 -+#define F367_OFDM_INTSTAT_SYR 0xF0830020 -+#define F367_OFDM_INTSTAT_FFT 0xF0830010 -+#define F367_OFDM_INTSAT_AGC 0xF0830008 -+#define F367_OFDM_INTSTAT_TPS1 0xF0830004 -+#define F367_OFDM_INTSTAT_TPS2 0xF0830002 -+#define F367_OFDM_INTSTAT_TPS3 0xF0830001 -+ -+/* COR_MODEGUARD */ -+#define R367_OFDM_COR_MODEGUARD 0xF084 -+#define F367_OFDM_FORCE 0xF0840010 -+#define F367_OFDM_MODE 0xF084000C -+#define F367_OFDM_GUARD 0xF0840003 -+ -+/* AGC_CTL */ -+#define R367_OFDM_AGC_CTL 0xF085 -+#define F367_OFDM_AGC_TIMING_FACTOR 0xF08500E0 -+#define F367_OFDM_AGC_LAST 0xF0850010 -+#define F367_OFDM_AGC_GAIN 0xF085000C -+#define F367_OFDM_AGC_NEG 0xF0850002 -+#define F367_OFDM_AGC_SET 0xF0850001 -+ -+/* AGC_MANUAL1 */ -+#define R367_OFDM_AGC_MANUAL1 0xF086 -+#define F367_OFDM_AGC_VAL_LO 0xF08600FF -+ -+/* AGC_MANUAL2 */ -+#define R367_OFDM_AGC_MANUAL2 0xF087 -+#define F367_OFDM_AGC_VAL_HI 0xF087000F -+ -+/* AGC_TARG */ -+#define R367_OFDM_AGC_TARG 0xF088 -+#define F367_OFDM_AGC_TARGET 0xF08800FF -+ -+/* AGC_GAIN1 */ -+#define R367_OFDM_AGC_GAIN1 0xF089 -+#define F367_OFDM_AGC_GAIN_LO 0xF08900FF -+ -+/* AGC_GAIN2 */ -+#define R367_OFDM_AGC_GAIN2 0xF08A -+#define F367_OFDM_AGC_LOCKED_GAIN2 0xF08A0010 -+#define F367_OFDM_AGC_GAIN_HI 0xF08A000F -+ -+/* RESERVED_1 */ -+#define R367_OFDM_RESERVED_1 0xF08B -+#define F367_OFDM_RESERVED1 0xF08B00FF -+ -+/* RESERVED_2 */ -+#define R367_OFDM_RESERVED_2 0xF08C -+#define F367_OFDM_RESERVED2 0xF08C00FF -+ -+/* RESERVED_3 */ -+#define R367_OFDM_RESERVED_3 0xF08D -+#define F367_OFDM_RESERVED3 0xF08D00FF -+ -+/* CAS_CTL */ -+#define R367_OFDM_CAS_CTL 0xF08E -+#define F367_OFDM_CCS_ENABLE 0xF08E0080 -+#define F367_OFDM_ACS_DISABLE 0xF08E0040 -+#define F367_OFDM_DAGC_DIS 0xF08E0020 -+#define F367_OFDM_DAGC_GAIN 0xF08E0018 -+#define F367_OFDM_CCSMU 0xF08E0007 -+ -+/* CAS_FREQ */ -+#define R367_OFDM_CAS_FREQ 0xF08F -+#define F367_OFDM_CCS_FREQ 0xF08F00FF -+ -+/* CAS_DAGCGAIN */ -+#define R367_OFDM_CAS_DAGCGAIN 0xF090 -+#define F367_OFDM_CAS_DAGC_GAIN 0xF09000FF -+ -+/* SYR_CTL */ -+#define R367_OFDM_SYR_CTL 0xF091 -+#define F367_OFDM_SICTH_ENABLE 0xF0910080 -+#define F367_OFDM_LONG_ECHO 0xF0910078 -+#define F367_OFDM_AUTO_LE_EN 0xF0910004 -+#define F367_OFDM_SYR_BYPASS 0xF0910002 -+#define F367_OFDM_SYR_TR_DIS 0xF0910001 -+ -+/* SYR_STAT */ -+#define R367_OFDM_SYR_STAT 0xF092 -+#define F367_OFDM_SYR_LOCKED_STAT 0xF0920010 -+#define F367_OFDM_SYR_MODE 0xF092000C -+#define F367_OFDM_SYR_GUARD 0xF0920003 -+ -+/* SYR_NCO1 */ -+#define R367_OFDM_SYR_NCO1 0xF093 -+#define F367_OFDM_SYR_NCO_LO 0xF09300FF -+ -+/* SYR_NCO2 */ -+#define R367_OFDM_SYR_NCO2 0xF094 -+#define F367_OFDM_SYR_NCO_HI 0xF094003F -+ -+/* SYR_OFFSET1 */ -+#define R367_OFDM_SYR_OFFSET1 0xF095 -+#define F367_OFDM_SYR_OFFSET_LO 0xF09500FF -+ -+/* SYR_OFFSET2 */ -+#define R367_OFDM_SYR_OFFSET2 0xF096 -+#define F367_OFDM_SYR_OFFSET_HI 0xF096003F -+ -+/* FFT_CTL */ -+#define R367_OFDM_FFT_CTL 0xF097 -+#define F367_OFDM_SHIFT_FFT_TRIG 0xF0970018 -+#define F367_OFDM_FFT_TRIGGER 0xF0970004 -+#define F367_OFDM_FFT_MANUAL 0xF0970002 -+#define F367_OFDM_IFFT_MODE 0xF0970001 -+ -+/* SCR_CTL */ -+#define R367_OFDM_SCR_CTL 0xF098 -+#define F367_OFDM_SYRADJDECAY 0xF0980070 -+#define F367_OFDM_SCR_CPEDIS 0xF0980002 -+#define F367_OFDM_SCR_DIS 0xF0980001 -+ -+/* PPM_CTL1 */ -+#define R367_OFDM_PPM_CTL1 0xF099 -+#define F367_OFDM_PPM_MAXFREQ 0xF0990030 -+#define F367_OFDM_PPM_MAXTIM 0xF0990008 -+#define F367_OFDM_PPM_INVSEL 0xF0990004 -+#define F367_OFDM_PPM_SCATDIS 0xF0990002 -+#define F367_OFDM_PPM_BYP 0xF0990001 -+ -+/* TRL_CTL */ -+#define R367_OFDM_TRL_CTL 0xF09A -+#define F367_OFDM_TRL_NOMRATE_LSB 0xF09A0080 -+#define F367_OFDM_TRL_GAIN_FACTOR 0xF09A0078 -+#define F367_OFDM_TRL_LOOPGAIN 0xF09A0007 -+ -+/* TRL_NOMRATE1 */ -+#define R367_OFDM_TRL_NOMRATE1 0xF09B -+#define F367_OFDM_TRL_NOMRATE_LO 0xF09B00FF -+ -+/* TRL_NOMRATE2 */ -+#define R367_OFDM_TRL_NOMRATE2 0xF09C -+#define F367_OFDM_TRL_NOMRATE_HI 0xF09C00FF -+ -+/* TRL_TIME1 */ -+#define R367_OFDM_TRL_TIME1 0xF09D -+#define F367_OFDM_TRL_TOFFSET_LO 0xF09D00FF -+ -+/* TRL_TIME2 */ -+#define R367_OFDM_TRL_TIME2 0xF09E -+#define F367_OFDM_TRL_TOFFSET_HI 0xF09E00FF -+ -+/* CRL_CTL */ -+#define R367_OFDM_CRL_CTL 0xF09F -+#define F367_OFDM_CRL_DIS 0xF09F0080 -+#define F367_OFDM_CRL_GAIN_FACTOR 0xF09F0078 -+#define F367_OFDM_CRL_LOOPGAIN 0xF09F0007 -+ -+/* CRL_FREQ1 */ -+#define R367_OFDM_CRL_FREQ1 0xF0A0 -+#define F367_OFDM_CRL_FOFFSET_LO 0xF0A000FF -+ -+/* CRL_FREQ2 */ -+#define R367_OFDM_CRL_FREQ2 0xF0A1 -+#define F367_OFDM_CRL_FOFFSET_HI 0xF0A100FF -+ -+/* CRL_FREQ3 */ -+#define R367_OFDM_CRL_FREQ3 0xF0A2 -+#define F367_OFDM_CRL_FOFFSET_VHI 0xF0A200FF -+ -+/* TPS_SFRAME_CTL */ -+#define R367_OFDM_TPS_SFRAME_CTL 0xF0A3 -+#define F367_OFDM_TPS_SFRAME_SYNC 0xF0A30001 -+ -+/* CHC_SNR */ -+#define R367_OFDM_CHC_SNR 0xF0A4 -+#define F367_OFDM_CHCSNR 0xF0A400FF -+ -+/* BDI_CTL */ -+#define R367_OFDM_BDI_CTL 0xF0A5 -+#define F367_OFDM_BDI_LPSEL 0xF0A50002 -+#define F367_OFDM_BDI_SERIAL 0xF0A50001 -+ -+/* DMP_CTL */ -+#define R367_OFDM_DMP_CTL 0xF0A6 -+#define F367_OFDM_DMP_SCALING_FACTOR 0xF0A6001E -+#define F367_OFDM_DMP_SDDIS 0xF0A60001 -+ -+/* TPS_RCVD1 */ -+#define R367_OFDM_TPS_RCVD1 0xF0A7 -+#define F367_OFDM_TPS_CHANGE 0xF0A70040 -+#define F367_OFDM_BCH_OK 0xF0A70020 -+#define F367_OFDM_TPS_SYNC 0xF0A70010 -+#define F367_OFDM_TPS_FRAME 0xF0A70003 -+ -+/* TPS_RCVD2 */ -+#define R367_OFDM_TPS_RCVD2 0xF0A8 -+#define F367_OFDM_TPS_HIERMODE 0xF0A80070 -+#define F367_OFDM_TPS_CONST 0xF0A80003 -+ -+/* TPS_RCVD3 */ -+#define R367_OFDM_TPS_RCVD3 0xF0A9 -+#define F367_OFDM_TPS_LPCODE 0xF0A90070 -+#define F367_OFDM_TPS_HPCODE 0xF0A90007 -+ -+/* TPS_RCVD4 */ -+#define R367_OFDM_TPS_RCVD4 0xF0AA -+#define F367_OFDM_TPS_GUARD 0xF0AA0030 -+#define F367_OFDM_TPS_MODE 0xF0AA0003 -+ -+/* TPS_ID_CELL1 */ -+#define R367_OFDM_TPS_ID_CELL1 0xF0AB -+#define F367_OFDM_TPS_ID_CELL_LO 0xF0AB00FF -+ -+/* TPS_ID_CELL2 */ -+#define R367_OFDM_TPS_ID_CELL2 0xF0AC -+#define F367_OFDM_TPS_ID_CELL_HI 0xF0AC00FF -+ -+/* TPS_RCVD5_SET1 */ -+#define R367_OFDM_TPS_RCVD5_SET1 0xF0AD -+#define F367_OFDM_TPS_NA 0xF0AD00FC -+#define F367_OFDM_TPS_SETFRAME 0xF0AD0003 -+ -+/* TPS_SET2 */ -+#define R367_OFDM_TPS_SET2 0xF0AE -+#define F367_OFDM_TPS_SETHIERMODE 0xF0AE0070 -+#define F367_OFDM_TPS_SETCONST 0xF0AE0003 -+ -+/* TPS_SET3 */ -+#define R367_OFDM_TPS_SET3 0xF0AF -+#define F367_OFDM_TPS_SETLPCODE 0xF0AF0070 -+#define F367_OFDM_TPS_SETHPCODE 0xF0AF0007 -+ -+/* TPS_CTL */ -+#define R367_OFDM_TPS_CTL 0xF0B0 -+#define F367_OFDM_TPS_IMM 0xF0B00004 -+#define F367_OFDM_TPS_BCHDIS 0xF0B00002 -+#define F367_OFDM_TPS_UPDDIS 0xF0B00001 -+ -+/* CTL_FFTOSNUM */ -+#define R367_OFDM_CTL_FFTOSNUM 0xF0B1 -+#define F367_OFDM_SYMBOL_NUMBER 0xF0B1007F -+ -+/* TESTSELECT */ -+#define R367_OFDM_TESTSELECT 0xF0B2 -+#define F367_OFDM_TEST_SELECT 0xF0B2001F -+ -+/* MSC_REV */ -+#define R367_OFDM_MSC_REV 0xF0B3 -+#define F367_OFDM_REV_NUMBER 0xF0B300FF -+ -+/* PIR_CTL */ -+#define R367_OFDM_PIR_CTL 0xF0B4 -+#define F367_OFDM_FREEZE 0xF0B40001 -+ -+/* SNR_CARRIER1 */ -+#define R367_OFDM_SNR_CARRIER1 0xF0B5 -+#define F367_OFDM_SNR_CARRIER_LO 0xF0B500FF -+ -+/* SNR_CARRIER2 */ -+#define R367_OFDM_SNR_CARRIER2 0xF0B6 -+#define F367_OFDM_MEAN 0xF0B600C0 -+#define F367_OFDM_SNR_CARRIER_HI 0xF0B6001F -+ -+/* PPM_CPAMP */ -+#define R367_OFDM_PPM_CPAMP 0xF0B7 -+#define F367_OFDM_PPM_CPC 0xF0B700FF -+ -+/* TSM_AP0 */ -+#define R367_OFDM_TSM_AP0 0xF0B8 -+#define F367_OFDM_ADDRESS_BYTE_0 0xF0B800FF -+ -+/* TSM_AP1 */ -+#define R367_OFDM_TSM_AP1 0xF0B9 -+#define F367_OFDM_ADDRESS_BYTE_1 0xF0B900FF -+ -+/* TSM_AP2 */ -+#define R367_OFDM_TSM_AP2 0xF0BA -+#define F367_OFDM_DATA_BYTE_0 0xF0BA00FF -+ -+/* TSM_AP3 */ -+#define R367_OFDM_TSM_AP3 0xF0BB -+#define F367_OFDM_DATA_BYTE_1 0xF0BB00FF -+ -+/* TSM_AP4 */ -+#define R367_OFDM_TSM_AP4 0xF0BC -+#define F367_OFDM_DATA_BYTE_2 0xF0BC00FF -+ -+/* TSM_AP5 */ -+#define R367_OFDM_TSM_AP5 0xF0BD -+#define F367_OFDM_DATA_BYTE_3 0xF0BD00FF -+ -+/* TSM_AP6 */ -+#define R367_OFDM_TSM_AP6 0xF0BE -+#define F367_OFDM_TSM_AP_6 0xF0BE00FF -+ -+/* TSM_AP7 */ -+#define R367_OFDM_TSM_AP7 0xF0BF -+#define F367_OFDM_MEM_SELECT_BYTE 0xF0BF00FF -+ -+/* TSTRES */ -+#define R367_TSTRES 0xF0C0 -+#define F367_FRES_DISPLAY 0xF0C00080 -+#define F367_FRES_FIFO_AD 0xF0C00020 -+#define F367_FRESRS 0xF0C00010 -+#define F367_FRESACS 0xF0C00008 -+#define F367_FRESFEC 0xF0C00004 -+#define F367_FRES_PRIF 0xF0C00002 -+#define F367_FRESCORE 0xF0C00001 -+ -+/* ANACTRL */ -+#define R367_ANACTRL 0xF0C1 -+#define F367_BYPASS_XTAL 0xF0C10040 -+#define F367_BYPASS_PLLXN 0xF0C1000C -+#define F367_DIS_PAD_OSC 0xF0C10002 -+#define F367_STDBY_PLLXN 0xF0C10001 -+ -+/* TSTBUS */ -+#define R367_TSTBUS 0xF0C2 -+#define F367_TS_BYTE_CLK_INV 0xF0C20080 -+#define F367_CFG_IP 0xF0C20070 -+#define F367_CFG_TST 0xF0C2000F -+ -+/* TSTRATE */ -+#define R367_TSTRATE 0xF0C6 -+#define F367_FORCEPHA 0xF0C60080 -+#define F367_FNEWPHA 0xF0C60010 -+#define F367_FROT90 0xF0C60008 -+#define F367_FR 0xF0C60007 -+ -+/* CONSTMODE */ -+#define R367_OFDM_CONSTMODE 0xF0CB -+#define F367_OFDM_TST_PRIF 0xF0CB00E0 -+#define F367_OFDM_CAR_TYPE 0xF0CB0018 -+#define F367_OFDM_CONST_MODE 0xF0CB0003 -+ -+/* CONSTCARR1 */ -+#define R367_OFDM_CONSTCARR1 0xF0CC -+#define F367_OFDM_CONST_CARR_LO 0xF0CC00FF -+ -+/* CONSTCARR2 */ -+#define R367_OFDM_CONSTCARR2 0xF0CD -+#define F367_OFDM_CONST_CARR_HI 0xF0CD001F -+ -+/* ICONSTEL */ -+#define R367_OFDM_ICONSTEL 0xF0CE -+#define F367_OFDM_PICONSTEL 0xF0CE00FF -+ -+/* QCONSTEL */ -+#define R367_OFDM_QCONSTEL 0xF0CF -+#define F367_OFDM_PQCONSTEL 0xF0CF00FF -+ -+/* TSTBISTRES0 */ -+#define R367_OFDM_TSTBISTRES0 0xF0D0 -+#define F367_OFDM_BEND_PPM 0xF0D00080 -+#define F367_OFDM_BBAD_PPM 0xF0D00040 -+#define F367_OFDM_BEND_FFTW 0xF0D00020 -+#define F367_OFDM_BBAD_FFTW 0xF0D00010 -+#define F367_OFDM_BEND_FFT_BUF 0xF0D00008 -+#define F367_OFDM_BBAD_FFT_BUF 0xF0D00004 -+#define F367_OFDM_BEND_SYR 0xF0D00002 -+#define F367_OFDM_BBAD_SYR 0xF0D00001 -+ -+/* TSTBISTRES1 */ -+#define R367_OFDM_TSTBISTRES1 0xF0D1 -+#define F367_OFDM_BEND_CHC_CP 0xF0D10080 -+#define F367_OFDM_BBAD_CHC_CP 0xF0D10040 -+#define F367_OFDM_BEND_CHCI 0xF0D10020 -+#define F367_OFDM_BBAD_CHCI 0xF0D10010 -+#define F367_OFDM_BEND_BDI 0xF0D10008 -+#define F367_OFDM_BBAD_BDI 0xF0D10004 -+#define F367_OFDM_BEND_SDI 0xF0D10002 -+#define F367_OFDM_BBAD_SDI 0xF0D10001 -+ -+/* TSTBISTRES2 */ -+#define R367_OFDM_TSTBISTRES2 0xF0D2 -+#define F367_OFDM_BEND_CHC_INC 0xF0D20080 -+#define F367_OFDM_BBAD_CHC_INC 0xF0D20040 -+#define F367_OFDM_BEND_CHC_SPP 0xF0D20020 -+#define F367_OFDM_BBAD_CHC_SPP 0xF0D20010 -+#define F367_OFDM_BEND_CHC_CPP 0xF0D20008 -+#define F367_OFDM_BBAD_CHC_CPP 0xF0D20004 -+#define F367_OFDM_BEND_CHC_SP 0xF0D20002 -+#define F367_OFDM_BBAD_CHC_SP 0xF0D20001 -+ -+/* TSTBISTRES3 */ -+#define R367_OFDM_TSTBISTRES3 0xF0D3 -+#define F367_OFDM_BEND_QAM 0xF0D30080 -+#define F367_OFDM_BBAD_QAM 0xF0D30040 -+#define F367_OFDM_BEND_SFEC_VIT 0xF0D30020 -+#define F367_OFDM_BBAD_SFEC_VIT 0xF0D30010 -+#define F367_OFDM_BEND_SFEC_DLINE 0xF0D30008 -+#define F367_OFDM_BBAD_SFEC_DLINE 0xF0D30004 -+#define F367_OFDM_BEND_SFEC_HW 0xF0D30002 -+#define F367_OFDM_BBAD_SFEC_HW 0xF0D30001 -+ -+/* RF_AGC1 */ -+#define R367_RF_AGC1 0xF0D4 -+#define F367_RF_AGC1_LEVEL_HI 0xF0D400FF -+ -+/* RF_AGC2 */ -+#define R367_RF_AGC2 0xF0D5 -+#define F367_REF_ADGP 0xF0D50080 -+#define F367_STDBY_ADCGP 0xF0D50020 -+#define F367_CHANNEL_SEL 0xF0D5001C -+#define F367_RF_AGC1_LEVEL_LO 0xF0D50003 -+ -+/* ANADIGCTRL */ -+#define R367_ANADIGCTRL 0xF0D7 -+#define F367_SEL_CLKDEM 0xF0D70020 -+#define F367_EN_BUFFER_Q 0xF0D70010 -+#define F367_EN_BUFFER_I 0xF0D70008 -+#define F367_ADC_RIS_EGDE 0xF0D70004 -+#define F367_SGN_ADC 0xF0D70002 -+#define F367_SEL_AD12_SYNC 0xF0D70001 -+ -+/* PLLMDIV */ -+#define R367_PLLMDIV 0xF0D8 -+#define F367_PLL_MDIV 0xF0D800FF -+ -+/* PLLNDIV */ -+#define R367_PLLNDIV 0xF0D9 -+#define F367_PLL_NDIV 0xF0D900FF -+ -+/* PLLSETUP */ -+#define R367_PLLSETUP 0xF0DA -+#define F367_PLL_PDIV 0xF0DA0070 -+#define F367_PLL_KDIV 0xF0DA000F -+ -+/* DUAL_AD12 */ -+#define R367_DUAL_AD12 0xF0DB -+#define F367_FS20M 0xF0DB0020 -+#define F367_FS50M 0xF0DB0010 -+#define F367_INMODE0 0xF0DB0008 -+#define F367_POFFQ 0xF0DB0004 -+#define F367_POFFI 0xF0DB0002 -+#define F367_INMODE1 0xF0DB0001 -+ -+/* TSTBIST */ -+#define R367_TSTBIST 0xF0DC -+#define F367_TST_BYP_CLK 0xF0DC0080 -+#define F367_TST_GCLKENA_STD 0xF0DC0040 -+#define F367_TST_GCLKENA 0xF0DC0020 -+#define F367_TST_MEMBIST 0xF0DC001F -+ -+/* PAD_COMP_CTRL */ -+#define R367_PAD_COMP_CTRL 0xF0DD -+#define F367_COMPTQ 0xF0DD0010 -+#define F367_COMPEN 0xF0DD0008 -+#define F367_FREEZE2 0xF0DD0004 -+#define F367_SLEEP_INHBT 0xF0DD0002 -+#define F367_CHIP_SLEEP 0xF0DD0001 -+ -+/* PAD_COMP_WR */ -+#define R367_PAD_COMP_WR 0xF0DE -+#define F367_WR_ASRC 0xF0DE007F -+ -+/* PAD_COMP_RD */ -+#define R367_PAD_COMP_RD 0xF0DF -+#define F367_COMPOK 0xF0DF0080 -+#define F367_RD_ASRC 0xF0DF007F -+ -+/* SYR_TARGET_FFTADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_MSB 0xF100 -+#define F367_OFDM_SYR_START 0xF1000080 -+#define F367_OFDM_SYR_TARGET_FFTADJ_HI 0xF100000F -+ -+/* SYR_TARGET_FFTADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_LSB 0xF101 -+#define F367_OFDM_SYR_TARGET_FFTADJ_LO 0xF10100FF -+ -+/* SYR_TARGET_CHCADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_MSB 0xF102 -+#define F367_OFDM_SYR_TARGET_CHCADJ_HI 0xF102000F -+ -+/* SYR_TARGET_CHCADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_LSB 0xF103 -+#define F367_OFDM_SYR_TARGET_CHCADJ_LO 0xF10300FF -+ -+/* SYR_FLAG */ -+#define R367_OFDM_SYR_FLAG 0xF104 -+#define F367_OFDM_TRIG_FLG1 0xF1040080 -+#define F367_OFDM_TRIG_FLG0 0xF1040040 -+#define F367_OFDM_FFT_FLG1 0xF1040008 -+#define F367_OFDM_FFT_FLG0 0xF1040004 -+#define F367_OFDM_CHC_FLG1 0xF1040002 -+#define F367_OFDM_CHC_FLG0 0xF1040001 -+ -+/* CRL_TARGET1 */ -+#define R367_OFDM_CRL_TARGET1 0xF105 -+#define F367_OFDM_CRL_START 0xF1050080 -+#define F367_OFDM_CRL_TARGET_VHI 0xF105000F -+ -+/* CRL_TARGET2 */ -+#define R367_OFDM_CRL_TARGET2 0xF106 -+#define F367_OFDM_CRL_TARGET_HI 0xF10600FF -+ -+/* CRL_TARGET3 */ -+#define R367_OFDM_CRL_TARGET3 0xF107 -+#define F367_OFDM_CRL_TARGET_LO 0xF10700FF -+ -+/* CRL_TARGET4 */ -+#define R367_OFDM_CRL_TARGET4 0xF108 -+#define F367_OFDM_CRL_TARGET_VLO 0xF10800FF -+ -+/* CRL_FLAG */ -+#define R367_OFDM_CRL_FLAG 0xF109 -+#define F367_OFDM_CRL_FLAG1 0xF1090002 -+#define F367_OFDM_CRL_FLAG0 0xF1090001 -+ -+/* TRL_TARGET1 */ -+#define R367_OFDM_TRL_TARGET1 0xF10A -+#define F367_OFDM_TRL_TARGET_HI 0xF10A00FF -+ -+/* TRL_TARGET2 */ -+#define R367_OFDM_TRL_TARGET2 0xF10B -+#define F367_OFDM_TRL_TARGET_LO 0xF10B00FF -+ -+/* TRL_CHC */ -+#define R367_OFDM_TRL_CHC 0xF10C -+#define F367_OFDM_TRL_START 0xF10C0080 -+#define F367_OFDM_CHC_START 0xF10C0040 -+#define F367_OFDM_TRL_FLAG1 0xF10C0002 -+#define F367_OFDM_TRL_FLAG0 0xF10C0001 -+ -+/* CHC_SNR_TARG */ -+#define R367_OFDM_CHC_SNR_TARG 0xF10D -+#define F367_OFDM_CHC_SNR_TARGET 0xF10D00FF -+ -+/* TOP_TRACK */ -+#define R367_OFDM_TOP_TRACK 0xF10E -+#define F367_OFDM_TOP_START 0xF10E0080 -+#define F367_OFDM_FIRST_FLAG 0xF10E0070 -+#define F367_OFDM_TOP_FLAG1 0xF10E0008 -+#define F367_OFDM_TOP_FLAG0 0xF10E0004 -+#define F367_OFDM_CHC_FLAG1 0xF10E0002 -+#define F367_OFDM_CHC_FLAG0 0xF10E0001 -+ -+/* TRACKER_FREE1 */ -+#define R367_OFDM_TRACKER_FREE1 0xF10F -+#define F367_OFDM_TRACKER_FREE_1 0xF10F00FF -+ -+/* ERROR_CRL1 */ -+#define R367_OFDM_ERROR_CRL1 0xF110 -+#define F367_OFDM_ERROR_CRL_VHI 0xF11000FF -+ -+/* ERROR_CRL2 */ -+#define R367_OFDM_ERROR_CRL2 0xF111 -+#define F367_OFDM_ERROR_CRL_HI 0xF11100FF -+ -+/* ERROR_CRL3 */ -+#define R367_OFDM_ERROR_CRL3 0xF112 -+#define F367_OFDM_ERROR_CRL_LOI 0xF11200FF -+ -+/* ERROR_CRL4 */ -+#define R367_OFDM_ERROR_CRL4 0xF113 -+#define F367_OFDM_ERROR_CRL_VLO 0xF11300FF -+ -+/* DEC_NCO1 */ -+#define R367_OFDM_DEC_NCO1 0xF114 -+#define F367_OFDM_DEC_NCO_VHI 0xF11400FF -+ -+/* DEC_NCO2 */ -+#define R367_OFDM_DEC_NCO2 0xF115 -+#define F367_OFDM_DEC_NCO_HI 0xF11500FF -+ -+/* DEC_NCO3 */ -+#define R367_OFDM_DEC_NCO3 0xF116 -+#define F367_OFDM_DEC_NCO_LO 0xF11600FF -+ -+/* SNR */ -+#define R367_OFDM_SNR 0xF117 -+#define F367_OFDM_SNRATIO 0xF11700FF -+ -+/* SYR_FFTADJ1 */ -+#define R367_OFDM_SYR_FFTADJ1 0xF118 -+#define F367_OFDM_SYR_FFTADJ_HI 0xF11800FF -+ -+/* SYR_FFTADJ2 */ -+#define R367_OFDM_SYR_FFTADJ2 0xF119 -+#define F367_OFDM_SYR_FFTADJ_LO 0xF11900FF -+ -+/* SYR_CHCADJ1 */ -+#define R367_OFDM_SYR_CHCADJ1 0xF11A -+#define F367_OFDM_SYR_CHCADJ_HI 0xF11A00FF -+ -+/* SYR_CHCADJ2 */ -+#define R367_OFDM_SYR_CHCADJ2 0xF11B -+#define F367_OFDM_SYR_CHCADJ_LO 0xF11B00FF -+ -+/* SYR_OFF */ -+#define R367_OFDM_SYR_OFF 0xF11C -+#define F367_OFDM_SYR_OFFSET 0xF11C00FF -+ -+/* PPM_OFFSET1 */ -+#define R367_OFDM_PPM_OFFSET1 0xF11D -+#define F367_OFDM_PPM_OFFSET_HI 0xF11D00FF -+ -+/* PPM_OFFSET2 */ -+#define R367_OFDM_PPM_OFFSET2 0xF11E -+#define F367_OFDM_PPM_OFFSET_LO 0xF11E00FF -+ -+/* TRACKER_FREE2 */ -+#define R367_OFDM_TRACKER_FREE2 0xF11F -+#define F367_OFDM_TRACKER_FREE_2 0xF11F00FF -+ -+/* DEBG_LT10 */ -+#define R367_OFDM_DEBG_LT10 0xF120 -+#define F367_OFDM_DEBUG_LT10 0xF12000FF -+ -+/* DEBG_LT11 */ -+#define R367_OFDM_DEBG_LT11 0xF121 -+#define F367_OFDM_DEBUG_LT11 0xF12100FF -+ -+/* DEBG_LT12 */ -+#define R367_OFDM_DEBG_LT12 0xF122 -+#define F367_OFDM_DEBUG_LT12 0xF12200FF -+ -+/* DEBG_LT13 */ -+#define R367_OFDM_DEBG_LT13 0xF123 -+#define F367_OFDM_DEBUG_LT13 0xF12300FF -+ -+/* DEBG_LT14 */ -+#define R367_OFDM_DEBG_LT14 0xF124 -+#define F367_OFDM_DEBUG_LT14 0xF12400FF -+ -+/* DEBG_LT15 */ -+#define R367_OFDM_DEBG_LT15 0xF125 -+#define F367_OFDM_DEBUG_LT15 0xF12500FF -+ -+/* DEBG_LT16 */ -+#define R367_OFDM_DEBG_LT16 0xF126 -+#define F367_OFDM_DEBUG_LT16 0xF12600FF -+ -+/* DEBG_LT17 */ -+#define R367_OFDM_DEBG_LT17 0xF127 -+#define F367_OFDM_DEBUG_LT17 0xF12700FF -+ -+/* DEBG_LT18 */ -+#define R367_OFDM_DEBG_LT18 0xF128 -+#define F367_OFDM_DEBUG_LT18 0xF12800FF -+ -+/* DEBG_LT19 */ -+#define R367_OFDM_DEBG_LT19 0xF129 -+#define F367_OFDM_DEBUG_LT19 0xF12900FF -+ -+/* DEBG_LT1A */ -+#define R367_OFDM_DEBG_LT1A 0xF12A -+#define F367_OFDM_DEBUG_LT1A 0xF12A00FF -+ -+/* DEBG_LT1B */ -+#define R367_OFDM_DEBG_LT1B 0xF12B -+#define F367_OFDM_DEBUG_LT1B 0xF12B00FF -+ -+/* DEBG_LT1C */ -+#define R367_OFDM_DEBG_LT1C 0xF12C -+#define F367_OFDM_DEBUG_LT1C 0xF12C00FF -+ -+/* DEBG_LT1D */ -+#define R367_OFDM_DEBG_LT1D 0xF12D -+#define F367_OFDM_DEBUG_LT1D 0xF12D00FF -+ -+/* DEBG_LT1E */ -+#define R367_OFDM_DEBG_LT1E 0xF12E -+#define F367_OFDM_DEBUG_LT1E 0xF12E00FF -+ -+/* DEBG_LT1F */ -+#define R367_OFDM_DEBG_LT1F 0xF12F -+#define F367_OFDM_DEBUG_LT1F 0xF12F00FF -+ -+/* RCCFGH */ -+#define R367_OFDM_RCCFGH 0xF200 -+#define F367_OFDM_TSRCFIFO_DVBCI 0xF2000080 -+#define F367_OFDM_TSRCFIFO_SERIAL 0xF2000040 -+#define F367_OFDM_TSRCFIFO_DISABLE 0xF2000020 -+#define F367_OFDM_TSFIFO_2TORC 0xF2000010 -+#define F367_OFDM_TSRCFIFO_HSGNLOUT 0xF2000008 -+#define F367_OFDM_TSRCFIFO_ERRMODE 0xF2000006 -+#define F367_OFDM_RCCFGH_0 0xF2000001 -+ -+/* RCCFGM */ -+#define R367_OFDM_RCCFGM 0xF201 -+#define F367_OFDM_TSRCFIFO_MANSPEED 0xF20100C0 -+#define F367_OFDM_TSRCFIFO_PERMDATA 0xF2010020 -+#define F367_OFDM_TSRCFIFO_NONEWSGNL 0xF2010010 -+#define F367_OFDM_RCBYTE_OVERSAMPLING 0xF201000E -+#define F367_OFDM_TSRCFIFO_INVDATA 0xF2010001 -+ -+/* RCCFGL */ -+#define R367_OFDM_RCCFGL 0xF202 -+#define F367_OFDM_TSRCFIFO_BCLKDEL1CK 0xF20200C0 -+#define F367_OFDM_RCCFGL_5 0xF2020020 -+#define F367_OFDM_TSRCFIFO_DUTY50 0xF2020010 -+#define F367_OFDM_TSRCFIFO_NSGNL2DATA 0xF2020008 -+#define F367_OFDM_TSRCFIFO_DISSERMUX 0xF2020004 -+#define F367_OFDM_RCCFGL_1 0xF2020002 -+#define F367_OFDM_TSRCFIFO_STOPCKDIS 0xF2020001 -+ -+/* RCINSDELH */ -+#define R367_OFDM_RCINSDELH 0xF203 -+#define F367_OFDM_TSRCDEL_SYNCBYTE 0xF2030080 -+#define F367_OFDM_TSRCDEL_XXHEADER 0xF2030040 -+#define F367_OFDM_TSRCDEL_BBHEADER 0xF2030020 -+#define F367_OFDM_TSRCDEL_DATAFIELD 0xF2030010 -+#define F367_OFDM_TSRCINSDEL_ISCR 0xF2030008 -+#define F367_OFDM_TSRCINSDEL_NPD 0xF2030004 -+#define F367_OFDM_TSRCINSDEL_RSPARITY 0xF2030002 -+#define F367_OFDM_TSRCINSDEL_CRC8 0xF2030001 -+ -+/* RCINSDELM */ -+#define R367_OFDM_RCINSDELM 0xF204 -+#define F367_OFDM_TSRCINS_BBPADDING 0xF2040080 -+#define F367_OFDM_TSRCINS_BCHFEC 0xF2040040 -+#define F367_OFDM_TSRCINS_LDPCFEC 0xF2040020 -+#define F367_OFDM_TSRCINS_EMODCOD 0xF2040010 -+#define F367_OFDM_TSRCINS_TOKEN 0xF2040008 -+#define F367_OFDM_TSRCINS_XXXERR 0xF2040004 -+#define F367_OFDM_TSRCINS_MATYPE 0xF2040002 -+#define F367_OFDM_TSRCINS_UPL 0xF2040001 -+ -+/* RCINSDELL */ -+#define R367_OFDM_RCINSDELL 0xF205 -+#define F367_OFDM_TSRCINS_DFL 0xF2050080 -+#define F367_OFDM_TSRCINS_SYNCD 0xF2050040 -+#define F367_OFDM_TSRCINS_BLOCLEN 0xF2050020 -+#define F367_OFDM_TSRCINS_SIGPCOUNT 0xF2050010 -+#define F367_OFDM_TSRCINS_FIFO 0xF2050008 -+#define F367_OFDM_TSRCINS_REALPACK 0xF2050004 -+#define F367_OFDM_TSRCINS_TSCONFIG 0xF2050002 -+#define F367_OFDM_TSRCINS_LATENCY 0xF2050001 -+ -+/* RCSTATUS */ -+#define R367_OFDM_RCSTATUS 0xF206 -+#define F367_OFDM_TSRCFIFO_LINEOK 0xF2060080 -+#define F367_OFDM_TSRCFIFO_ERROR 0xF2060040 -+#define F367_OFDM_TSRCFIFO_DATA7 0xF2060020 -+#define F367_OFDM_RCSTATUS_4 0xF2060010 -+#define F367_OFDM_TSRCFIFO_DEMODSEL 0xF2060008 -+#define F367_OFDM_TSRC1FIFOSPEED_STORE 0xF2060004 -+#define F367_OFDM_RCSTATUS_1 0xF2060002 -+#define F367_OFDM_TSRCSERIAL_IMPOSSIBLE 0xF2060001 -+ -+/* RCSPEED */ -+#define R367_OFDM_RCSPEED 0xF207 -+#define F367_OFDM_TSRCFIFO_OUTSPEED 0xF20700FF -+ -+/* RCDEBUGM */ -+#define R367_OFDM_RCDEBUGM 0xF208 -+#define F367_OFDM_SD_UNSYNC 0xF2080080 -+#define F367_OFDM_ULFLOCK_DETECTM 0xF2080040 -+#define F367_OFDM_SUL_SELECTOS 0xF2080020 -+#define F367_OFDM_DILUL_NOSCRBLE 0xF2080010 -+#define F367_OFDM_NUL_SCRB 0xF2080008 -+#define F367_OFDM_UL_SCRB 0xF2080004 -+#define F367_OFDM_SCRAULBAD 0xF2080002 -+#define F367_OFDM_SCRAUL_UNSYNC 0xF2080001 -+ -+/* RCDEBUGL */ -+#define R367_OFDM_RCDEBUGL 0xF209 -+#define F367_OFDM_RS_ERR 0xF2090080 -+#define F367_OFDM_LLFLOCK_DETECTM 0xF2090040 -+#define F367_OFDM_NOT_SUL_SELECTOS 0xF2090020 -+#define F367_OFDM_DILLL_NOSCRBLE 0xF2090010 -+#define F367_OFDM_NLL_SCRB 0xF2090008 -+#define F367_OFDM_LL_SCRB 0xF2090004 -+#define F367_OFDM_SCRALLBAD 0xF2090002 -+#define F367_OFDM_SCRALL_UNSYNC 0xF2090001 -+ -+/* RCOBSCFG */ -+#define R367_OFDM_RCOBSCFG 0xF20A -+#define F367_OFDM_TSRCFIFO_OBSCFG 0xF20A00FF -+ -+/* RCOBSM */ -+#define R367_OFDM_RCOBSM 0xF20B -+#define F367_OFDM_TSRCFIFO_OBSDATA_HI 0xF20B00FF -+ -+/* RCOBSL */ -+#define R367_OFDM_RCOBSL 0xF20C -+#define F367_OFDM_TSRCFIFO_OBSDATA_LO 0xF20C00FF -+ -+/* RCFECSPY */ -+#define R367_OFDM_RCFECSPY 0xF210 -+#define F367_OFDM_SPYRC_ENABLE 0xF2100080 -+#define F367_OFDM_RCNO_SYNCBYTE 0xF2100040 -+#define F367_OFDM_RCSERIAL_MODE 0xF2100020 -+#define F367_OFDM_RCUNUSUAL_PACKET 0xF2100010 -+#define F367_OFDM_BERRCMETER_DATAMODE 0xF210000C -+#define F367_OFDM_BERRCMETER_LMODE 0xF2100002 -+#define F367_OFDM_BERRCMETER_RESET 0xF2100001 -+ -+/* RCFSPYCFG */ -+#define R367_OFDM_RCFSPYCFG 0xF211 -+#define F367_OFDM_FECSPYRC_INPUT 0xF21100C0 -+#define F367_OFDM_RCRST_ON_ERROR 0xF2110020 -+#define F367_OFDM_RCONE_SHOT 0xF2110010 -+#define F367_OFDM_RCI2C_MODE 0xF211000C -+#define F367_OFDM_SPYRC_HSTERESIS 0xF2110003 -+ -+/* RCFSPYDATA */ -+#define R367_OFDM_RCFSPYDATA 0xF212 -+#define F367_OFDM_SPYRC_STUFFING 0xF2120080 -+#define F367_OFDM_RCNOERR_PKTJITTER 0xF2120040 -+#define F367_OFDM_SPYRC_CNULLPKT 0xF2120020 -+#define F367_OFDM_SPYRC_OUTDATA_MODE 0xF212001F -+ -+/* RCFSPYOUT */ -+#define R367_OFDM_RCFSPYOUT 0xF213 -+#define F367_OFDM_FSPYRC_DIRECT 0xF2130080 -+#define F367_OFDM_RCFSPYOUT_6 0xF2130040 -+#define F367_OFDM_SPYRC_OUTDATA_BUS 0xF2130038 -+#define F367_OFDM_RCSTUFF_MODE 0xF2130007 -+ -+/* RCFSTATUS */ -+#define R367_OFDM_RCFSTATUS 0xF214 -+#define F367_OFDM_SPYRC_ENDSIM 0xF2140080 -+#define F367_OFDM_RCVALID_SIM 0xF2140040 -+#define F367_OFDM_RCFOUND_SIGNAL 0xF2140020 -+#define F367_OFDM_RCDSS_SYNCBYTE 0xF2140010 -+#define F367_OFDM_RCRESULT_STATE 0xF214000F -+ -+/* RCFGOODPACK */ -+#define R367_OFDM_RCFGOODPACK 0xF215 -+#define F367_OFDM_RCGOOD_PACKET 0xF21500FF -+ -+/* RCFPACKCNT */ -+#define R367_OFDM_RCFPACKCNT 0xF216 -+#define F367_OFDM_RCPACKET_COUNTER 0xF21600FF -+ -+/* RCFSPYMISC */ -+#define R367_OFDM_RCFSPYMISC 0xF217 -+#define F367_OFDM_RCLABEL_COUNTER 0xF21700FF -+ -+/* RCFBERCPT4 */ -+#define R367_OFDM_RCFBERCPT4 0xF218 -+#define F367_OFDM_FBERRCMETER_CPT_MMMMSB 0xF21800FF -+ -+/* RCFBERCPT3 */ -+#define R367_OFDM_RCFBERCPT3 0xF219 -+#define F367_OFDM_FBERRCMETER_CPT_MMMSB 0xF21900FF -+ -+/* RCFBERCPT2 */ -+#define R367_OFDM_RCFBERCPT2 0xF21A -+#define F367_OFDM_FBERRCMETER_CPT_MMSB 0xF21A00FF -+ -+/* RCFBERCPT1 */ -+#define R367_OFDM_RCFBERCPT1 0xF21B -+#define F367_OFDM_FBERRCMETER_CPT_MSB 0xF21B00FF -+ -+/* RCFBERCPT0 */ -+#define R367_OFDM_RCFBERCPT0 0xF21C -+#define F367_OFDM_FBERRCMETER_CPT_LSB 0xF21C00FF -+ -+/* RCFBERERR2 */ -+#define R367_OFDM_RCFBERERR2 0xF21D -+#define F367_OFDM_FBERRCMETER_ERR_HI 0xF21D00FF -+ -+/* RCFBERERR1 */ -+#define R367_OFDM_RCFBERERR1 0xF21E -+#define F367_OFDM_FBERRCMETER_ERR 0xF21E00FF -+ -+/* RCFBERERR0 */ -+#define R367_OFDM_RCFBERERR0 0xF21F -+#define F367_OFDM_FBERRCMETER_ERR_LO 0xF21F00FF -+ -+/* RCFSTATESM */ -+#define R367_OFDM_RCFSTATESM 0xF220 -+#define F367_OFDM_RCRSTATE_F 0xF2200080 -+#define F367_OFDM_RCRSTATE_E 0xF2200040 -+#define F367_OFDM_RCRSTATE_D 0xF2200020 -+#define F367_OFDM_RCRSTATE_C 0xF2200010 -+#define F367_OFDM_RCRSTATE_B 0xF2200008 -+#define F367_OFDM_RCRSTATE_A 0xF2200004 -+#define F367_OFDM_RCRSTATE_9 0xF2200002 -+#define F367_OFDM_RCRSTATE_8 0xF2200001 -+ -+/* RCFSTATESL */ -+#define R367_OFDM_RCFSTATESL 0xF221 -+#define F367_OFDM_RCRSTATE_7 0xF2210080 -+#define F367_OFDM_RCRSTATE_6 0xF2210040 -+#define F367_OFDM_RCRSTATE_5 0xF2210020 -+#define F367_OFDM_RCRSTATE_4 0xF2210010 -+#define F367_OFDM_RCRSTATE_3 0xF2210008 -+#define F367_OFDM_RCRSTATE_2 0xF2210004 -+#define F367_OFDM_RCRSTATE_1 0xF2210002 -+#define F367_OFDM_RCRSTATE_0 0xF2210001 -+ -+/* RCFSPYBER */ -+#define R367_OFDM_RCFSPYBER 0xF222 -+#define F367_OFDM_RCFSPYBER_7 0xF2220080 -+#define F367_OFDM_SPYRCOBS_XORREAD 0xF2220040 -+#define F367_OFDM_FSPYRCBER_OBSMODE 0xF2220020 -+#define F367_OFDM_FSPYRCBER_SYNCBYT 0xF2220010 -+#define F367_OFDM_FSPYRCBER_UNSYNC 0xF2220008 -+#define F367_OFDM_FSPYRCBER_CTIME 0xF2220007 -+ -+/* RCFSPYDISTM */ -+#define R367_OFDM_RCFSPYDISTM 0xF223 -+#define F367_OFDM_RCPKTTIME_DISTANCE_HI 0xF22300FF -+ -+/* RCFSPYDISTL */ -+#define R367_OFDM_RCFSPYDISTL 0xF224 -+#define F367_OFDM_RCPKTTIME_DISTANCE_LO 0xF22400FF -+ -+/* RCFSPYOBS7 */ -+#define R367_OFDM_RCFSPYOBS7 0xF228 -+#define F367_OFDM_RCSPYOBS_SPYFAIL 0xF2280080 -+#define F367_OFDM_RCSPYOBS_SPYFAIL1 0xF2280040 -+#define F367_OFDM_RCSPYOBS_ERROR 0xF2280020 -+#define F367_OFDM_RCSPYOBS_STROUT 0xF2280010 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE1 0xF228000F -+ -+/* RCFSPYOBS6 */ -+#define R367_OFDM_RCFSPYOBS6 0xF229 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE0 0xF22900F0 -+#define F367_OFDM_RCSPYOBS_RESULTSTATEM1 0xF229000F -+ -+/* RCFSPYOBS5 */ -+#define R367_OFDM_RCFSPYOBS5 0xF22A -+#define F367_OFDM_RCSPYOBS_BYTEOFPACKET1 0xF22A00FF -+ -+/* RCFSPYOBS4 */ -+#define R367_OFDM_RCFSPYOBS4 0xF22B -+#define F367_OFDM_RCSPYOBS_BYTEVALUE1 0xF22B00FF -+ -+/* RCFSPYOBS3 */ -+#define R367_OFDM_RCFSPYOBS3 0xF22C -+#define F367_OFDM_RCSPYOBS_DATA1 0xF22C00FF -+ -+/* RCFSPYOBS2 */ -+#define R367_OFDM_RCFSPYOBS2 0xF22D -+#define F367_OFDM_RCSPYOBS_DATA0 0xF22D00FF -+ -+/* RCFSPYOBS1 */ -+#define R367_OFDM_RCFSPYOBS1 0xF22E -+#define F367_OFDM_RCSPYOBS_DATAM1 0xF22E00FF -+ -+/* RCFSPYOBS0 */ -+#define R367_OFDM_RCFSPYOBS0 0xF22F -+#define F367_OFDM_RCSPYOBS_DATAM2 0xF22F00FF -+ -+/* TSGENERAL */ -+#define R367_TSGENERAL 0xF230 -+#define F367_TSGENERAL_7 0xF2300080 -+#define F367_TSGENERAL_6 0xF2300040 -+#define F367_TSFIFO_BCLK1ALL 0xF2300020 -+#define F367_TSGENERAL_4 0xF2300010 -+#define F367_MUXSTREAM_OUTMODE 0xF2300008 -+#define F367_TSFIFO_PERMPARAL 0xF2300006 -+#define F367_RST_REEDSOLO 0xF2300001 -+ -+/* RC1SPEED */ -+#define R367_RC1SPEED 0xF231 -+#define F367_TSRCFIFO1_OUTSPEED 0xF23100FF -+ -+/* TSGSTATUS */ -+#define R367_TSGSTATUS 0xF232 -+#define F367_TSGSTATUS_7 0xF2320080 -+#define F367_TSGSTATUS_6 0xF2320040 -+#define F367_RSMEM_FULL 0xF2320020 -+#define F367_RS_MULTCALC 0xF2320010 -+#define F367_RSIN_OVERTIME 0xF2320008 -+#define F367_TSFIFO3_DEMODSEL 0xF2320004 -+#define F367_TSFIFO2_DEMODSEL 0xF2320002 -+#define F367_TSFIFO1_DEMODSEL 0xF2320001 -+ -+ -+/* FECM */ -+#define R367_OFDM_FECM 0xF233 -+#define F367_OFDM_DSS_DVB 0xF2330080 -+#define F367_OFDM_DEMOD_BYPASS 0xF2330040 -+#define F367_OFDM_CMP_SLOWMODE 0xF2330020 -+#define F367_OFDM_DSS_SRCH 0xF2330010 -+#define F367_OFDM_FECM_3 0xF2330008 -+#define F367_OFDM_DIFF_MODEVIT 0xF2330004 -+#define F367_OFDM_SYNCVIT 0xF2330002 -+#define F367_OFDM_I2CSYM 0xF2330001 -+ -+/* VTH12 */ -+#define R367_OFDM_VTH12 0xF234 -+#define F367_OFDM_VTH_12 0xF23400FF -+ -+/* VTH23 */ -+#define R367_OFDM_VTH23 0xF235 -+#define F367_OFDM_VTH_23 0xF23500FF -+ -+/* VTH34 */ -+#define R367_OFDM_VTH34 0xF236 -+#define F367_OFDM_VTH_34 0xF23600FF -+ -+/* VTH56 */ -+#define R367_OFDM_VTH56 0xF237 -+#define F367_OFDM_VTH_56 0xF23700FF -+ -+/* VTH67 */ -+#define R367_OFDM_VTH67 0xF238 -+#define F367_OFDM_VTH_67 0xF23800FF -+ -+/* VTH78 */ -+#define R367_OFDM_VTH78 0xF239 -+#define F367_OFDM_VTH_78 0xF23900FF -+ -+/* VITCURPUN */ -+#define R367_OFDM_VITCURPUN 0xF23A -+#define F367_OFDM_VIT_MAPPING 0xF23A00E0 -+#define F367_OFDM_VIT_CURPUN 0xF23A001F -+ -+/* VERROR */ -+#define R367_OFDM_VERROR 0xF23B -+#define F367_OFDM_REGERR_VIT 0xF23B00FF -+ -+/* PRVIT */ -+#define R367_OFDM_PRVIT 0xF23C -+#define F367_OFDM_PRVIT_7 0xF23C0080 -+#define F367_OFDM_DIS_VTHLOCK 0xF23C0040 -+#define F367_OFDM_E7_8VIT 0xF23C0020 -+#define F367_OFDM_E6_7VIT 0xF23C0010 -+#define F367_OFDM_E5_6VIT 0xF23C0008 -+#define F367_OFDM_E3_4VIT 0xF23C0004 -+#define F367_OFDM_E2_3VIT 0xF23C0002 -+#define F367_OFDM_E1_2VIT 0xF23C0001 -+ -+/* VAVSRVIT */ -+#define R367_OFDM_VAVSRVIT 0xF23D -+#define F367_OFDM_AMVIT 0xF23D0080 -+#define F367_OFDM_FROZENVIT 0xF23D0040 -+#define F367_OFDM_SNVIT 0xF23D0030 -+#define F367_OFDM_TOVVIT 0xF23D000C -+#define F367_OFDM_HYPVIT 0xF23D0003 -+ -+/* VSTATUSVIT */ -+#define R367_OFDM_VSTATUSVIT 0xF23E -+#define F367_OFDM_VITERBI_ON 0xF23E0080 -+#define F367_OFDM_END_LOOPVIT 0xF23E0040 -+#define F367_OFDM_VITERBI_DEPRF 0xF23E0020 -+#define F367_OFDM_PRFVIT 0xF23E0010 -+#define F367_OFDM_LOCKEDVIT 0xF23E0008 -+#define F367_OFDM_VITERBI_DELOCK 0xF23E0004 -+#define F367_OFDM_VIT_DEMODSEL 0xF23E0002 -+#define F367_OFDM_VITERBI_COMPOUT 0xF23E0001 -+ -+/* VTHINUSE */ -+#define R367_OFDM_VTHINUSE 0xF23F -+#define F367_OFDM_VIT_INUSE 0xF23F00FF -+ -+/* KDIV12 */ -+#define R367_OFDM_KDIV12 0xF240 -+#define F367_OFDM_KDIV12_MANUAL 0xF2400080 -+#define F367_OFDM_K_DIVIDER_12 0xF240007F -+ -+/* KDIV23 */ -+#define R367_OFDM_KDIV23 0xF241 -+#define F367_OFDM_KDIV23_MANUAL 0xF2410080 -+#define F367_OFDM_K_DIVIDER_23 0xF241007F -+ -+/* KDIV34 */ -+#define R367_OFDM_KDIV34 0xF242 -+#define F367_OFDM_KDIV34_MANUAL 0xF2420080 -+#define F367_OFDM_K_DIVIDER_34 0xF242007F -+ -+/* KDIV56 */ -+#define R367_OFDM_KDIV56 0xF243 -+#define F367_OFDM_KDIV56_MANUAL 0xF2430080 -+#define F367_OFDM_K_DIVIDER_56 0xF243007F -+ -+/* KDIV67 */ -+#define R367_OFDM_KDIV67 0xF244 -+#define F367_OFDM_KDIV67_MANUAL 0xF2440080 -+#define F367_OFDM_K_DIVIDER_67 0xF244007F -+ -+/* KDIV78 */ -+#define R367_OFDM_KDIV78 0xF245 -+#define F367_OFDM_KDIV78_MANUAL 0xF2450080 -+#define F367_OFDM_K_DIVIDER_78 0xF245007F -+ -+/* SIGPOWER */ -+#define R367_OFDM_SIGPOWER 0xF246 -+#define F367_OFDM_SIGPOWER_MANUAL 0xF2460080 -+#define F367_OFDM_SIG_POWER 0xF246007F -+ -+/* DEMAPVIT */ -+#define R367_OFDM_DEMAPVIT 0xF247 -+#define F367_OFDM_DEMAPVIT_7 0xF2470080 -+#define F367_OFDM_K_DIVIDER_VIT 0xF247007F -+ -+/* VITSCALE */ -+#define R367_OFDM_VITSCALE 0xF248 -+#define F367_OFDM_NVTH_NOSRANGE 0xF2480080 -+#define F367_OFDM_VERROR_MAXMODE 0xF2480040 -+#define F367_OFDM_KDIV_MODE 0xF2480030 -+#define F367_OFDM_NSLOWSN_LOCKED 0xF2480008 -+#define F367_OFDM_DELOCK_PRFLOSS 0xF2480004 -+#define F367_OFDM_DIS_RSFLOCK 0xF2480002 -+#define F367_OFDM_VITSCALE_0 0xF2480001 -+ -+/* FFEC1PRG */ -+#define R367_OFDM_FFEC1PRG 0xF249 -+#define F367_OFDM_FDSS_DVB 0xF2490080 -+#define F367_OFDM_FDSS_SRCH 0xF2490040 -+#define F367_OFDM_FFECPROG_5 0xF2490020 -+#define F367_OFDM_FFECPROG_4 0xF2490010 -+#define F367_OFDM_FFECPROG_3 0xF2490008 -+#define F367_OFDM_FFECPROG_2 0xF2490004 -+#define F367_OFDM_FTS1_DISABLE 0xF2490002 -+#define F367_OFDM_FTS2_DISABLE 0xF2490001 -+ -+/* FVITCURPUN */ -+#define R367_OFDM_FVITCURPUN 0xF24A -+#define F367_OFDM_FVIT_MAPPING 0xF24A00E0 -+#define F367_OFDM_FVIT_CURPUN 0xF24A001F -+ -+/* FVERROR */ -+#define R367_OFDM_FVERROR 0xF24B -+#define F367_OFDM_FREGERR_VIT 0xF24B00FF -+ -+/* FVSTATUSVIT */ -+#define R367_OFDM_FVSTATUSVIT 0xF24C -+#define F367_OFDM_FVITERBI_ON 0xF24C0080 -+#define F367_OFDM_F1END_LOOPVIT 0xF24C0040 -+#define F367_OFDM_FVITERBI_DEPRF 0xF24C0020 -+#define F367_OFDM_FPRFVIT 0xF24C0010 -+#define F367_OFDM_FLOCKEDVIT 0xF24C0008 -+#define F367_OFDM_FVITERBI_DELOCK 0xF24C0004 -+#define F367_OFDM_FVIT_DEMODSEL 0xF24C0002 -+#define F367_OFDM_FVITERBI_COMPOUT 0xF24C0001 -+ -+/* DEBUG_LT1 */ -+#define R367_OFDM_DEBUG_LT1 0xF24D -+#define F367_OFDM_DBG_LT1 0xF24D00FF -+ -+/* DEBUG_LT2 */ -+#define R367_OFDM_DEBUG_LT2 0xF24E -+#define F367_OFDM_DBG_LT2 0xF24E00FF -+ -+/* DEBUG_LT3 */ -+#define R367_OFDM_DEBUG_LT3 0xF24F -+#define F367_OFDM_DBG_LT3 0xF24F00FF -+ -+ /* TSTSFMET */ -+#define R367_OFDM_TSTSFMET 0xF250 -+#define F367_OFDM_TSTSFEC_METRIQUES 0xF25000FF -+ -+ /* SELOUT */ -+#define R367_OFDM_SELOUT 0xF252 -+#define F367_OFDM_EN_SYNC 0xF2520080 -+#define F367_OFDM_EN_TBUSDEMAP 0xF2520040 -+#define F367_OFDM_SELOUT_5 0xF2520020 -+#define F367_OFDM_SELOUT_4 0xF2520010 -+#define F367_OFDM_TSTSYNCHRO_MODE 0xF2520002 -+ -+ /* TSYNC */ -+#define R367_OFDM_TSYNC 0xF253 -+#define F367_OFDM_CURPUN_INCMODE 0xF2530080 -+#define F367_OFDM_CERR_TSTMODE 0xF2530040 -+#define F367_OFDM_SHIFTSOF_MODE 0xF2530030 -+#define F367_OFDM_SLOWPHA_MODE 0xF2530008 -+#define F367_OFDM_PXX_BYPALL 0xF2530004 -+#define F367_OFDM_FROTA45_FIRST 0xF2530002 -+#define F367_OFDM_TST_BCHERROR 0xF2530001 -+ -+ /* TSTERR */ -+#define R367_OFDM_TSTERR 0xF254 -+#define F367_OFDM_TST_LONGPKT 0xF2540080 -+#define F367_OFDM_TST_ISSYION 0xF2540040 -+#define F367_OFDM_TST_NPDON 0xF2540020 -+#define F367_OFDM_TSTERR_4 0xF2540010 -+#define F367_OFDM_TRACEBACK_MODE 0xF2540008 -+#define F367_OFDM_TST_RSPARITY 0xF2540004 -+#define F367_OFDM_METRIQUE_MODE 0xF2540003 -+ -+ /* TSFSYNC */ -+#define R367_OFDM_TSFSYNC 0xF255 -+#define F367_OFDM_EN_SFECSYNC 0xF2550080 -+#define F367_OFDM_EN_SFECDEMAP 0xF2550040 -+#define F367_OFDM_SFCERR_TSTMODE 0xF2550020 -+#define F367_OFDM_SFECPXX_BYPALL 0xF2550010 -+#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F -+ -+ /* TSTSFERR */ -+#define R367_OFDM_TSTSFERR 0xF256 -+#define F367_OFDM_TSTSTERR_7 0xF2560080 -+#define F367_OFDM_TSTSTERR_6 0xF2560040 -+#define F367_OFDM_TSTSTERR_5 0xF2560020 -+#define F367_OFDM_TSTSTERR_4 0xF2560010 -+#define F367_OFDM_SFECTRACEBACK_MODE 0xF2560008 -+#define F367_OFDM_SFEC_NCONVPROG 0xF2560004 -+#define F367_OFDM_SFECMETRIQUE_MODE 0xF2560003 -+ -+ /* TSTTSSF1 */ -+#define R367_OFDM_TSTTSSF1 0xF258 -+#define F367_OFDM_TSTERSSF 0xF2580080 -+#define F367_OFDM_TSTTSSFEN 0xF2580040 -+#define F367_OFDM_SFEC_OUTMODE 0xF2580030 -+#define F367_OFDM_XLSF_NOFTHRESHOLD 0xF2580008 -+#define F367_OFDM_TSTTSSF_STACKSEL 0xF2580007 -+ -+ /* TSTTSSF2 */ -+#define R367_OFDM_TSTTSSF2 0xF259 -+#define F367_OFDM_DILSF_DBBHEADER 0xF2590080 -+#define F367_OFDM_TSTTSSF_DISBUG 0xF2590040 -+#define F367_OFDM_TSTTSSF_NOBADSTART 0xF2590020 -+#define F367_OFDM_TSTTSSF_SELECT 0xF259001F -+ -+ /* TSTTSSF3 */ -+#define R367_OFDM_TSTTSSF3 0xF25A -+#define F367_OFDM_TSTTSSF3_7 0xF25A0080 -+#define F367_OFDM_TSTTSSF3_6 0xF25A0040 -+#define F367_OFDM_TSTTSSF3_5 0xF25A0020 -+#define F367_OFDM_TSTTSSF3_4 0xF25A0010 -+#define F367_OFDM_TSTTSSF3_3 0xF25A0008 -+#define F367_OFDM_TSTTSSF3_2 0xF25A0004 -+#define F367_OFDM_TSTTSSF3_1 0xF25A0002 -+#define F367_OFDM_DISSF_CLKENABLE 0xF25A0001 -+ -+ /* TSTTS1 */ -+#define R367_OFDM_TSTTS1 0xF25C -+#define F367_OFDM_TSTERS 0xF25C0080 -+#define F367_OFDM_TSFIFO_DSSSYNCB 0xF25C0040 -+#define F367_OFDM_TSTTS_FSPYBEFRS 0xF25C0020 -+#define F367_OFDM_NFORCE_SYNCBYTE 0xF25C0010 -+#define F367_OFDM_XL_NOFTHRESHOLD 0xF25C0008 -+#define F367_OFDM_TSTTS_FRFORCEPKT 0xF25C0004 -+#define F367_OFDM_DESCR_NOTAUTO 0xF25C0002 -+#define F367_OFDM_TSTTSEN 0xF25C0001 -+ -+ /* TSTTS2 */ -+#define R367_OFDM_TSTTS2 0xF25D -+#define F367_OFDM_DIL_DBBHEADER 0xF25D0080 -+#define F367_OFDM_TSTTS_NOBADXXX 0xF25D0040 -+#define F367_OFDM_TSFIFO_DELSPEEDUP 0xF25D0020 -+#define F367_OFDM_TSTTS_SELECT 0xF25D001F -+ -+ /* TSTTS3 */ -+#define R367_OFDM_TSTTS3 0xF25E -+#define F367_OFDM_TSTTS_NOPKTGAIN 0xF25E0080 -+#define F367_OFDM_TSTTS_NOPKTENE 0xF25E0040 -+#define F367_OFDM_TSTTS_ISOLATION 0xF25E0020 -+#define F367_OFDM_TSTTS_DISBUG 0xF25E0010 -+#define F367_OFDM_TSTTS_NOBADSTART 0xF25E0008 -+#define F367_OFDM_TSTTS_STACKSEL 0xF25E0007 -+ -+ /* TSTTS4 */ -+#define R367_OFDM_TSTTS4 0xF25F -+#define F367_OFDM_TSTTS4_7 0xF25F0080 -+#define F367_OFDM_TSTTS4_6 0xF25F0040 -+#define F367_OFDM_TSTTS4_5 0xF25F0020 -+#define F367_OFDM_TSTTS_DISDSTATE 0xF25F0010 -+#define F367_OFDM_TSTTS_FASTNOSYNC 0xF25F0008 -+#define F367_OFDM_EXT_FECSPYIN 0xF25F0004 -+#define F367_OFDM_TSTTS_NODPZERO 0xF25F0002 -+#define F367_OFDM_TSTTS_NODIV3 0xF25F0001 -+ -+ /* TSTTSRC */ -+#define R367_OFDM_TSTTSRC 0xF26C -+#define F367_OFDM_TSTTSRC_7 0xF26C0080 -+#define F367_OFDM_TSRCFIFO_DSSSYNCB 0xF26C0040 -+#define F367_OFDM_TSRCFIFO_DPUNACTIVE 0xF26C0020 -+#define F367_OFDM_TSRCFIFO_DELSPEEDUP 0xF26C0010 -+#define F367_OFDM_TSTTSRC_NODIV3 0xF26C0008 -+#define F367_OFDM_TSTTSRC_FRFORCEPKT 0xF26C0004 -+#define F367_OFDM_SAT25_SDDORIGINE 0xF26C0002 -+#define F367_OFDM_TSTTSRC_INACTIVE 0xF26C0001 -+ -+ /* TSTTSRS */ -+#define R367_OFDM_TSTTSRS 0xF26D -+#define F367_OFDM_TSTTSRS_7 0xF26D0080 -+#define F367_OFDM_TSTTSRS_6 0xF26D0040 -+#define F367_OFDM_TSTTSRS_5 0xF26D0020 -+#define F367_OFDM_TSTTSRS_4 0xF26D0010 -+#define F367_OFDM_TSTTSRS_3 0xF26D0008 -+#define F367_OFDM_TSTTSRS_2 0xF26D0004 -+#define F367_OFDM_TSTRS_DISRS2 0xF26D0002 -+#define F367_OFDM_TSTRS_DISRS1 0xF26D0001 -+ -+/* TSSTATEM */ -+#define R367_OFDM_TSSTATEM 0xF270 -+#define F367_OFDM_TSDIL_ON 0xF2700080 -+#define F367_OFDM_TSSKIPRS_ON 0xF2700040 -+#define F367_OFDM_TSRS_ON 0xF2700020 -+#define F367_OFDM_TSDESCRAMB_ON 0xF2700010 -+#define F367_OFDM_TSFRAME_MODE 0xF2700008 -+#define F367_OFDM_TS_DISABLE 0xF2700004 -+#define F367_OFDM_TSACM_MODE 0xF2700002 -+#define F367_OFDM_TSOUT_NOSYNC 0xF2700001 -+ -+/* TSSTATEL */ -+#define R367_OFDM_TSSTATEL 0xF271 -+#define F367_OFDM_TSNOSYNCBYTE 0xF2710080 -+#define F367_OFDM_TSPARITY_ON 0xF2710040 -+#define F367_OFDM_TSSYNCOUTRS_ON 0xF2710020 -+#define F367_OFDM_TSDVBS2_MODE 0xF2710010 -+#define F367_OFDM_TSISSYI_ON 0xF2710008 -+#define F367_OFDM_TSNPD_ON 0xF2710004 -+#define F367_OFDM_TSCRC8_ON 0xF2710002 -+#define F367_OFDM_TSDSS_PACKET 0xF2710001 -+ -+/* TSCFGH */ -+#define R367_OFDM_TSCFGH 0xF272 -+#define F367_OFDM_TSFIFO_DVBCI 0xF2720080 -+#define F367_OFDM_TSFIFO_SERIAL 0xF2720040 -+#define F367_OFDM_TSFIFO_TEIUPDATE 0xF2720020 -+#define F367_OFDM_TSFIFO_DUTY50 0xF2720010 -+#define F367_OFDM_TSFIFO_HSGNLOUT 0xF2720008 -+#define F367_OFDM_TSFIFO_ERRMODE 0xF2720006 -+#define F367_OFDM_RST_HWARE 0xF2720001 -+ -+/* TSCFGM */ -+#define R367_OFDM_TSCFGM 0xF273 -+#define F367_OFDM_TSFIFO_MANSPEED 0xF27300C0 -+#define F367_OFDM_TSFIFO_PERMDATA 0xF2730020 -+#define F367_OFDM_TSFIFO_NONEWSGNL 0xF2730010 -+#define F367_OFDM_TSFIFO_BITSPEED 0xF2730008 -+#define F367_OFDM_NPD_SPECDVBS2 0xF2730004 -+#define F367_OFDM_TSFIFO_STOPCKDIS 0xF2730002 -+#define F367_OFDM_TSFIFO_INVDATA 0xF2730001 -+ -+/* TSCFGL */ -+#define R367_OFDM_TSCFGL 0xF274 -+#define F367_OFDM_TSFIFO_BCLKDEL1CK 0xF27400C0 -+#define F367_OFDM_BCHERROR_MODE 0xF2740030 -+#define F367_OFDM_TSFIFO_NSGNL2DATA 0xF2740008 -+#define F367_OFDM_TSFIFO_EMBINDVB 0xF2740004 -+#define F367_OFDM_TSFIFO_DPUNACT 0xF2740002 -+#define F367_OFDM_TSFIFO_NPDOFF 0xF2740001 -+ -+/* TSSYNC */ -+#define R367_OFDM_TSSYNC 0xF275 -+#define F367_OFDM_TSFIFO_PERMUTE 0xF2750080 -+#define F367_OFDM_TSFIFO_FISCR3B 0xF2750060 -+#define F367_OFDM_TSFIFO_SYNCMODE 0xF2750018 -+#define F367_OFDM_TSFIFO_SYNCSEL 0xF2750007 -+ -+/* TSINSDELH */ -+#define R367_OFDM_TSINSDELH 0xF276 -+#define F367_OFDM_TSDEL_SYNCBYTE 0xF2760080 -+#define F367_OFDM_TSDEL_XXHEADER 0xF2760040 -+#define F367_OFDM_TSDEL_BBHEADER 0xF2760020 -+#define F367_OFDM_TSDEL_DATAFIELD 0xF2760010 -+#define F367_OFDM_TSINSDEL_ISCR 0xF2760008 -+#define F367_OFDM_TSINSDEL_NPD 0xF2760004 -+#define F367_OFDM_TSINSDEL_RSPARITY 0xF2760002 -+#define F367_OFDM_TSINSDEL_CRC8 0xF2760001 -+ -+/* TSINSDELM */ -+#define R367_OFDM_TSINSDELM 0xF277 -+#define F367_OFDM_TSINS_BBPADDING 0xF2770080 -+#define F367_OFDM_TSINS_BCHFEC 0xF2770040 -+#define F367_OFDM_TSINS_LDPCFEC 0xF2770020 -+#define F367_OFDM_TSINS_EMODCOD 0xF2770010 -+#define F367_OFDM_TSINS_TOKEN 0xF2770008 -+#define F367_OFDM_TSINS_XXXERR 0xF2770004 -+#define F367_OFDM_TSINS_MATYPE 0xF2770002 -+#define F367_OFDM_TSINS_UPL 0xF2770001 -+ -+/* TSINSDELL */ -+#define R367_OFDM_TSINSDELL 0xF278 -+#define F367_OFDM_TSINS_DFL 0xF2780080 -+#define F367_OFDM_TSINS_SYNCD 0xF2780040 -+#define F367_OFDM_TSINS_BLOCLEN 0xF2780020 -+#define F367_OFDM_TSINS_SIGPCOUNT 0xF2780010 -+#define F367_OFDM_TSINS_FIFO 0xF2780008 -+#define F367_OFDM_TSINS_REALPACK 0xF2780004 -+#define F367_OFDM_TSINS_TSCONFIG 0xF2780002 -+#define F367_OFDM_TSINS_LATENCY 0xF2780001 -+ -+/* TSDIVN */ -+#define R367_OFDM_TSDIVN 0xF279 -+#define F367_OFDM_TSFIFO_LOWSPEED 0xF2790080 -+#define F367_OFDM_BYTE_OVERSAMPLING 0xF2790070 -+#define F367_OFDM_TSMANUAL_PACKETNBR 0xF279000F -+ -+/* TSDIVPM */ -+#define R367_OFDM_TSDIVPM 0xF27A -+#define F367_OFDM_TSMANUAL_P_HI 0xF27A00FF -+ -+/* TSDIVPL */ -+#define R367_OFDM_TSDIVPL 0xF27B -+#define F367_OFDM_TSMANUAL_P_LO 0xF27B00FF -+ -+/* TSDIVQM */ -+#define R367_OFDM_TSDIVQM 0xF27C -+#define F367_OFDM_TSMANUAL_Q_HI 0xF27C00FF -+ -+/* TSDIVQL */ -+#define R367_OFDM_TSDIVQL 0xF27D -+#define F367_OFDM_TSMANUAL_Q_LO 0xF27D00FF -+ -+/* TSDILSTKM */ -+#define R367_OFDM_TSDILSTKM 0xF27E -+#define F367_OFDM_TSFIFO_DILSTK_HI 0xF27E00FF -+ -+/* TSDILSTKL */ -+#define R367_OFDM_TSDILSTKL 0xF27F -+#define F367_OFDM_TSFIFO_DILSTK_LO 0xF27F00FF -+ -+/* TSSPEED */ -+#define R367_OFDM_TSSPEED 0xF280 -+#define F367_OFDM_TSFIFO_OUTSPEED 0xF28000FF -+ -+/* TSSTATUS */ -+#define R367_OFDM_TSSTATUS 0xF281 -+#define F367_OFDM_TSFIFO_LINEOK 0xF2810080 -+#define F367_OFDM_TSFIFO_ERROR 0xF2810040 -+#define F367_OFDM_TSFIFO_DATA7 0xF2810020 -+#define F367_OFDM_TSFIFO_NOSYNC 0xF2810010 -+#define F367_OFDM_ISCR_INITIALIZED 0xF2810008 -+#define F367_OFDM_ISCR_UPDATED 0xF2810004 -+#define F367_OFDM_SOFFIFO_UNREGUL 0xF2810002 -+#define F367_OFDM_DIL_READY 0xF2810001 -+ -+/* TSSTATUS2 */ -+#define R367_OFDM_TSSTATUS2 0xF282 -+#define F367_OFDM_TSFIFO_DEMODSEL 0xF2820080 -+#define F367_OFDM_TSFIFOSPEED_STORE 0xF2820040 -+#define F367_OFDM_DILXX_RESET 0xF2820020 -+#define F367_OFDM_TSSERIAL_IMPOSSIBLE 0xF2820010 -+#define F367_OFDM_TSFIFO_UNDERSPEED 0xF2820008 -+#define F367_OFDM_BITSPEED_EVENT 0xF2820004 -+#define F367_OFDM_UL_SCRAMBDETECT 0xF2820002 -+#define F367_OFDM_ULDTV67_FALSELOCK 0xF2820001 -+ -+/* TSBITRATEM */ -+#define R367_OFDM_TSBITRATEM 0xF283 -+#define F367_OFDM_TSFIFO_BITRATE_HI 0xF28300FF -+ -+/* TSBITRATEL */ -+#define R367_OFDM_TSBITRATEL 0xF284 -+#define F367_OFDM_TSFIFO_BITRATE_LO 0xF28400FF -+ -+/* TSPACKLENM */ -+#define R367_OFDM_TSPACKLENM 0xF285 -+#define F367_OFDM_TSFIFO_PACKCPT 0xF28500E0 -+#define F367_OFDM_DIL_RPLEN_HI 0xF285001F -+ -+/* TSPACKLENL */ -+#define R367_OFDM_TSPACKLENL 0xF286 -+#define F367_OFDM_DIL_RPLEN_LO 0xF28600FF -+ -+/* TSBLOCLENM */ -+#define R367_OFDM_TSBLOCLENM 0xF287 -+#define F367_OFDM_TSFIFO_PFLEN_HI 0xF28700FF -+ -+/* TSBLOCLENL */ -+#define R367_OFDM_TSBLOCLENL 0xF288 -+#define F367_OFDM_TSFIFO_PFLEN_LO 0xF28800FF -+ -+/* TSDLYH */ -+#define R367_OFDM_TSDLYH 0xF289 -+#define F367_OFDM_SOFFIFO_TSTIMEVALID 0xF2890080 -+#define F367_OFDM_SOFFIFO_SPEEDUP 0xF2890040 -+#define F367_OFDM_SOFFIFO_STOP 0xF2890020 -+#define F367_OFDM_SOFFIFO_REGULATED 0xF2890010 -+#define F367_OFDM_SOFFIFO_REALSBOFF_HI 0xF289000F -+ -+/* TSDLYM */ -+#define R367_OFDM_TSDLYM 0xF28A -+#define F367_OFDM_SOFFIFO_REALSBOFF_MED 0xF28A00FF -+ -+/* TSDLYL */ -+#define R367_OFDM_TSDLYL 0xF28B -+#define F367_OFDM_SOFFIFO_REALSBOFF_LO 0xF28B00FF -+ -+/* TSNPDAV */ -+#define R367_OFDM_TSNPDAV 0xF28C -+#define F367_OFDM_TSNPD_AVERAGE 0xF28C00FF -+ -+/* TSBUFSTATH */ -+#define R367_OFDM_TSBUFSTATH 0xF28D -+#define F367_OFDM_TSISCR_3BYTES 0xF28D0080 -+#define F367_OFDM_TSISCR_NEWDATA 0xF28D0040 -+#define F367_OFDM_TSISCR_BUFSTAT_HI 0xF28D003F -+ -+/* TSBUFSTATM */ -+#define R367_OFDM_TSBUFSTATM 0xF28E -+#define F367_OFDM_TSISCR_BUFSTAT_MED 0xF28E00FF -+ -+/* TSBUFSTATL */ -+#define R367_OFDM_TSBUFSTATL 0xF28F -+#define F367_OFDM_TSISCR_BUFSTAT_LO 0xF28F00FF -+ -+/* TSDEBUGM */ -+#define R367_OFDM_TSDEBUGM 0xF290 -+#define F367_OFDM_TSFIFO_ILLPACKET 0xF2900080 -+#define F367_OFDM_DIL_NOSYNC 0xF2900040 -+#define F367_OFDM_DIL_ISCR 0xF2900020 -+#define F367_OFDM_DILOUT_BSYNCB 0xF2900010 -+#define F367_OFDM_TSFIFO_EMPTYPKT 0xF2900008 -+#define F367_OFDM_TSFIFO_EMPTYRD 0xF2900004 -+#define F367_OFDM_SOFFIFO_STOPM 0xF2900002 -+#define F367_OFDM_SOFFIFO_SPEEDUPM 0xF2900001 -+ -+/* TSDEBUGL */ -+#define R367_OFDM_TSDEBUGL 0xF291 -+#define F367_OFDM_TSFIFO_PACKLENFAIL 0xF2910080 -+#define F367_OFDM_TSFIFO_SYNCBFAIL 0xF2910040 -+#define F367_OFDM_TSFIFO_VITLIBRE 0xF2910020 -+#define F367_OFDM_TSFIFO_BOOSTSPEEDM 0xF2910010 -+#define F367_OFDM_TSFIFO_UNDERSPEEDM 0xF2910008 -+#define F367_OFDM_TSFIFO_ERROR_EVNT 0xF2910004 -+#define F367_OFDM_TSFIFO_FULL 0xF2910002 -+#define F367_OFDM_TSFIFO_OVERFLOWM 0xF2910001 -+ -+/* TSDLYSETH */ -+#define R367_OFDM_TSDLYSETH 0xF292 -+#define F367_OFDM_SOFFIFO_OFFSET 0xF29200E0 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_HI 0xF292001F -+ -+/* TSDLYSETM */ -+#define R367_OFDM_TSDLYSETM 0xF293 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_MED 0xF29300FF -+ -+/* TSDLYSETL */ -+#define R367_OFDM_TSDLYSETL 0xF294 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_LO 0xF29400FF -+ -+/* TSOBSCFG */ -+#define R367_OFDM_TSOBSCFG 0xF295 -+#define F367_OFDM_TSFIFO_OBSCFG 0xF29500FF -+ -+/* TSOBSM */ -+#define R367_OFDM_TSOBSM 0xF296 -+#define F367_OFDM_TSFIFO_OBSDATA_HI 0xF29600FF -+ -+/* TSOBSL */ -+#define R367_OFDM_TSOBSL 0xF297 -+#define F367_OFDM_TSFIFO_OBSDATA_LO 0xF29700FF -+ -+/* ERRCTRL1 */ -+#define R367_OFDM_ERRCTRL1 0xF298 -+#define F367_OFDM_ERR_SRC1 0xF29800F0 -+#define F367_OFDM_ERRCTRL1_3 0xF2980008 -+#define F367_OFDM_NUM_EVT1 0xF2980007 -+ -+/* ERRCNT1H */ -+#define R367_OFDM_ERRCNT1H 0xF299 -+#define F367_OFDM_ERRCNT1_OLDVALUE 0xF2990080 -+#define F367_OFDM_ERR_CNT1 0xF299007F -+ -+/* ERRCNT1M */ -+#define R367_OFDM_ERRCNT1M 0xF29A -+#define F367_OFDM_ERR_CNT1_HI 0xF29A00FF -+ -+/* ERRCNT1L */ -+#define R367_OFDM_ERRCNT1L 0xF29B -+#define F367_OFDM_ERR_CNT1_LO 0xF29B00FF -+ -+/* ERRCTRL2 */ -+#define R367_OFDM_ERRCTRL2 0xF29C -+#define F367_OFDM_ERR_SRC2 0xF29C00F0 -+#define F367_OFDM_ERRCTRL2_3 0xF29C0008 -+#define F367_OFDM_NUM_EVT2 0xF29C0007 -+ -+/* ERRCNT2H */ -+#define R367_OFDM_ERRCNT2H 0xF29D -+#define F367_OFDM_ERRCNT2_OLDVALUE 0xF29D0080 -+#define F367_OFDM_ERR_CNT2_HI 0xF29D007F -+ -+/* ERRCNT2M */ -+#define R367_OFDM_ERRCNT2M 0xF29E -+#define F367_OFDM_ERR_CNT2_MED 0xF29E00FF -+ -+/* ERRCNT2L */ -+#define R367_OFDM_ERRCNT2L 0xF29F -+#define F367_OFDM_ERR_CNT2_LO 0xF29F00FF -+ -+/* FECSPY */ -+#define R367_OFDM_FECSPY 0xF2A0 -+#define F367_OFDM_SPY_ENABLE 0xF2A00080 -+#define F367_OFDM_NO_SYNCBYTE 0xF2A00040 -+#define F367_OFDM_SERIAL_MODE 0xF2A00020 -+#define F367_OFDM_UNUSUAL_PACKET 0xF2A00010 -+#define F367_OFDM_BERMETER_DATAMODE 0xF2A0000C -+#define F367_OFDM_BERMETER_LMODE 0xF2A00002 -+#define F367_OFDM_BERMETER_RESET 0xF2A00001 -+ -+/* FSPYCFG */ -+#define R367_OFDM_FSPYCFG 0xF2A1 -+#define F367_OFDM_FECSPY_INPUT 0xF2A100C0 -+#define F367_OFDM_RST_ON_ERROR 0xF2A10020 -+#define F367_OFDM_ONE_SHOT 0xF2A10010 -+#define F367_OFDM_I2C_MOD 0xF2A1000C -+#define F367_OFDM_SPY_HYSTERESIS 0xF2A10003 -+ -+/* FSPYDATA */ -+#define R367_OFDM_FSPYDATA 0xF2A2 -+#define F367_OFDM_SPY_STUFFING 0xF2A20080 -+#define F367_OFDM_NOERROR_PKTJITTER 0xF2A20040 -+#define F367_OFDM_SPY_CNULLPKT 0xF2A20020 -+#define F367_OFDM_SPY_OUTDATA_MODE 0xF2A2001F -+ -+/* FSPYOUT */ -+#define R367_OFDM_FSPYOUT 0xF2A3 -+#define F367_OFDM_FSPY_DIRECT 0xF2A30080 -+#define F367_OFDM_FSPYOUT_6 0xF2A30040 -+#define F367_OFDM_SPY_OUTDATA_BUS 0xF2A30038 -+#define F367_OFDM_STUFF_MODE 0xF2A30007 -+ -+/* FSTATUS */ -+#define R367_OFDM_FSTATUS 0xF2A4 -+#define F367_OFDM_SPY_ENDSIM 0xF2A40080 -+#define F367_OFDM_VALID_SIM 0xF2A40040 -+#define F367_OFDM_FOUND_SIGNAL 0xF2A40020 -+#define F367_OFDM_DSS_SYNCBYTE 0xF2A40010 -+#define F367_OFDM_RESULT_STATE 0xF2A4000F -+ -+/* FGOODPACK */ -+#define R367_OFDM_FGOODPACK 0xF2A5 -+#define F367_OFDM_FGOOD_PACKET 0xF2A500FF -+ -+/* FPACKCNT */ -+#define R367_OFDM_FPACKCNT 0xF2A6 -+#define F367_OFDM_FPACKET_COUNTER 0xF2A600FF -+ -+/* FSPYMISC */ -+#define R367_OFDM_FSPYMISC 0xF2A7 -+#define F367_OFDM_FLABEL_COUNTER 0xF2A700FF -+ -+/* FBERCPT4 */ -+#define R367_OFDM_FBERCPT4 0xF2A8 -+#define F367_OFDM_FBERMETER_CPT5 0xF2A800FF -+ -+/* FBERCPT3 */ -+#define R367_OFDM_FBERCPT3 0xF2A9 -+#define F367_OFDM_FBERMETER_CPT4 0xF2A900FF -+ -+/* FBERCPT2 */ -+#define R367_OFDM_FBERCPT2 0xF2AA -+#define F367_OFDM_FBERMETER_CPT3 0xF2AA00FF -+ -+/* FBERCPT1 */ -+#define R367_OFDM_FBERCPT1 0xF2AB -+#define F367_OFDM_FBERMETER_CPT2 0xF2AB00FF -+ -+/* FBERCPT0 */ -+#define R367_OFDM_FBERCPT0 0xF2AC -+#define F367_OFDM_FBERMETER_CPT1 0xF2AC00FF -+ -+/* FBERERR2 */ -+#define R367_OFDM_FBERERR2 0xF2AD -+#define F367_OFDM_FBERMETER_ERR_HI 0xF2AD00FF -+ -+/* FBERERR1 */ -+#define R367_OFDM_FBERERR1 0xF2AE -+#define F367_OFDM_FBERMETER_ERR_MED 0xF2AE00FF -+ -+/* FBERERR0 */ -+#define R367_OFDM_FBERERR0 0xF2AF -+#define F367_OFDM_FBERMETER_ERR_LO 0xF2AF00FF -+ -+/* FSTATESM */ -+#define R367_OFDM_FSTATESM 0xF2B0 -+#define F367_OFDM_RSTATE_F 0xF2B00080 -+#define F367_OFDM_RSTATE_E 0xF2B00040 -+#define F367_OFDM_RSTATE_D 0xF2B00020 -+#define F367_OFDM_RSTATE_C 0xF2B00010 -+#define F367_OFDM_RSTATE_B 0xF2B00008 -+#define F367_OFDM_RSTATE_A 0xF2B00004 -+#define F367_OFDM_RSTATE_9 0xF2B00002 -+#define F367_OFDM_RSTATE_8 0xF2B00001 -+ -+/* FSTATESL */ -+#define R367_OFDM_FSTATESL 0xF2B1 -+#define F367_OFDM_RSTATE_7 0xF2B10080 -+#define F367_OFDM_RSTATE_6 0xF2B10040 -+#define F367_OFDM_RSTATE_5 0xF2B10020 -+#define F367_OFDM_RSTATE_4 0xF2B10010 -+#define F367_OFDM_RSTATE_3 0xF2B10008 -+#define F367_OFDM_RSTATE_2 0xF2B10004 -+#define F367_OFDM_RSTATE_1 0xF2B10002 -+#define F367_OFDM_RSTATE_0 0xF2B10001 -+ -+/* FSPYBER */ -+#define R367_OFDM_FSPYBER 0xF2B2 -+#define F367_OFDM_FSPYBER_7 0xF2B20080 -+#define F367_OFDM_FSPYOBS_XORREAD 0xF2B20040 -+#define F367_OFDM_FSPYBER_OBSMODE 0xF2B20020 -+#define F367_OFDM_FSPYBER_SYNCBYTE 0xF2B20010 -+#define F367_OFDM_FSPYBER_UNSYNC 0xF2B20008 -+#define F367_OFDM_FSPYBER_CTIME 0xF2B20007 -+ -+/* FSPYDISTM */ -+#define R367_OFDM_FSPYDISTM 0xF2B3 -+#define F367_OFDM_PKTTIME_DISTANCE_HI 0xF2B300FF -+ -+/* FSPYDISTL */ -+#define R367_OFDM_FSPYDISTL 0xF2B4 -+#define F367_OFDM_PKTTIME_DISTANCE_LO 0xF2B400FF -+ -+/* FSPYOBS7 */ -+#define R367_OFDM_FSPYOBS7 0xF2B8 -+#define F367_OFDM_FSPYOBS_SPYFAIL 0xF2B80080 -+#define F367_OFDM_FSPYOBS_SPYFAIL1 0xF2B80040 -+#define F367_OFDM_FSPYOBS_ERROR 0xF2B80020 -+#define F367_OFDM_FSPYOBS_STROUT 0xF2B80010 -+#define F367_OFDM_FSPYOBS_RESULTSTATE1 0xF2B8000F -+ -+/* FSPYOBS6 */ -+#define R367_OFDM_FSPYOBS6 0xF2B9 -+#define F367_OFDM_FSPYOBS_RESULTSTATE0 0xF2B900F0 -+#define F367_OFDM_FSPYOBS_RESULTSTATEM1 0xF2B9000F -+ -+/* FSPYOBS5 */ -+#define R367_OFDM_FSPYOBS5 0xF2BA -+#define F367_OFDM_FSPYOBS_BYTEOFPACKET1 0xF2BA00FF -+ -+/* FSPYOBS4 */ -+#define R367_OFDM_FSPYOBS4 0xF2BB -+#define F367_OFDM_FSPYOBS_BYTEVALUE1 0xF2BB00FF -+ -+/* FSPYOBS3 */ -+#define R367_OFDM_FSPYOBS3 0xF2BC -+#define F367_OFDM_FSPYOBS_DATA1 0xF2BC00FF -+ -+/* FSPYOBS2 */ -+#define R367_OFDM_FSPYOBS2 0xF2BD -+#define F367_OFDM_FSPYOBS_DATA0 0xF2BD00FF -+ -+/* FSPYOBS1 */ -+#define R367_OFDM_FSPYOBS1 0xF2BE -+#define F367_OFDM_FSPYOBS_DATAM1 0xF2BE00FF -+ -+/* FSPYOBS0 */ -+#define R367_OFDM_FSPYOBS0 0xF2BF -+#define F367_OFDM_FSPYOBS_DATAM2 0xF2BF00FF -+ -+/* SFDEMAP */ -+#define R367_OFDM_SFDEMAP 0xF2C0 -+#define F367_OFDM_SFDEMAP_7 0xF2C00080 -+#define F367_OFDM_SFEC_K_DIVIDER_VIT 0xF2C0007F -+ -+/* SFERROR */ -+#define R367_OFDM_SFERROR 0xF2C1 -+#define F367_OFDM_SFEC_REGERR_VIT 0xF2C100FF -+ -+/* SFAVSR */ -+#define R367_OFDM_SFAVSR 0xF2C2 -+#define F367_OFDM_SFEC_SUMERRORS 0xF2C20080 -+#define F367_OFDM_SERROR_MAXMODE 0xF2C20040 -+#define F367_OFDM_SN_SFEC 0xF2C20030 -+#define F367_OFDM_KDIV_MODE_SFEC 0xF2C2000C -+#define F367_OFDM_SFAVSR_1 0xF2C20002 -+#define F367_OFDM_SFAVSR_0 0xF2C20001 -+ -+/* SFECSTATUS */ -+#define R367_OFDM_SFECSTATUS 0xF2C3 -+#define F367_OFDM_SFEC_ON 0xF2C30080 -+#define F367_OFDM_SFSTATUS_6 0xF2C30040 -+#define F367_OFDM_SFSTATUS_5 0xF2C30020 -+#define F367_OFDM_SFSTATUS_4 0xF2C30010 -+#define F367_OFDM_LOCKEDSFEC 0xF2C30008 -+#define F367_OFDM_SFEC_DELOCK 0xF2C30004 -+#define F367_OFDM_SFEC_DEMODSEL1 0xF2C30002 -+#define F367_OFDM_SFEC_OVFON 0xF2C30001 -+ -+/* SFKDIV12 */ -+#define R367_OFDM_SFKDIV12 0xF2C4 -+#define F367_OFDM_SFECKDIV12_MAN 0xF2C40080 -+#define F367_OFDM_SFEC_K_DIVIDER_12 0xF2C4007F -+ -+/* SFKDIV23 */ -+#define R367_OFDM_SFKDIV23 0xF2C5 -+#define F367_OFDM_SFECKDIV23_MAN 0xF2C50080 -+#define F367_OFDM_SFEC_K_DIVIDER_23 0xF2C5007F -+ -+/* SFKDIV34 */ -+#define R367_OFDM_SFKDIV34 0xF2C6 -+#define F367_OFDM_SFECKDIV34_MAN 0xF2C60080 -+#define F367_OFDM_SFEC_K_DIVIDER_34 0xF2C6007F -+ -+/* SFKDIV56 */ -+#define R367_OFDM_SFKDIV56 0xF2C7 -+#define F367_OFDM_SFECKDIV56_MAN 0xF2C70080 -+#define F367_OFDM_SFEC_K_DIVIDER_56 0xF2C7007F -+ -+/* SFKDIV67 */ -+#define R367_OFDM_SFKDIV67 0xF2C8 -+#define F367_OFDM_SFECKDIV67_MAN 0xF2C80080 -+#define F367_OFDM_SFEC_K_DIVIDER_67 0xF2C8007F -+ -+/* SFKDIV78 */ -+#define R367_OFDM_SFKDIV78 0xF2C9 -+#define F367_OFDM_SFECKDIV78_MAN 0xF2C90080 -+#define F367_OFDM_SFEC_K_DIVIDER_78 0xF2C9007F -+ -+/* SFDILSTKM */ -+#define R367_OFDM_SFDILSTKM 0xF2CA -+#define F367_OFDM_SFEC_PACKCPT 0xF2CA00E0 -+#define F367_OFDM_SFEC_DILSTK_HI 0xF2CA001F -+ -+/* SFDILSTKL */ -+#define R367_OFDM_SFDILSTKL 0xF2CB -+#define F367_OFDM_SFEC_DILSTK_LO 0xF2CB00FF -+ -+/* SFSTATUS */ -+#define R367_OFDM_SFSTATUS 0xF2CC -+#define F367_OFDM_SFEC_LINEOK 0xF2CC0080 -+#define F367_OFDM_SFEC_ERROR 0xF2CC0040 -+#define F367_OFDM_SFEC_DATA7 0xF2CC0020 -+#define F367_OFDM_SFEC_OVERFLOW 0xF2CC0010 -+#define F367_OFDM_SFEC_DEMODSEL2 0xF2CC0008 -+#define F367_OFDM_SFEC_NOSYNC 0xF2CC0004 -+#define F367_OFDM_SFEC_UNREGULA 0xF2CC0002 -+#define F367_OFDM_SFEC_READY 0xF2CC0001 -+ -+/* SFDLYH */ -+#define R367_OFDM_SFDLYH 0xF2CD -+#define F367_OFDM_SFEC_TSTIMEVALID 0xF2CD0080 -+#define F367_OFDM_SFEC_SPEEDUP 0xF2CD0040 -+#define F367_OFDM_SFEC_STOP 0xF2CD0020 -+#define F367_OFDM_SFEC_REGULATED 0xF2CD0010 -+#define F367_OFDM_SFEC_REALSYMBOFFSET 0xF2CD000F -+ -+/* SFDLYM */ -+#define R367_OFDM_SFDLYM 0xF2CE -+#define F367_OFDM_SFEC_REALSYMBOFFSET_HI 0xF2CE00FF -+ -+/* SFDLYL */ -+#define R367_OFDM_SFDLYL 0xF2CF -+#define F367_OFDM_SFEC_REALSYMBOFFSET_LO 0xF2CF00FF -+ -+/* SFDLYSETH */ -+#define R367_OFDM_SFDLYSETH 0xF2D0 -+#define F367_OFDM_SFEC_OFFSET 0xF2D000E0 -+#define F367_OFDM_SFECDLYSETH_4 0xF2D00010 -+#define F367_OFDM_RST_SFEC 0xF2D00008 -+#define F367_OFDM_SFECDLYSETH_2 0xF2D00004 -+#define F367_OFDM_SFEC_DISABLE 0xF2D00002 -+#define F367_OFDM_SFEC_UNREGUL 0xF2D00001 -+ -+/* SFDLYSETM */ -+#define R367_OFDM_SFDLYSETM 0xF2D1 -+#define F367_OFDM_SFECDLYSETM_7 0xF2D10080 -+#define F367_OFDM_SFEC_SYMBOFFSET_HI 0xF2D1007F -+ -+/* SFDLYSETL */ -+#define R367_OFDM_SFDLYSETL 0xF2D2 -+#define F367_OFDM_SFEC_SYMBOFFSET_LO 0xF2D200FF -+ -+/* SFOBSCFG */ -+#define R367_OFDM_SFOBSCFG 0xF2D3 -+#define F367_OFDM_SFEC_OBSCFG 0xF2D300FF -+ -+/* SFOBSM */ -+#define R367_OFDM_SFOBSM 0xF2D4 -+#define F367_OFDM_SFEC_OBSDATA_HI 0xF2D400FF -+ -+/* SFOBSL */ -+#define R367_OFDM_SFOBSL 0xF2D5 -+#define F367_OFDM_SFEC_OBSDATA_LO 0xF2D500FF -+ -+/* SFECINFO */ -+#define R367_OFDM_SFECINFO 0xF2D6 -+#define F367_OFDM_SFECINFO_7 0xF2D60080 -+#define F367_OFDM_SFEC_SYNCDLSB 0xF2D60070 -+#define F367_OFDM_SFCE_S1CPHASE 0xF2D6000F -+ -+/* SFERRCTRL */ -+#define R367_OFDM_SFERRCTRL 0xF2D8 -+#define F367_OFDM_SFEC_ERR_SOURCE 0xF2D800F0 -+#define F367_OFDM_SFERRCTRL_3 0xF2D80008 -+#define F367_OFDM_SFEC_NUM_EVENT 0xF2D80007 -+ -+/* SFERRCNTH */ -+#define R367_OFDM_SFERRCNTH 0xF2D9 -+#define F367_OFDM_SFERRC_OLDVALUE 0xF2D90080 -+#define F367_OFDM_SFEC_ERR_CNT 0xF2D9007F -+ -+/* SFERRCNTM */ -+#define R367_OFDM_SFERRCNTM 0xF2DA -+#define F367_OFDM_SFEC_ERR_CNT_HI 0xF2DA00FF -+ -+/* SFERRCNTL */ -+#define R367_OFDM_SFERRCNTL 0xF2DB -+#define F367_OFDM_SFEC_ERR_CNT_LO 0xF2DB00FF -+ -+/* SYMBRATEM */ -+#define R367_OFDM_SYMBRATEM 0xF2E0 -+#define F367_OFDM_DEFGEN_SYMBRATE_HI 0xF2E000FF -+ -+/* SYMBRATEL */ -+#define R367_OFDM_SYMBRATEL 0xF2E1 -+#define F367_OFDM_DEFGEN_SYMBRATE_LO 0xF2E100FF -+ -+/* SYMBSTATUS */ -+#define R367_OFDM_SYMBSTATUS 0xF2E2 -+#define F367_OFDM_SYMBDLINE2_OFF 0xF2E20080 -+#define F367_OFDM_SDDL_REINIT1 0xF2E20040 -+#define F367_OFDM_SDD_REINIT1 0xF2E20020 -+#define F367_OFDM_TOKENID_ERROR 0xF2E20010 -+#define F367_OFDM_SYMBRATE_OVERFLOW 0xF2E20008 -+#define F367_OFDM_SYMBRATE_UNDERFLOW 0xF2E20004 -+#define F367_OFDM_TOKENID_RSTEVENT 0xF2E20002 -+#define F367_OFDM_TOKENID_RESET1 0xF2E20001 -+ -+/* SYMBCFG */ -+#define R367_OFDM_SYMBCFG 0xF2E3 -+#define F367_OFDM_SYMBCFG_7 0xF2E30080 -+#define F367_OFDM_SYMBCFG_6 0xF2E30040 -+#define F367_OFDM_SYMBCFG_5 0xF2E30020 -+#define F367_OFDM_SYMBCFG_4 0xF2E30010 -+#define F367_OFDM_SYMRATE_FSPEED 0xF2E3000C -+#define F367_OFDM_SYMRATE_SSPEED 0xF2E30003 -+ -+/* SYMBFIFOM */ -+#define R367_OFDM_SYMBFIFOM 0xF2E4 -+#define F367_OFDM_SYMBFIFOM_7 0xF2E40080 -+#define F367_OFDM_SYMBFIFOM_6 0xF2E40040 -+#define F367_OFDM_DEFGEN_SYMFIFO_HI 0xF2E4003F -+ -+/* SYMBFIFOL */ -+#define R367_OFDM_SYMBFIFOL 0xF2E5 -+#define F367_OFDM_DEFGEN_SYMFIFO_LO 0xF2E500FF -+ -+/* SYMBOFFSM */ -+#define R367_OFDM_SYMBOFFSM 0xF2E6 -+#define F367_OFDM_TOKENID_RESET2 0xF2E60080 -+#define F367_OFDM_SDDL_REINIT2 0xF2E60040 -+#define F367_OFDM_SDD_REINIT2 0xF2E60020 -+#define F367_OFDM_SYMBOFFSM_4 0xF2E60010 -+#define F367_OFDM_SYMBOFFSM_3 0xF2E60008 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_HI 0xF2E60007 -+ -+/* SYMBOFFSL */ -+#define R367_OFDM_SYMBOFFSL 0xF2E7 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_LO 0xF2E700FF -+ -+/* DEBUG_LT4 */ -+#define R367_DEBUG_LT4 0xF400 -+#define F367_F_DEBUG_LT4 0xF40000FF -+ -+/* DEBUG_LT5 */ -+#define R367_DEBUG_LT5 0xF401 -+#define F367_F_DEBUG_LT5 0xF40100FF -+ -+/* DEBUG_LT6 */ -+#define R367_DEBUG_LT6 0xF402 -+#define F367_F_DEBUG_LT6 0xF40200FF -+ -+/* DEBUG_LT7 */ -+#define R367_DEBUG_LT7 0xF403 -+#define F367_F_DEBUG_LT7 0xF40300FF -+ -+/* DEBUG_LT8 */ -+#define R367_DEBUG_LT8 0xF404 -+#define F367_F_DEBUG_LT8 0xF40400FF -+ -+/* DEBUG_LT9 */ -+#define R367_DEBUG_LT9 0xF405 -+#define F367_F_DEBUG_LT9 0xF40500FF -+ -+/* CTRL_1 */ -+#define R367_QAM_CTRL_1 0xF402 -+#define F367_QAM_SOFT_RST 0xF4020080 -+#define F367_QAM_EQU_RST 0xF4020008 -+#define F367_QAM_CRL_RST 0xF4020004 -+#define F367_QAM_TRL_RST 0xF4020002 -+#define F367_QAM_AGC_RST 0xF4020001 -+ -+/* CTRL_2 */ -+#define R367_QAM_CTRL_2 0xF403 -+#define F367_QAM_DEINT_RST 0xF4030008 -+#define F367_QAM_RS_RST 0xF4030004 -+ -+/* IT_STATUS1 */ -+#define R367_QAM_IT_STATUS1 0xF408 -+#define F367_QAM_SWEEP_OUT 0xF4080080 -+#define F367_QAM_FSM_CRL 0xF4080040 -+#define F367_QAM_CRL_LOCK 0xF4080020 -+#define F367_QAM_MFSM 0xF4080010 -+#define F367_QAM_TRL_LOCK 0xF4080008 -+#define F367_QAM_TRL_AGC_LIMIT 0xF4080004 -+#define F367_QAM_ADJ_AGC_LOCK 0xF4080002 -+#define F367_QAM_AGC_QAM_LOCK 0xF4080001 -+ -+/* IT_STATUS2 */ -+#define R367_QAM_IT_STATUS2 0xF409 -+#define F367_QAM_TSMF_CNT 0xF4090080 -+#define F367_QAM_TSMF_EOF 0xF4090040 -+#define F367_QAM_TSMF_RDY 0xF4090020 -+#define F367_QAM_FEC_NOCORR 0xF4090010 -+#define F367_QAM_SYNCSTATE 0xF4090008 -+#define F367_QAM_DEINT_LOCK 0xF4090004 -+#define F367_QAM_FADDING_FRZ 0xF4090002 -+#define F367_QAM_TAPMON_ALARM 0xF4090001 -+ -+/* IT_EN1 */ -+#define R367_QAM_IT_EN1 0xF40A -+#define F367_QAM_SWEEP_OUTE 0xF40A0080 -+#define F367_QAM_FSM_CRLE 0xF40A0040 -+#define F367_QAM_CRL_LOCKE 0xF40A0020 -+#define F367_QAM_MFSME 0xF40A0010 -+#define F367_QAM_TRL_LOCKE 0xF40A0008 -+#define F367_QAM_TRL_AGC_LIMITE 0xF40A0004 -+#define F367_QAM_ADJ_AGC_LOCKE 0xF40A0002 -+#define F367_QAM_AGC_LOCKE 0xF40A0001 -+ -+/* IT_EN2 */ -+#define R367_QAM_IT_EN2 0xF40B -+#define F367_QAM_TSMF_CNTE 0xF40B0080 -+#define F367_QAM_TSMF_EOFE 0xF40B0040 -+#define F367_QAM_TSMF_RDYE 0xF40B0020 -+#define F367_QAM_FEC_NOCORRE 0xF40B0010 -+#define F367_QAM_SYNCSTATEE 0xF40B0008 -+#define F367_QAM_DEINT_LOCKE 0xF40B0004 -+#define F367_QAM_FADDING_FRZE 0xF40B0002 -+#define F367_QAM_TAPMON_ALARME 0xF40B0001 -+ -+/* CTRL_STATUS */ -+#define R367_QAM_CTRL_STATUS 0xF40C -+#define F367_QAM_QAMFEC_LOCK 0xF40C0004 -+#define F367_QAM_TSMF_LOCK 0xF40C0002 -+#define F367_QAM_TSMF_ERROR 0xF40C0001 -+ -+/* TEST_CTL */ -+#define R367_QAM_TEST_CTL 0xF40F -+#define F367_QAM_TST_BLK_SEL 0xF40F0060 -+#define F367_QAM_TST_BUS_SEL 0xF40F001F -+ -+/* AGC_CTL */ -+#define R367_QAM_AGC_CTL 0xF410 -+#define F367_QAM_AGC_LCK_TH 0xF41000F0 -+#define F367_QAM_AGC_ACCUMRSTSEL 0xF4100007 -+ -+/* AGC_IF_CFG */ -+#define R367_QAM_AGC_IF_CFG 0xF411 -+#define F367_QAM_AGC_IF_BWSEL 0xF41100F0 -+#define F367_QAM_AGC_IF_FREEZE 0xF4110002 -+ -+/* AGC_RF_CFG */ -+#define R367_QAM_AGC_RF_CFG 0xF412 -+#define F367_QAM_AGC_RF_BWSEL 0xF4120070 -+#define F367_QAM_AGC_RF_FREEZE 0xF4120002 -+ -+/* AGC_PWM_CFG */ -+#define R367_QAM_AGC_PWM_CFG 0xF413 -+#define F367_QAM_AGC_RF_PWM_TST 0xF4130080 -+#define F367_QAM_AGC_RF_PWM_INV 0xF4130040 -+#define F367_QAM_AGC_IF_PWM_TST 0xF4130008 -+#define F367_QAM_AGC_IF_PWM_INV 0xF4130004 -+#define F367_QAM_AGC_PWM_CLKDIV 0xF4130003 -+ -+/* AGC_PWR_REF_L */ -+#define R367_QAM_AGC_PWR_REF_L 0xF414 -+#define F367_QAM_AGC_PWRREF_LO 0xF41400FF -+ -+/* AGC_PWR_REF_H */ -+#define R367_QAM_AGC_PWR_REF_H 0xF415 -+#define F367_QAM_AGC_PWRREF_HI 0xF4150003 -+ -+/* AGC_RF_TH_L */ -+#define R367_QAM_AGC_RF_TH_L 0xF416 -+#define F367_QAM_AGC_RF_TH_LO 0xF41600FF -+ -+/* AGC_RF_TH_H */ -+#define R367_QAM_AGC_RF_TH_H 0xF417 -+#define F367_QAM_AGC_RF_TH_HI 0xF417000F -+ -+/* AGC_IF_LTH_L */ -+#define R367_QAM_AGC_IF_LTH_L 0xF418 -+#define F367_QAM_AGC_IF_THLO_LO 0xF41800FF -+ -+/* AGC_IF_LTH_H */ -+#define R367_QAM_AGC_IF_LTH_H 0xF419 -+#define F367_QAM_AGC_IF_THLO_HI 0xF419000F -+ -+/* AGC_IF_HTH_L */ -+#define R367_QAM_AGC_IF_HTH_L 0xF41A -+#define F367_QAM_AGC_IF_THHI_LO 0xF41A00FF -+ -+/* AGC_IF_HTH_H */ -+#define R367_QAM_AGC_IF_HTH_H 0xF41B -+#define F367_QAM_AGC_IF_THHI_HI 0xF41B000F -+ -+/* AGC_PWR_RD_L */ -+#define R367_QAM_AGC_PWR_RD_L 0xF41C -+#define F367_QAM_AGC_PWR_WORD_LO 0xF41C00FF -+ -+/* AGC_PWR_RD_M */ -+#define R367_QAM_AGC_PWR_RD_M 0xF41D -+#define F367_QAM_AGC_PWR_WORD_ME 0xF41D00FF -+ -+/* AGC_PWR_RD_H */ -+#define R367_QAM_AGC_PWR_RD_H 0xF41E -+#define F367_QAM_AGC_PWR_WORD_HI 0xF41E0003 -+ -+/* AGC_PWM_IFCMD_L */ -+#define R367_QAM_AGC_PWM_IFCMD_L 0xF420 -+#define F367_QAM_AGC_IF_PWMCMD_LO 0xF42000FF -+ -+/* AGC_PWM_IFCMD_H */ -+#define R367_QAM_AGC_PWM_IFCMD_H 0xF421 -+#define F367_QAM_AGC_IF_PWMCMD_HI 0xF421000F -+ -+/* AGC_PWM_RFCMD_L */ -+#define R367_QAM_AGC_PWM_RFCMD_L 0xF422 -+#define F367_QAM_AGC_RF_PWMCMD_LO 0xF42200FF -+ -+/* AGC_PWM_RFCMD_H */ -+#define R367_QAM_AGC_PWM_RFCMD_H 0xF423 -+#define F367_QAM_AGC_RF_PWMCMD_HI 0xF423000F -+ -+/* IQDEM_CFG */ -+#define R367_QAM_IQDEM_CFG 0xF424 -+#define F367_QAM_IQDEM_CLK_SEL 0xF4240004 -+#define F367_QAM_IQDEM_INVIQ 0xF4240002 -+#define F367_QAM_IQDEM_A2DTYPE 0xF4240001 -+ -+/* MIX_NCO_LL */ -+#define R367_QAM_MIX_NCO_LL 0xF425 -+#define F367_QAM_MIX_NCO_INC_LL 0xF42500FF -+ -+/* MIX_NCO_HL */ -+#define R367_QAM_MIX_NCO_HL 0xF426 -+#define F367_QAM_MIX_NCO_INC_HL 0xF42600FF -+ -+/* MIX_NCO_HH */ -+#define R367_QAM_MIX_NCO_HH 0xF427 -+#define F367_QAM_MIX_NCO_INVCNST 0xF4270080 -+#define F367_QAM_MIX_NCO_INC_HH 0xF427007F -+ -+/* SRC_NCO_LL */ -+#define R367_QAM_SRC_NCO_LL 0xF428 -+#define F367_QAM_SRC_NCO_INC_LL 0xF42800FF -+ -+/* SRC_NCO_LH */ -+#define R367_QAM_SRC_NCO_LH 0xF429 -+#define F367_QAM_SRC_NCO_INC_LH 0xF42900FF -+ -+/* SRC_NCO_HL */ -+#define R367_QAM_SRC_NCO_HL 0xF42A -+#define F367_QAM_SRC_NCO_INC_HL 0xF42A00FF -+ -+/* SRC_NCO_HH */ -+#define R367_QAM_SRC_NCO_HH 0xF42B -+#define F367_QAM_SRC_NCO_INC_HH 0xF42B007F -+ -+/* IQDEM_GAIN_SRC_L */ -+#define R367_QAM_IQDEM_GAIN_SRC_L 0xF42C -+#define F367_QAM_GAIN_SRC_LO 0xF42C00FF -+ -+/* IQDEM_GAIN_SRC_H */ -+#define R367_QAM_IQDEM_GAIN_SRC_H 0xF42D -+#define F367_QAM_GAIN_SRC_HI 0xF42D0003 -+ -+/* IQDEM_DCRM_CFG_LL */ -+#define R367_QAM_IQDEM_DCRM_CFG_LL 0xF430 -+#define F367_QAM_DCRM0_DCIN_L 0xF43000FF -+ -+/* IQDEM_DCRM_CFG_LH */ -+#define R367_QAM_IQDEM_DCRM_CFG_LH 0xF431 -+#define F367_QAM_DCRM1_I_DCIN_L 0xF43100FC -+#define F367_QAM_DCRM0_DCIN_H 0xF4310003 -+ -+/* IQDEM_DCRM_CFG_HL */ -+#define R367_QAM_IQDEM_DCRM_CFG_HL 0xF432 -+#define F367_QAM_DCRM1_Q_DCIN_L 0xF43200F0 -+#define F367_QAM_DCRM1_I_DCIN_H 0xF432000F -+ -+/* IQDEM_DCRM_CFG_HH */ -+#define R367_QAM_IQDEM_DCRM_CFG_HH 0xF433 -+#define F367_QAM_DCRM1_FRZ 0xF4330080 -+#define F367_QAM_DCRM0_FRZ 0xF4330040 -+#define F367_QAM_DCRM1_Q_DCIN_H 0xF433003F -+ -+/* IQDEM_ADJ_COEFF0 */ -+#define R367_QAM_IQDEM_ADJ_COEFF0 0xF434 -+#define F367_QAM_ADJIIR_COEFF10_L 0xF43400FF -+ -+/* IQDEM_ADJ_COEFF1 */ -+#define R367_QAM_IQDEM_ADJ_COEFF1 0xF435 -+#define F367_QAM_ADJIIR_COEFF11_L 0xF43500FC -+#define F367_QAM_ADJIIR_COEFF10_H 0xF4350003 -+ -+/* IQDEM_ADJ_COEFF2 */ -+#define R367_QAM_IQDEM_ADJ_COEFF2 0xF436 -+#define F367_QAM_ADJIIR_COEFF12_L 0xF43600F0 -+#define F367_QAM_ADJIIR_COEFF11_H 0xF436000F -+ -+/* IQDEM_ADJ_COEFF3 */ -+#define R367_QAM_IQDEM_ADJ_COEFF3 0xF437 -+#define F367_QAM_ADJIIR_COEFF20_L 0xF43700C0 -+#define F367_QAM_ADJIIR_COEFF12_H 0xF437003F -+ -+/* IQDEM_ADJ_COEFF4 */ -+#define R367_QAM_IQDEM_ADJ_COEFF4 0xF438 -+#define F367_QAM_ADJIIR_COEFF20_H 0xF43800FF -+ -+/* IQDEM_ADJ_COEFF5 */ -+#define R367_QAM_IQDEM_ADJ_COEFF5 0xF439 -+#define F367_QAM_ADJIIR_COEFF21_L 0xF43900FF -+ -+/* IQDEM_ADJ_COEFF6 */ -+#define R367_QAM_IQDEM_ADJ_COEFF6 0xF43A -+#define F367_QAM_ADJIIR_COEFF22_L 0xF43A00FC -+#define F367_QAM_ADJIIR_COEFF21_H 0xF43A0003 -+ -+/* IQDEM_ADJ_COEFF7 */ -+#define R367_QAM_IQDEM_ADJ_COEFF7 0xF43B -+#define F367_QAM_ADJIIR_COEFF22_H 0xF43B000F -+ -+/* IQDEM_ADJ_EN */ -+#define R367_QAM_IQDEM_ADJ_EN 0xF43C -+#define F367_QAM_ALLPASSFILT_EN 0xF43C0008 -+#define F367_QAM_ADJ_AGC_EN 0xF43C0004 -+#define F367_QAM_ADJ_COEFF_FRZ 0xF43C0002 -+#define F367_QAM_ADJ_EN 0xF43C0001 -+ -+/* IQDEM_ADJ_AGC_REF */ -+#define R367_QAM_IQDEM_ADJ_AGC_REF 0xF43D -+#define F367_QAM_ADJ_AGC_REF 0xF43D00FF -+ -+/* ALLPASSFILT1 */ -+#define R367_QAM_ALLPASSFILT1 0xF440 -+#define F367_QAM_ALLPASSFILT_COEFF1_LO 0xF44000FF -+ -+/* ALLPASSFILT2 */ -+#define R367_QAM_ALLPASSFILT2 0xF441 -+#define F367_QAM_ALLPASSFILT_COEFF1_ME 0xF44100FF -+ -+/* ALLPASSFILT3 */ -+#define R367_QAM_ALLPASSFILT3 0xF442 -+#define F367_QAM_ALLPASSFILT_COEFF2_LO 0xF44200C0 -+#define F367_QAM_ALLPASSFILT_COEFF1_HI 0xF442003F -+ -+/* ALLPASSFILT4 */ -+#define R367_QAM_ALLPASSFILT4 0xF443 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEL 0xF44300FF -+ -+/* ALLPASSFILT5 */ -+#define R367_QAM_ALLPASSFILT5 0xF444 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEH 0xF44400FF -+ -+/* ALLPASSFILT6 */ -+#define R367_QAM_ALLPASSFILT6 0xF445 -+#define F367_QAM_ALLPASSFILT_COEFF3_LO 0xF44500F0 -+#define F367_QAM_ALLPASSFILT_COEFF2_HI 0xF445000F -+ -+/* ALLPASSFILT7 */ -+#define R367_QAM_ALLPASSFILT7 0xF446 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEL 0xF44600FF -+ -+/* ALLPASSFILT8 */ -+#define R367_QAM_ALLPASSFILT8 0xF447 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEH 0xF44700FF -+ -+/* ALLPASSFILT9 */ -+#define R367_QAM_ALLPASSFILT9 0xF448 -+#define F367_QAM_ALLPASSFILT_COEFF4_LO 0xF44800FC -+#define F367_QAM_ALLPASSFILT_COEFF3_HI 0xF4480003 -+ -+/* ALLPASSFILT10 */ -+#define R367_QAM_ALLPASSFILT10 0xF449 -+#define F367_QAM_ALLPASSFILT_COEFF4_ME 0xF44900FF -+ -+/* ALLPASSFILT11 */ -+#define R367_QAM_ALLPASSFILT11 0xF44A -+#define F367_QAM_ALLPASSFILT_COEFF4_HI 0xF44A00FF -+ -+/* TRL_AGC_CFG */ -+#define R367_QAM_TRL_AGC_CFG 0xF450 -+#define F367_QAM_TRL_AGC_FREEZE 0xF4500080 -+#define F367_QAM_TRL_AGC_REF 0xF450007F -+ -+/* TRL_LPF_CFG */ -+#define R367_QAM_TRL_LPF_CFG 0xF454 -+#define F367_QAM_NYQPOINT_INV 0xF4540040 -+#define F367_QAM_TRL_SHIFT 0xF4540030 -+#define F367_QAM_NYQ_COEFF_SEL 0xF454000C -+#define F367_QAM_TRL_LPF_FREEZE 0xF4540002 -+#define F367_QAM_TRL_LPF_CRT 0xF4540001 -+ -+/* TRL_LPF_ACQ_GAIN */ -+#define R367_QAM_TRL_LPF_ACQ_GAIN 0xF455 -+#define F367_QAM_TRL_GDIR_ACQ 0xF4550070 -+#define F367_QAM_TRL_GINT_ACQ 0xF4550007 -+ -+/* TRL_LPF_TRK_GAIN */ -+#define R367_QAM_TRL_LPF_TRK_GAIN 0xF456 -+#define F367_QAM_TRL_GDIR_TRK 0xF4560070 -+#define F367_QAM_TRL_GINT_TRK 0xF4560007 -+ -+/* TRL_LPF_OUT_GAIN */ -+#define R367_QAM_TRL_LPF_OUT_GAIN 0xF457 -+#define F367_QAM_TRL_GAIN_OUT 0xF4570007 -+ -+/* TRL_LOCKDET_LTH */ -+#define R367_QAM_TRL_LOCKDET_LTH 0xF458 -+#define F367_QAM_TRL_LCK_THLO 0xF4580007 -+ -+/* TRL_LOCKDET_HTH */ -+#define R367_QAM_TRL_LOCKDET_HTH 0xF459 -+#define F367_QAM_TRL_LCK_THHI 0xF45900FF -+ -+/* TRL_LOCKDET_TRGVAL */ -+#define R367_QAM_TRL_LOCKDET_TRGVAL 0xF45A -+#define F367_QAM_TRL_LCK_TRG 0xF45A00FF -+ -+/* IQ_QAM */ -+#define R367_QAM_IQ_QAM 0xF45C -+#define F367_QAM_IQ_INPUT 0xF45C0008 -+#define F367_QAM_DETECT_MODE 0xF45C0007 -+ -+/* FSM_STATE */ -+#define R367_QAM_FSM_STATE 0xF460 -+#define F367_QAM_CRL_DFE 0xF4600080 -+#define F367_QAM_DFE_START 0xF4600040 -+#define F367_QAM_CTRLG_START 0xF4600030 -+#define F367_QAM_FSM_FORCESTATE 0xF460000F -+ -+/* FSM_CTL */ -+#define R367_QAM_FSM_CTL 0xF461 -+#define F367_QAM_FEC2_EN 0xF4610040 -+#define F367_QAM_SIT_EN 0xF4610020 -+#define F367_QAM_TRL_AHEAD 0xF4610010 -+#define F367_QAM_TRL2_EN 0xF4610008 -+#define F367_QAM_FSM_EQA1_EN 0xF4610004 -+#define F367_QAM_FSM_BKP_DIS 0xF4610002 -+#define F367_QAM_FSM_FORCE_EN 0xF4610001 -+ -+/* FSM_STS */ -+#define R367_QAM_FSM_STS 0xF462 -+#define F367_QAM_FSM_STATUS 0xF462000F -+ -+/* FSM_SNR0_HTH */ -+#define R367_QAM_FSM_SNR0_HTH 0xF463 -+#define F367_QAM_SNR0_HTH 0xF46300FF -+ -+/* FSM_SNR1_HTH */ -+#define R367_QAM_FSM_SNR1_HTH 0xF464 -+#define F367_QAM_SNR1_HTH 0xF46400FF -+ -+/* FSM_SNR2_HTH */ -+#define R367_QAM_FSM_SNR2_HTH 0xF465 -+#define F367_QAM_SNR2_HTH 0xF46500FF -+ -+/* FSM_SNR0_LTH */ -+#define R367_QAM_FSM_SNR0_LTH 0xF466 -+#define F367_QAM_SNR0_LTH 0xF46600FF -+ -+/* FSM_SNR1_LTH */ -+#define R367_QAM_FSM_SNR1_LTH 0xF467 -+#define F367_QAM_SNR1_LTH 0xF46700FF -+ -+/* FSM_EQA1_HTH */ -+#define R367_QAM_FSM_EQA1_HTH 0xF468 -+#define F367_QAM_SNR3_HTH_LO 0xF46800F0 -+#define F367_QAM_EQA1_HTH 0xF468000F -+ -+/* FSM_TEMPO */ -+#define R367_QAM_FSM_TEMPO 0xF469 -+#define F367_QAM_SIT 0xF46900C0 -+#define F367_QAM_WST 0xF4690038 -+#define F367_QAM_ELT 0xF4690006 -+#define F367_QAM_SNR3_HTH_HI 0xF4690001 -+ -+/* FSM_CONFIG */ -+#define R367_QAM_FSM_CONFIG 0xF46A -+#define F367_QAM_FEC2_DFEOFF 0xF46A0004 -+#define F367_QAM_PRIT_STATE 0xF46A0002 -+#define F367_QAM_MODMAP_STATE 0xF46A0001 -+ -+/* EQU_I_TESTTAP_L */ -+#define R367_QAM_EQU_I_TESTTAP_L 0xF474 -+#define F367_QAM_I_TEST_TAP_L 0xF47400FF -+ -+/* EQU_I_TESTTAP_M */ -+#define R367_QAM_EQU_I_TESTTAP_M 0xF475 -+#define F367_QAM_I_TEST_TAP_M 0xF47500FF -+ -+/* EQU_I_TESTTAP_H */ -+#define R367_QAM_EQU_I_TESTTAP_H 0xF476 -+#define F367_QAM_I_TEST_TAP_H 0xF476001F -+ -+/* EQU_TESTAP_CFG */ -+#define R367_QAM_EQU_TESTAP_CFG 0xF477 -+#define F367_QAM_TEST_FFE_DFE_SEL 0xF4770040 -+#define F367_QAM_TEST_TAP_SELECT 0xF477003F -+ -+/* EQU_Q_TESTTAP_L */ -+#define R367_QAM_EQU_Q_TESTTAP_L 0xF478 -+#define F367_QAM_Q_TEST_TAP_L 0xF47800FF -+ -+/* EQU_Q_TESTTAP_M */ -+#define R367_QAM_EQU_Q_TESTTAP_M 0xF479 -+#define F367_QAM_Q_TEST_TAP_M 0xF47900FF -+ -+/* EQU_Q_TESTTAP_H */ -+#define R367_QAM_EQU_Q_TESTTAP_H 0xF47A -+#define F367_QAM_Q_TEST_TAP_H 0xF47A001F -+ -+/* EQU_TAP_CTRL */ -+#define R367_QAM_EQU_TAP_CTRL 0xF47B -+#define F367_QAM_MTAP_FRZ 0xF47B0010 -+#define F367_QAM_PRE_FREEZE 0xF47B0008 -+#define F367_QAM_DFE_TAPMON_EN 0xF47B0004 -+#define F367_QAM_FFE_TAPMON_EN 0xF47B0002 -+#define F367_QAM_MTAP_ONLY 0xF47B0001 -+ -+/* EQU_CTR_CRL_CONTROL_L */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_L 0xF47C -+#define F367_QAM_EQU_CTR_CRL_CONTROL_LO 0xF47C00FF -+ -+/* EQU_CTR_CRL_CONTROL_H */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_H 0xF47D -+#define F367_QAM_EQU_CTR_CRL_CONTROL_HI 0xF47D00FF -+ -+/* EQU_CTR_HIPOW_L */ -+#define R367_QAM_EQU_CTR_HIPOW_L 0xF47E -+#define F367_QAM_CTR_HIPOW_L 0xF47E00FF -+ -+/* EQU_CTR_HIPOW_H */ -+#define R367_QAM_EQU_CTR_HIPOW_H 0xF47F -+#define F367_QAM_CTR_HIPOW_H 0xF47F00FF -+ -+/* EQU_I_EQU_LO */ -+#define R367_QAM_EQU_I_EQU_LO 0xF480 -+#define F367_QAM_EQU_I_EQU_L 0xF48000FF -+ -+/* EQU_I_EQU_HI */ -+#define R367_QAM_EQU_I_EQU_HI 0xF481 -+#define F367_QAM_EQU_I_EQU_H 0xF4810003 -+ -+/* EQU_Q_EQU_LO */ -+#define R367_QAM_EQU_Q_EQU_LO 0xF482 -+#define F367_QAM_EQU_Q_EQU_L 0xF48200FF -+ -+/* EQU_Q_EQU_HI */ -+#define R367_QAM_EQU_Q_EQU_HI 0xF483 -+#define F367_QAM_EQU_Q_EQU_H 0xF4830003 -+ -+/* EQU_MAPPER */ -+#define R367_QAM_EQU_MAPPER 0xF484 -+#define F367_QAM_QUAD_AUTO 0xF4840080 -+#define F367_QAM_QUAD_INV 0xF4840040 -+#define F367_QAM_QAM_MODE 0xF4840007 -+ -+/* EQU_SWEEP_RATE */ -+#define R367_QAM_EQU_SWEEP_RATE 0xF485 -+#define F367_QAM_SNR_PER 0xF48500C0 -+#define F367_QAM_SWEEP_RATE 0xF485003F -+ -+/* EQU_SNR_LO */ -+#define R367_QAM_EQU_SNR_LO 0xF486 -+#define F367_QAM_SNR_LO 0xF48600FF -+ -+/* EQU_SNR_HI */ -+#define R367_QAM_EQU_SNR_HI 0xF487 -+#define F367_QAM_SNR_HI 0xF48700FF -+ -+/* EQU_GAMMA_LO */ -+#define R367_QAM_EQU_GAMMA_LO 0xF488 -+#define F367_QAM_GAMMA_LO 0xF48800FF -+ -+/* EQU_GAMMA_HI */ -+#define R367_QAM_EQU_GAMMA_HI 0xF489 -+#define F367_QAM_GAMMA_ME 0xF48900FF -+ -+/* EQU_ERR_GAIN */ -+#define R367_QAM_EQU_ERR_GAIN 0xF48A -+#define F367_QAM_EQA1MU 0xF48A0070 -+#define F367_QAM_CRL2MU 0xF48A000E -+#define F367_QAM_GAMMA_HI 0xF48A0001 -+ -+/* EQU_RADIUS */ -+#define R367_QAM_EQU_RADIUS 0xF48B -+#define F367_QAM_RADIUS 0xF48B00FF -+ -+/* EQU_FFE_MAINTAP */ -+#define R367_QAM_EQU_FFE_MAINTAP 0xF48C -+#define F367_QAM_FFE_MAINTAP_INIT 0xF48C00FF -+ -+/* EQU_FFE_LEAKAGE */ -+#define R367_QAM_EQU_FFE_LEAKAGE 0xF48E -+#define F367_QAM_LEAK_PER 0xF48E00F0 -+#define F367_QAM_EQU_OUTSEL 0xF48E0002 -+#define F367_QAM_PNT2DFE 0xF48E0001 -+ -+/* EQU_FFE_MAINTAP_POS */ -+#define R367_QAM_EQU_FFE_MAINTAP_POS 0xF48F -+#define F367_QAM_FFE_LEAK_EN 0xF48F0080 -+#define F367_QAM_DFE_LEAK_EN 0xF48F0040 -+#define F367_QAM_FFE_MAINTAP_POS 0xF48F003F -+ -+/* EQU_GAIN_WIDE */ -+#define R367_QAM_EQU_GAIN_WIDE 0xF490 -+#define F367_QAM_DFE_GAIN_WIDE 0xF49000F0 -+#define F367_QAM_FFE_GAIN_WIDE 0xF490000F -+ -+/* EQU_GAIN_NARROW */ -+#define R367_QAM_EQU_GAIN_NARROW 0xF491 -+#define F367_QAM_DFE_GAIN_NARROW 0xF49100F0 -+#define F367_QAM_FFE_GAIN_NARROW 0xF491000F -+ -+/* EQU_CTR_LPF_GAIN */ -+#define R367_QAM_EQU_CTR_LPF_GAIN 0xF492 -+#define F367_QAM_CTR_GTO 0xF4920080 -+#define F367_QAM_CTR_GDIR 0xF4920070 -+#define F367_QAM_SWEEP_EN 0xF4920008 -+#define F367_QAM_CTR_GINT 0xF4920007 -+ -+/* EQU_CRL_LPF_GAIN */ -+#define R367_QAM_EQU_CRL_LPF_GAIN 0xF493 -+#define F367_QAM_CRL_GTO 0xF4930080 -+#define F367_QAM_CRL_GDIR 0xF4930070 -+#define F367_QAM_SWEEP_DIR 0xF4930008 -+#define F367_QAM_CRL_GINT 0xF4930007 -+ -+/* EQU_GLOBAL_GAIN */ -+#define R367_QAM_EQU_GLOBAL_GAIN 0xF494 -+#define F367_QAM_CRL_GAIN 0xF49400F8 -+#define F367_QAM_CTR_INC_GAIN 0xF4940004 -+#define F367_QAM_CTR_FRAC 0xF4940003 -+ -+/* EQU_CRL_LD_SEN */ -+#define R367_QAM_EQU_CRL_LD_SEN 0xF495 -+#define F367_QAM_CTR_BADPOINT_EN 0xF4950080 -+#define F367_QAM_CTR_GAIN 0xF4950070 -+#define F367_QAM_LIMANEN 0xF4950008 -+#define F367_QAM_CRL_LD_SEN 0xF4950007 -+ -+/* EQU_CRL_LD_VAL */ -+#define R367_QAM_EQU_CRL_LD_VAL 0xF496 -+#define F367_QAM_CRL_BISTH_LIMIT 0xF4960080 -+#define F367_QAM_CARE_EN 0xF4960040 -+#define F367_QAM_CRL_LD_PER 0xF4960030 -+#define F367_QAM_CRL_LD_WST 0xF496000C -+#define F367_QAM_CRL_LD_TFS 0xF4960003 -+ -+/* EQU_CRL_TFR */ -+#define R367_QAM_EQU_CRL_TFR 0xF497 -+#define F367_QAM_CRL_LD_TFR 0xF49700FF -+ -+/* EQU_CRL_BISTH_LO */ -+#define R367_QAM_EQU_CRL_BISTH_LO 0xF498 -+#define F367_QAM_CRL_BISTH_LO 0xF49800FF -+ -+/* EQU_CRL_BISTH_HI */ -+#define R367_QAM_EQU_CRL_BISTH_HI 0xF499 -+#define F367_QAM_CRL_BISTH_HI 0xF49900FF -+ -+/* EQU_SWEEP_RANGE_LO */ -+#define R367_QAM_EQU_SWEEP_RANGE_LO 0xF49A -+#define F367_QAM_SWEEP_RANGE_LO 0xF49A00FF -+ -+/* EQU_SWEEP_RANGE_HI */ -+#define R367_QAM_EQU_SWEEP_RANGE_HI 0xF49B -+#define F367_QAM_SWEEP_RANGE_HI 0xF49B00FF -+ -+/* EQU_CRL_LIMITER */ -+#define R367_QAM_EQU_CRL_LIMITER 0xF49C -+#define F367_QAM_BISECTOR_EN 0xF49C0080 -+#define F367_QAM_PHEST128_EN 0xF49C0040 -+#define F367_QAM_CRL_LIM 0xF49C003F -+ -+/* EQU_MODULUS_MAP */ -+#define R367_QAM_EQU_MODULUS_MAP 0xF49D -+#define F367_QAM_PNT_DEPTH 0xF49D00E0 -+#define F367_QAM_MODULUS_CMP 0xF49D001F -+ -+/* EQU_PNT_GAIN */ -+#define R367_QAM_EQU_PNT_GAIN 0xF49E -+#define F367_QAM_PNT_EN 0xF49E0080 -+#define F367_QAM_MODULUSMAP_EN 0xF49E0040 -+#define F367_QAM_PNT_GAIN 0xF49E003F -+ -+/* FEC_AC_CTR_0 */ -+#define R367_QAM_FEC_AC_CTR_0 0xF4A8 -+#define F367_QAM_BE_BYPASS 0xF4A80020 -+#define F367_QAM_REFRESH47 0xF4A80010 -+#define F367_QAM_CT_NBST 0xF4A80008 -+#define F367_QAM_TEI_ENA 0xF4A80004 -+#define F367_QAM_DS_ENA 0xF4A80002 -+#define F367_QAM_TSMF_EN 0xF4A80001 -+ -+/* FEC_AC_CTR_1 */ -+#define R367_QAM_FEC_AC_CTR_1 0xF4A9 -+#define F367_QAM_DEINT_DEPTH 0xF4A900FF -+ -+/* FEC_AC_CTR_2 */ -+#define R367_QAM_FEC_AC_CTR_2 0xF4AA -+#define F367_QAM_DEINT_M 0xF4AA00F8 -+#define F367_QAM_DIS_UNLOCK 0xF4AA0004 -+#define F367_QAM_DESCR_MODE 0xF4AA0003 -+ -+/* FEC_AC_CTR_3 */ -+#define R367_QAM_FEC_AC_CTR_3 0xF4AB -+#define F367_QAM_DI_UNLOCK 0xF4AB0080 -+#define F367_QAM_DI_FREEZE 0xF4AB0040 -+#define F367_QAM_MISMATCH 0xF4AB0030 -+#define F367_QAM_ACQ_MODE 0xF4AB000C -+#define F367_QAM_TRK_MODE 0xF4AB0003 -+ -+/* FEC_STATUS */ -+#define R367_QAM_FEC_STATUS 0xF4AC -+#define F367_QAM_DEINT_SMCNTR 0xF4AC00E0 -+#define F367_QAM_DEINT_SYNCSTATE 0xF4AC0018 -+#define F367_QAM_DEINT_SYNLOST 0xF4AC0004 -+#define F367_QAM_DESCR_SYNCSTATE 0xF4AC0002 -+ -+/* RS_COUNTER_0 */ -+#define R367_QAM_RS_COUNTER_0 0xF4AE -+#define F367_QAM_BK_CT_L 0xF4AE00FF -+ -+/* RS_COUNTER_1 */ -+#define R367_QAM_RS_COUNTER_1 0xF4AF -+#define F367_QAM_BK_CT_H 0xF4AF00FF -+ -+/* RS_COUNTER_2 */ -+#define R367_QAM_RS_COUNTER_2 0xF4B0 -+#define F367_QAM_CORR_CT_L 0xF4B000FF -+ -+/* RS_COUNTER_3 */ -+#define R367_QAM_RS_COUNTER_3 0xF4B1 -+#define F367_QAM_CORR_CT_H 0xF4B100FF -+ -+/* RS_COUNTER_4 */ -+#define R367_QAM_RS_COUNTER_4 0xF4B2 -+#define F367_QAM_UNCORR_CT_L 0xF4B200FF -+ -+/* RS_COUNTER_5 */ -+#define R367_QAM_RS_COUNTER_5 0xF4B3 -+#define F367_QAM_UNCORR_CT_H 0xF4B300FF -+ -+/* BERT_0 */ -+#define R367_QAM_BERT_0 0xF4B4 -+#define F367_QAM_RS_NOCORR 0xF4B40004 -+#define F367_QAM_CT_HOLD 0xF4B40002 -+#define F367_QAM_CT_CLEAR 0xF4B40001 -+ -+/* BERT_1 */ -+#define R367_QAM_BERT_1 0xF4B5 -+#define F367_QAM_BERT_ON 0xF4B50020 -+#define F367_QAM_BERT_ERR_SRC 0xF4B50010 -+#define F367_QAM_BERT_ERR_MODE 0xF4B50008 -+#define F367_QAM_BERT_NBYTE 0xF4B50007 -+ -+/* BERT_2 */ -+#define R367_QAM_BERT_2 0xF4B6 -+#define F367_QAM_BERT_ERRCOUNT_L 0xF4B600FF -+ -+/* BERT_3 */ -+#define R367_QAM_BERT_3 0xF4B7 -+#define F367_QAM_BERT_ERRCOUNT_H 0xF4B700FF -+ -+/* OUTFORMAT_0 */ -+#define R367_QAM_OUTFORMAT_0 0xF4B8 -+#define F367_QAM_CLK_POLARITY 0xF4B80080 -+#define F367_QAM_FEC_TYPE 0xF4B80040 -+#define F367_QAM_SYNC_STRIP 0xF4B80008 -+#define F367_QAM_TS_SWAP 0xF4B80004 -+#define F367_QAM_OUTFORMAT 0xF4B80003 -+ -+/* OUTFORMAT_1 */ -+#define R367_QAM_OUTFORMAT_1 0xF4B9 -+#define F367_QAM_CI_DIVRANGE 0xF4B900FF -+ -+/* SMOOTHER_2 */ -+#define R367_QAM_SMOOTHER_2 0xF4BE -+#define F367_QAM_FIFO_BYPASS 0xF4BE0020 -+ -+/* TSMF_CTRL_0 */ -+#define R367_QAM_TSMF_CTRL_0 0xF4C0 -+#define F367_QAM_TS_NUMBER 0xF4C0001E -+#define F367_QAM_SEL_MODE 0xF4C00001 -+ -+/* TSMF_CTRL_1 */ -+#define R367_QAM_TSMF_CTRL_1 0xF4C1 -+#define F367_QAM_CHECK_ERROR_BIT 0xF4C10080 -+#define F367_QAM_CHCK_F_SYNC 0xF4C10040 -+#define F367_QAM_H_MODE 0xF4C10008 -+#define F367_QAM_D_V_MODE 0xF4C10004 -+#define F367_QAM_MODE 0xF4C10003 -+ -+/* TSMF_CTRL_3 */ -+#define R367_QAM_TSMF_CTRL_3 0xF4C3 -+#define F367_QAM_SYNC_IN_COUNT 0xF4C300F0 -+#define F367_QAM_SYNC_OUT_COUNT 0xF4C3000F -+ -+/* TS_ON_ID_0 */ -+#define R367_QAM_TS_ON_ID_0 0xF4C4 -+#define F367_QAM_TS_ID_L 0xF4C400FF -+ -+/* TS_ON_ID_1 */ -+#define R367_QAM_TS_ON_ID_1 0xF4C5 -+#define F367_QAM_TS_ID_H 0xF4C500FF -+ -+/* TS_ON_ID_2 */ -+#define R367_QAM_TS_ON_ID_2 0xF4C6 -+#define F367_QAM_ON_ID_L 0xF4C600FF -+ -+/* TS_ON_ID_3 */ -+#define R367_QAM_TS_ON_ID_3 0xF4C7 -+#define F367_QAM_ON_ID_H 0xF4C700FF -+ -+/* RE_STATUS_0 */ -+#define R367_QAM_RE_STATUS_0 0xF4C8 -+#define F367_QAM_RECEIVE_STATUS_L 0xF4C800FF -+ -+/* RE_STATUS_1 */ -+#define R367_QAM_RE_STATUS_1 0xF4C9 -+#define F367_QAM_RECEIVE_STATUS_LH 0xF4C900FF -+ -+/* RE_STATUS_2 */ -+#define R367_QAM_RE_STATUS_2 0xF4CA -+#define F367_QAM_RECEIVE_STATUS_HL 0xF4CA00FF -+ -+/* RE_STATUS_3 */ -+#define R367_QAM_RE_STATUS_3 0xF4CB -+#define F367_QAM_RECEIVE_STATUS_HH 0xF4CB003F -+ -+/* TS_STATUS_0 */ -+#define R367_QAM_TS_STATUS_0 0xF4CC -+#define F367_QAM_TS_STATUS_L 0xF4CC00FF -+ -+/* TS_STATUS_1 */ -+#define R367_QAM_TS_STATUS_1 0xF4CD -+#define F367_QAM_TS_STATUS_H 0xF4CD007F -+ -+/* TS_STATUS_2 */ -+#define R367_QAM_TS_STATUS_2 0xF4CE -+#define F367_QAM_ERROR 0xF4CE0080 -+#define F367_QAM_EMERGENCY 0xF4CE0040 -+#define F367_QAM_CRE_TS 0xF4CE0030 -+#define F367_QAM_VER 0xF4CE000E -+#define F367_QAM_M_LOCK 0xF4CE0001 -+ -+/* TS_STATUS_3 */ -+#define R367_QAM_TS_STATUS_3 0xF4CF -+#define F367_QAM_UPDATE_READY 0xF4CF0080 -+#define F367_QAM_END_FRAME_HEADER 0xF4CF0040 -+#define F367_QAM_CONTCNT 0xF4CF0020 -+#define F367_QAM_TS_IDENTIFIER_SEL 0xF4CF000F -+ -+/* T_O_ID_0 */ -+#define R367_QAM_T_O_ID_0 0xF4D0 -+#define F367_QAM_ON_ID_I_L 0xF4D000FF -+ -+/* T_O_ID_1 */ -+#define R367_QAM_T_O_ID_1 0xF4D1 -+#define F367_QAM_ON_ID_I_H 0xF4D100FF -+ -+/* T_O_ID_2 */ -+#define R367_QAM_T_O_ID_2 0xF4D2 -+#define F367_QAM_TS_ID_I_L 0xF4D200FF -+ -+/* T_O_ID_3 */ -+#define R367_QAM_T_O_ID_3 0xF4D3 -+#define F367_QAM_TS_ID_I_H 0xF4D300FF -+ -diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c -index 0b2a934..ba93e7b 100644 ---- a/drivers/media/dvb-frontends/stv090x.c -+++ b/drivers/media/dvb-frontends/stv090x.c -@@ -3562,6 +3562,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) - return 0; - } - -+#if 0 - static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) - { - struct stv090x_state *state = fe->demodulator_priv; -@@ -3612,6 +3613,27 @@ err: - dprintk(FE_ERROR, 1, "I/O error"); - return -1; - } -+#endif -+ -+static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv090x_state *state = fe->demodulator_priv; -+ u32 reg, h, m, l; -+ -+ /* Counter 1: S1: 0x75 BER, S2: 0x67 PER */ -+ reg = STV090x_READ_DEMOD(state, ERRCNT12); -+ h = STV090x_GETFIELD_Px(reg, ERR_CNT12_FIELD); -+ -+ reg = STV090x_READ_DEMOD(state, ERRCNT11); -+ m = STV090x_GETFIELD_Px(reg, ERR_CNT11_FIELD); -+ -+ reg = STV090x_READ_DEMOD(state, ERRCNT10); -+ l = STV090x_GETFIELD_Px(reg, ERR_CNT10_FIELD); -+ -+ *ber = ((h << 16) | (m << 8) | l); -+ -+ return 0; -+} - - static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) - { -@@ -3732,6 +3754,26 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) - return 0; - } - -+static int stv090x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct stv090x_state *state = fe->demodulator_priv; -+ u32 reg, h, m, l; -+ -+ /* Counter 2: 0xc1 TS error count */ -+ reg = STV090x_READ_DEMOD(state, ERRCNT22); -+ h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); -+ -+ reg = STV090x_READ_DEMOD(state, ERRCNT21); -+ m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); -+ -+ reg = STV090x_READ_DEMOD(state, ERRCNT20); -+ l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); -+ -+ *ucblocks = ((h << 16) | (m << 8) | l); -+ -+ return 0; -+} -+ - static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) - { - struct stv090x_state *state = fe->demodulator_priv; -@@ -4914,9 +4956,10 @@ static struct dvb_frontend_ops stv090x_ops = { - - .search = stv090x_search, - .read_status = stv090x_read_status, -- .read_ber = stv090x_read_per, -+ .read_ber = stv090x_read_ber, - .read_signal_strength = stv090x_read_signal_strength, - .read_snr = stv090x_read_cnr, -+ .read_ucblocks = stv090x_read_ucblocks, - }; - - -diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c -new file mode 100644 -index 0000000..d247932 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910.c -@@ -0,0 +1,1371 @@ -+/* -+ * Driver for the ST STV0910 DVB-S/S2 demodulator. -+ * -+ * Copyright (C) 2014 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "stv0910.h" -+#include "stv0910_regs.h" -+ -+ -+#define TUNING_DELAY 200 -+#define BER_SRC_S 0x20 -+#define BER_SRC_S2 0x20 -+ -+LIST_HEAD(stvlist); -+ -+enum ReceiveMode { Mode_None, Mode_DVBS, Mode_DVBS2, Mode_Auto }; -+ -+ -+enum DVBS2_FECType { DVBS2_64K, DVBS2_16K }; -+ -+enum DVBS2_ModCod { -+ DVBS2_DUMMY_PLF, DVBS2_QPSK_1_4, DVBS2_QPSK_1_3, DVBS2_QPSK_2_5, -+ DVBS2_QPSK_1_2, DVBS2_QPSK_3_5, DVBS2_QPSK_2_3, DVBS2_QPSK_3_4, -+ DVBS2_QPSK_4_5, DVBS2_QPSK_5_6, DVBS2_QPSK_8_9, DVBS2_QPSK_9_10, -+ DVBS2_8PSK_3_5, DVBS2_8PSK_2_3, DVBS2_8PSK_3_4, DVBS2_8PSK_5_6, -+ DVBS2_8PSK_8_9, DVBS2_8PSK_9_10, DVBS2_16APSK_2_3, DVBS2_16APSK_3_4, -+ DVBS2_16APSK_4_5, DVBS2_16APSK_5_6, DVBS2_16APSK_8_9, DVBS2_16APSK_9_10, -+ DVBS2_32APSK_3_4, DVBS2_32APSK_4_5, DVBS2_32APSK_5_6, DVBS2_32APSK_8_9, -+ DVBS2_32APSK_9_10 -+}; -+ -+enum FE_STV0910_ModCod { -+ FE_DUMMY_PLF, FE_QPSK_14, FE_QPSK_13, FE_QPSK_25, -+ FE_QPSK_12, FE_QPSK_35, FE_QPSK_23, FE_QPSK_34, -+ FE_QPSK_45, FE_QPSK_56, FE_QPSK_89, FE_QPSK_910, -+ FE_8PSK_35, FE_8PSK_23, FE_8PSK_34, FE_8PSK_56, -+ FE_8PSK_89, FE_8PSK_910, FE_16APSK_23, FE_16APSK_34, -+ FE_16APSK_45, FE_16APSK_56, FE_16APSK_89, FE_16APSK_910, -+ FE_32APSK_34, FE_32APSK_45, FE_32APSK_56, FE_32APSK_89, -+ FE_32APSK_910 -+}; -+ -+enum FE_STV0910_RollOff { FE_SAT_35, FE_SAT_25, FE_SAT_20, FE_SAT_15 }; -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+struct stv_base { -+ struct list_head stvlist; -+ -+ u8 adr; -+ struct i2c_adapter *i2c; -+ struct mutex i2c_lock; -+ struct mutex reg_lock; -+ int count; -+ -+ u32 extclk; -+ u32 mclk; -+}; -+ -+struct stv { -+ struct stv_base *base; -+ struct dvb_frontend fe; -+ int nr; -+ u16 regoff; -+ u8 i2crpt; -+ u8 tscfgh; -+ u8 tsspeed; -+ unsigned long tune_time; -+ -+ s32 SearchRange; -+ u32 Started; -+ u32 DemodLockTime; -+ enum ReceiveMode ReceiveMode; -+ u32 DemodTimeout; -+ u32 FecTimeout; -+ u32 FirstTimeLock; -+ u8 DEMOD; -+ u32 SymbolRate; -+ -+ u8 LastViterbiRate; -+ enum fe_code_rate PunctureRate; -+ enum FE_STV0910_ModCod ModCod; -+ enum DVBS2_FECType FECType; -+ u32 Pilots; -+ enum FE_STV0910_RollOff FERollOff; -+ -+ u32 LastBERNumerator; -+ u32 LastBERDenominator; -+ u8 BERScale; -+}; -+ -+struct SInitTable { -+ u16 Address; -+ u8 Data; -+}; -+ -+struct SLookupSNTable { -+ s16 SignalToNoise; -+ u16 RefValue; -+}; -+ -+static inline int i2c_write(struct i2c_adapter *adap, u8 adr, -+ u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static int write_reg(struct stv *state, u16 reg, u8 val) -+{ -+ return i2c_write_reg16(state->base->i2c, state->base->adr, reg, val); -+} -+ -+static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int read_reg(struct stv *state, u16 reg, u8 *val) -+{ -+ return i2c_read_reg16(state->base->i2c, state->base->adr, reg, val); -+} -+ -+ -+static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val, int len) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int read_regs(struct stv *state, u16 reg, u8 *val, int len) -+{ -+ return i2c_read_regs16(state->base->i2c, state->base->adr, -+ reg, val, len); -+} -+ -+struct SLookupSNTable S1_SN_Lookup[] = { -+ { 0, 9242 }, /*C/N= 0dB*/ -+ { 05, 9105 }, /*C/N=0.5dB*/ -+ { 10, 8950 }, /*C/N=1.0dB*/ -+ { 15, 8780 }, /*C/N=1.5dB*/ -+ { 20, 8566 }, /*C/N=2.0dB*/ -+ { 25, 8366 }, /*C/N=2.5dB*/ -+ { 30, 8146 }, /*C/N=3.0dB*/ -+ { 35, 7908 }, /*C/N=3.5dB*/ -+ { 40, 7666 }, /*C/N=4.0dB*/ -+ { 45, 7405 }, /*C/N=4.5dB*/ -+ { 50, 7136 }, /*C/N=5.0dB*/ -+ { 55, 6861 }, /*C/N=5.5dB*/ -+ { 60, 6576 }, /*C/N=6.0dB*/ -+ { 65, 6330 }, /*C/N=6.5dB*/ -+ { 70, 6048 }, /*C/N=7.0dB*/ -+ { 75, 5768 }, /*C/N=7.5dB*/ -+ { 80, 5492 }, /*C/N=8.0dB*/ -+ { 85, 5224 }, /*C/N=8.5dB*/ -+ { 90, 4959 }, /*C/N=9.0dB*/ -+ { 95, 4709 }, /*C/N=9.5dB*/ -+ { 100, 4467 }, /*C/N=10.0dB*/ -+ { 105, 4236 }, /*C/N=10.5dB*/ -+ { 110, 4013 }, /*C/N=11.0dB*/ -+ { 115, 3800 }, /*C/N=11.5dB*/ -+ { 120, 3598 }, /*C/N=12.0dB*/ -+ { 125, 3406 }, /*C/N=12.5dB*/ -+ { 130, 3225 }, /*C/N=13.0dB*/ -+ { 135, 3052 }, /*C/N=13.5dB*/ -+ { 140, 2889 }, /*C/N=14.0dB*/ -+ { 145, 2733 }, /*C/N=14.5dB*/ -+ { 150, 2587 }, /*C/N=15.0dB*/ -+ { 160, 2318 }, /*C/N=16.0dB*/ -+ { 170, 2077 }, /*C/N=17.0dB*/ -+ { 180, 1862 }, /*C/N=18.0dB*/ -+ { 190, 1670 }, /*C/N=19.0dB*/ -+ { 200, 1499 }, /*C/N=20.0dB*/ -+ { 210, 1347 }, /*C/N=21.0dB*/ -+ { 220, 1213 }, /*C/N=22.0dB*/ -+ { 230, 1095 }, /*C/N=23.0dB*/ -+ { 240, 992 }, /*C/N=24.0dB*/ -+ { 250, 900 }, /*C/N=25.0dB*/ -+ { 260, 826 }, /*C/N=26.0dB*/ -+ { 270, 758 }, /*C/N=27.0dB*/ -+ { 280, 702 }, /*C/N=28.0dB*/ -+ { 290, 653 }, /*C/N=29.0dB*/ -+ { 300, 613 }, /*C/N=30.0dB*/ -+ { 310, 579 }, /*C/N=31.0dB*/ -+ { 320, 550 }, /*C/N=32.0dB*/ -+ { 330, 526 }, /*C/N=33.0dB*/ -+ { 350, 490 }, /*C/N=33.0dB*/ -+ { 400, 445 }, /*C/N=40.0dB*/ -+ { 450, 430 }, /*C/N=45.0dB*/ -+ { 500, 426 }, /*C/N=50.0dB*/ -+ { 510, 425 } /*C/N=51.0dB*/ -+}; -+ -+struct SLookupSNTable S2_SN_Lookup[] = { -+ { -30, 13950 }, /*C/N=-2.5dB*/ -+ { -25, 13580 }, /*C/N=-2.5dB*/ -+ { -20, 13150 }, /*C/N=-2.0dB*/ -+ { -15, 12760 }, /*C/N=-1.5dB*/ -+ { -10, 12345 }, /*C/N=-1.0dB*/ -+ { -05, 11900 }, /*C/N=-0.5dB*/ -+ { 0, 11520 }, /*C/N= 0dB*/ -+ { 05, 11080 }, /*C/N= 0.5dB*/ -+ { 10, 10630 }, /*C/N= 1.0dB*/ -+ { 15, 10210 }, /*C/N= 1.5dB*/ -+ { 20, 9790 }, /*C/N= 2.0dB*/ -+ { 25, 9390 }, /*C/N= 2.5dB*/ -+ { 30, 8970 }, /*C/N= 3.0dB*/ -+ { 35, 8575 }, /*C/N= 3.5dB*/ -+ { 40, 8180 }, /*C/N= 4.0dB*/ -+ { 45, 7800 }, /*C/N= 4.5dB*/ -+ { 50, 7430 }, /*C/N= 5.0dB*/ -+ { 55, 7080 }, /*C/N= 5.5dB*/ -+ { 60, 6720 }, /*C/N= 6.0dB*/ -+ { 65, 6320 }, /*C/N= 6.5dB*/ -+ { 70, 6060 }, /*C/N= 7.0dB*/ -+ { 75, 5760 }, /*C/N= 7.5dB*/ -+ { 80, 5480 }, /*C/N= 8.0dB*/ -+ { 85, 5200 }, /*C/N= 8.5dB*/ -+ { 90, 4930 }, /*C/N= 9.0dB*/ -+ { 95, 4680 }, /*C/N= 9.5dB*/ -+ { 100, 4425 }, /*C/N=10.0dB*/ -+ { 105, 4210 }, /*C/N=10.5dB*/ -+ { 110, 3980 }, /*C/N=11.0dB*/ -+ { 115, 3765 }, /*C/N=11.5dB*/ -+ { 120, 3570 }, /*C/N=12.0dB*/ -+ { 125, 3315 }, /*C/N=12.5dB*/ -+ { 130, 3140 }, /*C/N=13.0dB*/ -+ { 135, 2980 }, /*C/N=13.5dB*/ -+ { 140, 2820 }, /*C/N=14.0dB*/ -+ { 145, 2670 }, /*C/N=14.5dB*/ -+ { 150, 2535 }, /*C/N=15.0dB*/ -+ { 160, 2270 }, /*C/N=16.0dB*/ -+ { 170, 2035 }, /*C/N=17.0dB*/ -+ { 180, 1825 }, /*C/N=18.0dB*/ -+ { 190, 1650 }, /*C/N=19.0dB*/ -+ { 200, 1485 }, /*C/N=20.0dB*/ -+ { 210, 1340 }, /*C/N=21.0dB*/ -+ { 220, 1212 }, /*C/N=22.0dB*/ -+ { 230, 1100 }, /*C/N=23.0dB*/ -+ { 240, 1000 }, /*C/N=24.0dB*/ -+ { 250, 910 }, /*C/N=25.0dB*/ -+ { 260, 836 }, /*C/N=26.0dB*/ -+ { 270, 772 }, /*C/N=27.0dB*/ -+ { 280, 718 }, /*C/N=28.0dB*/ -+ { 290, 671 }, /*C/N=29.0dB*/ -+ { 300, 635 }, /*C/N=30.0dB*/ -+ { 310, 602 }, /*C/N=31.0dB*/ -+ { 320, 575 }, /*C/N=32.0dB*/ -+ { 330, 550 }, /*C/N=33.0dB*/ -+ { 350, 517 }, /*C/N=35.0dB*/ -+ { 400, 480 }, /*C/N=40.0dB*/ -+ { 450, 466 }, /*C/N=45.0dB*/ -+ { 500, 464 }, /*C/N=50.0dB*/ -+ { 510, 463 }, /*C/N=51.0dB*/ -+}; -+ -+/********************************************************************* -+Tracking carrier loop carrier QPSK 1/4 to 8PSK 9/10 long Frame -+*********************************************************************/ -+static u8 S2CarLoop[] = { -+ /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff -+ 20MPon 20MPoff 30MPon 30MPoff*/ -+ /* FE_QPSK_14 */ -+ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, -+ /* FE_QPSK_13 */ -+ 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, -+ /* FE_QPSK_25 */ -+ 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, -+ /* FE_QPSK_12 */ -+ 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_35 */ -+ 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_23 */ -+ 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, -+ /* FE_QPSK_34 */ -+ 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, -+ /* FE_QPSK_45 */ -+ 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, -+ /* FE_QPSK_56 */ -+ 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, -+ /* FE_QPSK_89 */ -+ 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, -+ /* FE_QPSK_910 */ -+ 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, -+ /* FE_8PSK_35 */ -+ 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, -+ /* FE_8PSK_23 */ -+ 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, -+ /* FE_8PSK_34 */ -+ 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, -+ /* FE_8PSK_56 */ -+ 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, -+ /* FE_8PSK_89 */ -+ 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, -+ /* FE_8PSK_910 */ -+ 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, -+ -+ /********************************************************************** -+ Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame -+ **********************************************************************/ -+ /*Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon -+ 20MPoff 30MPon 30MPoff*/ -+ /* FE_16APSK_23 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, -+ /* FE_16APSK_34 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, -+ /* FE_16APSK_45 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, -+ /* FE_16APSK_56 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, -+ /* FE_16APSK_89 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, -+ /* FE_16APSK_910 */ -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, -+ /* FE_32APSK_34 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_45 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_56 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_89 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+ /* FE_32APSK_910 */ -+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, -+}; -+ -+static u8 get_optim_cloop(struct stv *state, -+ enum FE_STV0910_ModCod ModCod, u32 Pilots) -+{ -+ int i = 0; -+ if (ModCod >= FE_32APSK_910) -+ i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; -+ else if (ModCod >= FE_QPSK_14) -+ i = ((int)ModCod - (int)FE_QPSK_14) * 10; -+ -+ if (state->SymbolRate <= 3000000) -+ i += 0; -+ else if (state->SymbolRate <= 7000000) -+ i += 2; -+ else if (state->SymbolRate <= 15000000) -+ i += 4; -+ else if (state->SymbolRate <= 25000000) -+ i += 6; -+ else -+ i += 8; -+ -+ if (!Pilots) -+ i += 1; -+ -+ return S2CarLoop[i]; -+} -+ -+static int GetCurSymbolRate(struct stv *state, u32 *pSymbolRate) -+{ -+ int status = 0; -+ u8 SymbFreq0; -+ u8 SymbFreq1; -+ u8 SymbFreq2; -+ u8 SymbFreq3; -+ u8 TimOffs0; -+ u8 TimOffs1; -+ u8 TimOffs2; -+ u32 SymbolRate; -+ s32 TimingOffset; -+ -+ *pSymbolRate = 0; -+ if (!state->Started) -+ return status; -+ -+ read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &SymbFreq3); -+ read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &SymbFreq2); -+ read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &SymbFreq1); -+ read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &SymbFreq0); -+ read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &TimOffs2); -+ read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &TimOffs1); -+ read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &TimOffs0); -+ -+ SymbolRate = ((u32) SymbFreq3 << 24) | ((u32) SymbFreq2 << 16) | -+ ((u32) SymbFreq1 << 8) | (u32) SymbFreq0; -+ TimingOffset = ((u32) TimOffs2 << 16) | ((u32) TimOffs1 << 8) | -+ (u32) TimOffs0; -+ -+ if ((TimingOffset & (1<<23)) != 0) -+ TimingOffset |= 0xFF000000; /* Sign extent */ -+ -+ SymbolRate = (u32) (((u64) SymbolRate * state->base->mclk) >> 32); -+ TimingOffset = (s32) (((s64) SymbolRate * (s64) TimingOffset) >> 29); -+ -+ *pSymbolRate = SymbolRate + TimingOffset; -+ -+ return 0; -+} -+ -+static int GetSignalParameters(struct stv *state) -+{ -+ if (!state->Started) -+ return -1; -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ u8 tmp; -+ u8 rolloff; -+ -+ read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); -+ state->ModCod = (enum FE_STV0910_ModCod) ((tmp & 0x7c) >> 2); -+ state->Pilots = (tmp & 0x01) != 0; -+ state->FECType = (enum DVBS2_FECType) ((tmp & 0x02) >> 1); -+ -+ read_reg(state, RSTV0910_P2_TMGOBS + state->regoff, &rolloff); -+ rolloff = rolloff >> 6; -+ state->FERollOff = (enum FE_STV0910_RollOff) rolloff; -+ -+ } else if (state->ReceiveMode == Mode_DVBS) { -+ /* todo */ -+ } -+ return 0; -+} -+ -+static int TrackingOptimization(struct stv *state) -+{ -+ u32 SymbolRate = 0; -+ u8 tmp; -+ -+ GetCurSymbolRate(state, &SymbolRate); -+ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); -+ tmp &= ~0xC0; -+ -+ switch (state->ReceiveMode) { -+ case Mode_DVBS: -+ tmp |= 0x40; break; -+ case Mode_DVBS2: -+ tmp |= 0x80; break; -+ default: -+ tmp |= 0xC0; break; -+ } -+ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ /* force to PRE BCH Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S2 | state->BERScale); -+ -+ if (state->FECType == DVBS2_64K) { -+ u8 aclc = get_optim_cloop(state, state->ModCod, -+ state->Pilots); -+ -+ if (state->ModCod <= FE_QPSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_8PSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S28 + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_16APSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S216A + -+ state->regoff, aclc); -+ } else if (state->ModCod <= FE_32APSK_910) { -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + -+ state->regoff, 0x2a); -+ write_reg(state, RSTV0910_P2_ACLC2S232A + -+ state->regoff, aclc); -+ } -+ } -+ } -+ if (state->ReceiveMode == Mode_DVBS) { -+ u8 tmp; -+ -+ read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); -+ state->PunctureRate = FEC_NONE; -+ switch (tmp & 0x1F) { -+ case 0x0d: -+ state->PunctureRate = FEC_1_2; -+ break; -+ case 0x12: -+ state->PunctureRate = FEC_2_3; -+ break; -+ case 0x15: -+ state->PunctureRate = FEC_3_4; -+ break; -+ case 0x18: -+ state->PunctureRate = FEC_5_6; -+ break; -+ case 0x1A: -+ state->PunctureRate = FEC_7_8; -+ break; -+ } -+ } -+ return 0; -+} -+ -+static int GetSignalToNoise(struct stv *state, s32 *SignalToNoise) -+{ -+ int i; -+ u8 Data0; -+ u8 Data1; -+ u16 Data; -+ int nLookup; -+ struct SLookupSNTable *Lookup; -+ -+ *SignalToNoise = 0; -+ -+ if (!state->Started) -+ return 0; -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, &Data1); -+ read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, &Data0); -+ nLookup = ARRAY_SIZE(S2_SN_Lookup); -+ Lookup = S2_SN_Lookup; -+ } else { -+ read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, &Data1); -+ read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, &Data0); -+ nLookup = ARRAY_SIZE(S1_SN_Lookup); -+ Lookup = S1_SN_Lookup; -+ } -+ Data = (((u16)Data1) << 8) | (u16) Data0; -+ if (Data > Lookup[0].RefValue) { -+ *SignalToNoise = Lookup[0].SignalToNoise; -+ } else if (Data <= Lookup[nLookup-1].RefValue) { -+ *SignalToNoise = Lookup[nLookup-1].SignalToNoise; -+ } else { -+ for (i = 0; i < nLookup - 1; i += 1) { -+ if (Data <= Lookup[i].RefValue && -+ Data > Lookup[i+1].RefValue) { -+ *SignalToNoise = -+ (s32)(Lookup[i].SignalToNoise) + -+ ((s32)(Data - Lookup[i].RefValue) * -+ (s32)(Lookup[i+1].SignalToNoise - -+ Lookup[i].SignalToNoise)) / -+ ((s32)(Lookup[i+1].RefValue) - -+ (s32)(Lookup[i].RefValue)); -+ break; -+ } -+ } -+ } -+ return 0; -+} -+ -+static int GetBitErrorRateS(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ u8 Regs[3]; -+ -+ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, -+ Regs, 3); -+ -+ if (status) -+ return -1; -+ -+ if ((Regs[0] & 0x80) == 0) { -+ state->LastBERDenominator = 1 << ((state->BERScale * 2) + -+ 10 + 3); -+ state->LastBERNumerator = ((u32) (Regs[0] & 0x7F) << 16) | -+ ((u32) Regs[1] << 8) | Regs[2]; -+ if (state->LastBERNumerator < 256 && state->BERScale < 6) { -+ state->BERScale += 1; -+ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + -+ state->regoff, -+ 0x20 | state->BERScale); -+ } else if (state->LastBERNumerator > 1024 && -+ state->BERScale > 2) { -+ state->BERScale -= 1; -+ status = write_reg(state, RSTV0910_P2_ERRCTRL1 + -+ state->regoff, 0x20 | -+ state->BERScale); -+ } -+ } -+ *BERNumerator = state->LastBERNumerator; -+ *BERDenominator = state->LastBERDenominator; -+ return 0; -+} -+ -+static u32 DVBS2_nBCH(enum DVBS2_ModCod ModCod, enum DVBS2_FECType FECType) -+{ -+ static u32 nBCH[][2] = { -+ {16200, 3240}, /* QPSK_1_4, */ -+ {21600, 5400}, /* QPSK_1_3, */ -+ {25920, 6480}, /* QPSK_2_5, */ -+ {32400, 7200}, /* QPSK_1_2, */ -+ {38880, 9720}, /* QPSK_3_5, */ -+ {43200, 10800}, /* QPSK_2_3, */ -+ {48600, 11880}, /* QPSK_3_4, */ -+ {51840, 12600}, /* QPSK_4_5, */ -+ {54000, 13320}, /* QPSK_5_6, */ -+ {57600, 14400}, /* QPSK_8_9, */ -+ {58320, 16000}, /* QPSK_9_10, */ -+ {43200, 9720}, /* 8PSK_3_5, */ -+ {48600, 10800}, /* 8PSK_2_3, */ -+ {51840, 11880}, /* 8PSK_3_4, */ -+ {54000, 13320}, /* 8PSK_5_6, */ -+ {57600, 14400}, /* 8PSK_8_9, */ -+ {58320, 16000}, /* 8PSK_9_10, */ -+ {43200, 10800}, /* 16APSK_2_3, */ -+ {48600, 11880}, /* 16APSK_3_4, */ -+ {51840, 12600}, /* 16APSK_4_5, */ -+ {54000, 13320}, /* 16APSK_5_6, */ -+ {57600, 14400}, /* 16APSK_8_9, */ -+ {58320, 16000}, /* 16APSK_9_10 */ -+ {48600, 11880}, /* 32APSK_3_4, */ -+ {51840, 12600}, /* 32APSK_4_5, */ -+ {54000, 13320}, /* 32APSK_5_6, */ -+ {57600, 14400}, /* 32APSK_8_9, */ -+ {58320, 16000}, /* 32APSK_9_10 */ -+ }; -+ -+ if (ModCod >= DVBS2_QPSK_1_4 && -+ ModCod <= DVBS2_32APSK_9_10 && FECType <= DVBS2_16K) -+ return nBCH[FECType][ModCod]; -+ return 64800; -+} -+ -+static int GetBitErrorRateS2(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ u8 Regs[3]; -+ -+ int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, -+ Regs, 3); -+ -+ if (status) -+ return -1; -+ -+ if ((Regs[0] & 0x80) == 0) { -+ state->LastBERDenominator = -+ DVBS2_nBCH((enum DVBS2_ModCod) state->ModCod, -+ state->FECType) << -+ (state->BERScale * 2); -+ state->LastBERNumerator = (((u32) Regs[0] & 0x7F) << 16) | -+ ((u32) Regs[1] << 8) | Regs[2]; -+ if (state->LastBERNumerator < 256 && state->BERScale < 6) { -+ state->BERScale += 1; -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ 0x20 | state->BERScale); -+ } else if (state->LastBERNumerator > 1024 && -+ state->BERScale > 2) { -+ state->BERScale -= 1; -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ 0x20 | state->BERScale); -+ } -+ } -+ *BERNumerator = state->LastBERNumerator; -+ *BERDenominator = state->LastBERDenominator; -+ return status; -+} -+ -+static int GetBitErrorRate(struct stv *state, u32 *BERNumerator, -+ u32 *BERDenominator) -+{ -+ *BERNumerator = 0; -+ *BERDenominator = 1; -+ -+ switch (state->ReceiveMode) { -+ case Mode_DVBS: -+ return GetBitErrorRateS(state, BERNumerator, BERDenominator); -+ break; -+ case Mode_DVBS2: -+ return GetBitErrorRateS2(state, BERNumerator, BERDenominator); -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static int init(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+ -+static int set_mclock(struct stv *state, u32 MasterClock) -+{ -+ u32 idf = 1; -+ u32 odf = 4; -+ u32 quartz = state->base->extclk / 1000000; -+ u32 Fphi = MasterClock / 1000000; -+ u32 ndiv = (Fphi * odf * idf) / quartz; -+ u32 cp = 7; -+ u32 fvco; -+ -+ if (ndiv >= 7 && ndiv <= 71) -+ cp = 7; -+ else if (ndiv >= 72 && ndiv <= 79) -+ cp = 8; -+ else if (ndiv >= 80 && ndiv <= 87) -+ cp = 9; -+ else if (ndiv >= 88 && ndiv <= 95) -+ cp = 10; -+ else if (ndiv >= 96 && ndiv <= 103) -+ cp = 11; -+ else if (ndiv >= 104 && ndiv <= 111) -+ cp = 12; -+ else if (ndiv >= 112 && ndiv <= 119) -+ cp = 13; -+ else if (ndiv >= 120 && ndiv <= 127) -+ cp = 14; -+ else if (ndiv >= 128 && ndiv <= 135) -+ cp = 15; -+ else if (ndiv >= 136 && ndiv <= 143) -+ cp = 16; -+ else if (ndiv >= 144 && ndiv <= 151) -+ cp = 17; -+ else if (ndiv >= 152 && ndiv <= 159) -+ cp = 18; -+ else if (ndiv >= 160 && ndiv <= 167) -+ cp = 19; -+ else if (ndiv >= 168 && ndiv <= 175) -+ cp = 20; -+ else if (ndiv >= 176 && ndiv <= 183) -+ cp = 21; -+ else if (ndiv >= 184 && ndiv <= 191) -+ cp = 22; -+ else if (ndiv >= 192 && ndiv <= 199) -+ cp = 23; -+ else if (ndiv >= 200 && ndiv <= 207) -+ cp = 24; -+ else if (ndiv >= 208 && ndiv <= 215) -+ cp = 25; -+ else if (ndiv >= 216 && ndiv <= 223) -+ cp = 26; -+ else if (ndiv >= 224 && ndiv <= 225) -+ cp = 27; -+ -+ write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); -+ write_reg(state, RSTV0910_NCOARSE2, odf); -+ write_reg(state, RSTV0910_NCOARSE1, ndiv); -+ -+ fvco = (quartz * 2 * ndiv) / idf; -+ state->base->mclk = fvco / (2 * odf) * 1000000; -+ -+ pr_info("ndiv = %d, MasterClock = %d\n", ndiv, state->base->mclk); -+ return 0; -+} -+ -+static int Stop(struct stv *state) -+{ -+ if (state->Started) { -+ u8 tmp; -+ -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh | 0x01); -+ read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); -+ tmp &= ~0x01; /*release reset DVBS2 packet delin*/ -+ write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); -+ /* Blind optim*/ -+ write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); -+ /* Stop the demod */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); -+ state->Started = 0; -+ } -+ state->ReceiveMode = Mode_None; -+ return 0; -+} -+ -+ -+static int Start(struct stv *state, struct dtv_frontend_properties *p) -+{ -+ s32 Freq; -+ u8 regDMDCFGMD; -+ u16 symb; -+ -+ if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) -+ return -EINVAL; -+ -+ state->ReceiveMode = Mode_None; -+ state->DemodLockTime = 0; -+ -+ /* Demod Stop*/ -+ if (state->Started) -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); -+ -+ if (p->symbol_rate <= 1000000) { /*SR <=1Msps*/ -+ state->DemodTimeout = 3000; -+ state->FecTimeout = 2000; -+ } else if (p->symbol_rate <= 2000000) { /*1Msps < SR <=2Msps*/ -+ state->DemodTimeout = 2500; -+ state->FecTimeout = 1300; -+ } else if (p->symbol_rate <= 5000000) { /*2Msps< SR <=5Msps*/ -+ state->DemodTimeout = 1000; -+ state->FecTimeout = 650; -+ } else if (p->symbol_rate <= 10000000) { /*5Msps< SR <=10Msps*/ -+ state->DemodTimeout = 700; -+ state->FecTimeout = 350; -+ } else if (p->symbol_rate < 20000000) { /*10Msps< SR <=20Msps*/ -+ state->DemodTimeout = 400; -+ state->FecTimeout = 200; -+ } else { /*SR >=20Msps*/ -+ state->DemodTimeout = 300; -+ state->FecTimeout = 200; -+ } -+ -+ /* Set the Init Symbol rate*/ -+ symb = MulDiv32(p->symbol_rate, 65536, state->base->mclk); -+ write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, -+ ((symb >> 8) & 0x7F)); -+ write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); -+ -+ pr_info("symb = %u\n", symb); -+ -+ state->DEMOD |= 0x80; -+ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->DEMOD); -+ -+ /* FE_STV0910_SetSearchStandard */ -+ read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®DMDCFGMD); -+ write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, -+ regDMDCFGMD |= 0xC0); -+ -+ /* Disable DSS */ -+ write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); -+ write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); -+ -+ /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/ -+ write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); -+ write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); -+ write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); -+ write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); -+ write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); -+ /* Reset demod */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); -+ -+ write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); -+ -+ Freq = (state->SearchRange / 2000) + 600; -+ if (p->symbol_rate <= 5000000) -+ Freq -= (600 + 80); -+ Freq = (Freq << 16) / (state->base->mclk / 1000); -+ -+ write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, -+ (Freq >> 8) & 0xff); -+ write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (Freq & 0xff)); -+ /*CFR Low Setting*/ -+ Freq = -Freq; -+ write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, -+ (Freq >> 8) & 0xff); -+ write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (Freq & 0xff)); -+ -+ /* init the demod frequency offset to 0 */ -+ write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); -+ write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); -+ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); -+ /* Trigger acq */ -+ write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); -+ -+ state->DemodLockTime += TUNING_DELAY; -+ state->Started = 1; -+ -+ return 0; -+} -+ -+static int init_diseqc(struct stv *state) -+{ -+ u16 offs = state->nr ? 0x40 : 0; /* Address offset */ -+ u8 Freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); -+ -+ /* Disable receiver */ -+ write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ -+ write_reg(state, RSTV0910_P1_DISTXF22 + offs, Freq); -+ return 0; -+} -+ -+static int probe(struct stv *state) -+{ -+ u8 id; -+ -+ state->ReceiveMode = Mode_None; -+ state->Started = 0; -+ -+ if (read_reg(state, RSTV0910_MID, &id) < 0) -+ return -1; -+ -+ if (id != 0x51) -+ return -EINVAL; -+ pr_info("Found STV0910 id=0x%02x\n", id); -+ -+ /* Configure the I2C repeater to off */ -+ write_reg(state, RSTV0910_P1_I2CRPT, 0x24); -+ /* Configure the I2C repeater to off */ -+ write_reg(state, RSTV0910_P2_I2CRPT, 0x24); -+ /* Set the I2C to oversampling ratio */ -+ write_reg(state, RSTV0910_I2CCFG, 0x88); -+ -+ write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ -+ write_reg(state, RSTV0910_PADCFG, 0x05); /* RF AGC Pads Dev = 05 */ -+ write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ -+ write_reg(state, RSTV0910_TSGENERAL, 0x00); /* TSGENERAL */ -+ write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ -+ write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ -+ -+ -+ write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ -+ write_reg(state, RSTV0910_TSTRES0, 0x00); -+ -+ set_mclock(state, 135000000); -+ -+ /* TS output */ -+ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); -+ write_reg(state, RSTV0910_P1_TSCFGM , 0xC0); /* Manual speed */ -+ write_reg(state, RSTV0910_P1_TSCFGL , 0x20); -+ -+ /* Speed = 67.5 MHz */ -+ write_reg(state, RSTV0910_P1_TSSPEED , state->tsspeed); -+ -+ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); -+ write_reg(state, RSTV0910_P2_TSCFGM , 0xC0); /* Manual speed */ -+ write_reg(state, RSTV0910_P2_TSCFGL , 0x20); -+ -+ /* Speed = 67.5 MHz */ -+ write_reg(state, RSTV0910_P2_TSSPEED , state->tsspeed); -+ -+ /* Reset stream merger */ -+ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P1_TSCFGH , state->tscfgh); -+ write_reg(state, RSTV0910_P2_TSCFGH , state->tscfgh); -+ -+ write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); -+ write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); -+ -+ init_diseqc(state); -+ return 0; -+} -+ -+ -+static int gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 i2crpt = state->i2crpt & ~0x86; -+ -+ if (enable) -+ mutex_lock(&state->base->i2c_lock); -+ -+ if (enable) -+ i2crpt |= 0x80; -+ else -+ i2crpt |= 0x02; -+ -+ if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : -+ RSTV0910_P1_I2CRPT, i2crpt) < 0) -+ return -EIO; -+ -+ state->i2crpt = i2crpt; -+ -+ if (!enable) -+ mutex_unlock(&state->base->i2c_lock); -+ return 0; -+} -+ -+static void release(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->demodulator_priv; -+ -+ state->base->count--; -+ if (state->base->count == 0) { -+ pr_info("remove STV base\n"); -+ list_del(&state->base->stvlist); -+ kfree(state->base); -+ } -+ kfree(state); -+} -+ -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat = 0; -+ struct stv *state = fe->demodulator_priv; -+ u32 IF; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ -+ Stop(state); -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ if (fe->ops.tuner_ops.get_if_frequency) -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ state->SymbolRate = p->symbol_rate; -+ stat = Start(state, p); -+ return stat; -+} -+ -+ -+static int read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 DmdState = 0; -+ u8 DStatus = 0; -+ enum ReceiveMode CurReceiveMode = Mode_None; -+ u32 FECLock = 0; -+ -+ read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &DmdState); -+ -+ if (DmdState & 0x40) { -+ read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &DStatus); -+ if (DStatus & 0x08) -+ CurReceiveMode = (DmdState & 0x20) ? -+ Mode_DVBS : Mode_DVBS2; -+ } -+ if (CurReceiveMode == Mode_None) { -+ *status = 0; -+ return 0; -+ } -+ -+ *status |= 0x0f; -+ if (state->ReceiveMode == Mode_None) { -+ state->ReceiveMode = CurReceiveMode; -+ state->DemodLockTime = jiffies; -+ state->FirstTimeLock = 0; -+ -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh); -+ usleep_range(3000, 4000); -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh | 0x01); -+ write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, -+ state->tscfgh); -+ } -+ if (DmdState & 0x40) { -+ if (state->ReceiveMode == Mode_DVBS2) { -+ u8 PDELStatus; -+ read_reg(state, -+ RSTV0910_P2_PDELSTATUS1 + state->regoff, -+ &PDELStatus); -+ FECLock = (PDELStatus & 0x02) != 0; -+ } else { -+ u8 VStatus; -+ read_reg(state, -+ RSTV0910_P2_VSTATUSVIT + state->regoff, -+ &VStatus); -+ FECLock = (VStatus & 0x08) != 0; -+ } -+ } -+ -+ if (!FECLock) -+ return 0; -+ -+ *status |= 0x10; -+ -+ if (state->FirstTimeLock) { -+ u8 tmp; -+ -+ state->FirstTimeLock = 0; -+ GetSignalParameters(state); -+ -+ if (state->ReceiveMode == Mode_DVBS2) { -+ /* FSTV0910_P2_MANUALSX_ROLLOFF, -+ FSTV0910_P2_MANUALS2_ROLLOFF = 0 */ -+ state->DEMOD &= ~0x84; -+ write_reg(state, RSTV0910_P2_DEMOD + state->regoff, -+ state->DEMOD); -+ read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ &tmp); -+ /*reset DVBS2 packet delinator error counter */ -+ tmp |= 0x40; -+ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ tmp); -+ /*reset DVBS2 packet delinator error counter */ -+ tmp &= ~0x40; -+ write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, -+ tmp); -+ -+ state->BERScale = 2; -+ state->LastBERNumerator = 0; -+ state->LastBERDenominator = 1; -+ /* force to PRE BCH Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S2 | state->BERScale); -+ } else { -+ state->BERScale = 2; -+ state->LastBERNumerator = 0; -+ state->LastBERDenominator = 1; -+ /* force to PRE RS Rate */ -+ write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, -+ BER_SRC_S | state->BERScale); -+ } -+ /*Reset the Total packet counter */ -+ write_reg(state, RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); -+ /*Reset the packet Error counter2 (and Set it to -+ infinit error count mode )*/ -+ write_reg(state, RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); -+ -+ TrackingOptimization(state); -+ } -+ return 0; -+} -+ -+static int tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, fe_status_t *status) -+{ -+ struct stv *state = fe->demodulator_priv; -+ int r; -+ -+ if (re_tune) { -+ r = set_parameters(fe); -+ if (r) -+ return r; -+ state->tune_time = jiffies; -+ } -+ if (*status & FE_HAS_LOCK) -+ return 0; -+ *delay = HZ; -+ -+ r = read_status(fe, status); -+ if (r) -+ return r; -+ return 0; -+} -+ -+ -+static int get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+static int set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u16 offs = state->nr ? 0x40 : 0; -+ -+ switch (tone) { -+ case SEC_TONE_ON: -+ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x38); -+ break; -+ case SEC_TONE_OFF: -+ return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3a); -+ break; -+ default: -+ break; -+ } -+ return -EINVAL; -+} -+ -+static int send_master_cmd(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u16 offs = state->nr ? 0x40 : 0; -+ int i; -+ -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); -+ for (i = 0; i < cmd->msg_len; i++) -+ write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); -+ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); -+ return 0; -+} -+ -+static int recv_slave_reply(struct dvb_frontend *fe, -+ struct dvb_diseqc_slave_reply *reply) -+{ -+ return 0; -+} -+ -+static int send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) -+{ -+ return 0; -+} -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->demodulator_priv; -+ -+ pr_info("sleep %d\n", state->nr); -+ Stop(state); -+ return 0; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct stv *state = fe->demodulator_priv; -+ s32 SNR; -+ -+ *snr = 0; -+ if (GetSignalToNoise(state, &SNR)) -+ return -EIO; -+ *snr = SNR; -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u32 n, d; -+ -+ GetBitErrorRate(state, &n, &d); -+ if (d) -+ *ber = n / d; -+ else -+ *ber = 0; -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ struct stv *state = fe->demodulator_priv; -+ u8 Agc1, Agc0; -+ -+ read_reg(state, RSTV0910_P2_AGCIQIN1 + state->regoff, &Agc1); -+ read_reg(state, RSTV0910_P2_AGCIQIN0 + state->regoff, &Agc0); -+ -+ *strength = ((255 - Agc1) * 3300) / 256; -+ return 0; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ /* struct stv *state = fe->demodulator_priv; */ -+ -+ -+ return 0; -+} -+ -+static struct dvb_frontend_ops stv0910_ops = { -+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, -+ .info = { -+ .name = "STV0910", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 0, -+ .frequency_tolerance = 0, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 70000000, -+ .caps = FE_CAN_INVERSION_AUTO | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QPSK | -+ FE_CAN_2G_MODULATION -+ }, -+ .init = init, -+ .sleep = sleep, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ .get_frontend_algo = get_algo, -+ .tune = tune, -+ .read_status = read_status, -+ .set_tone = set_tone, -+ -+ .diseqc_send_master_cmd = send_master_cmd, -+ .diseqc_send_burst = send_burst, -+ .diseqc_recv_slave_reply = recv_slave_reply, -+ -+ .read_snr = read_snr, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_ucblocks = read_ucblocks, -+}; -+ -+static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) -+{ -+ struct stv_base *p; -+ -+ list_for_each_entry(p, &stvlist, stvlist) -+ if (p->i2c == i2c && p->adr == adr) -+ return p; -+ return NULL; -+} -+ -+struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, -+ int nr) -+{ -+ struct stv *state; -+ struct stv_base *base; -+ -+ state = kzalloc(sizeof(struct stv), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); -+ state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); -+ state->tsspeed = 0x40; -+ state->nr = nr; -+ state->regoff = state->nr ? 0 : 0x200; -+ state->SearchRange = 16000000; -+ state->DEMOD = 0x10; /* Inversion : Auto with reset to 0 */ -+ state->ReceiveMode = Mode_None; -+ -+ base = match_base(i2c, cfg->adr); -+ if (base) { -+ base->count++; -+ state->base = base; -+ } else { -+ base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); -+ if (!base) -+ goto fail; -+ base->i2c = i2c; -+ base->adr = cfg->adr; -+ base->count = 1; -+ base->extclk = cfg->clk ? cfg->clk : 30000000; -+ -+ mutex_init(&base->i2c_lock); -+ mutex_init(&base->reg_lock); -+ state->base = base; -+ if (probe(state) < 0) { -+ kfree(base); -+ goto fail; -+ } -+ list_add(&base->stvlist, &stvlist); -+ } -+ state->fe.ops = stv0910_ops; -+ state->fe.demodulator_priv = state; -+ state->nr = nr; -+ -+ return &state->fe; -+ -+fail: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(stv0910_attach); -+ -+MODULE_DESCRIPTION("STV0910 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h -new file mode 100644 -index 0000000..a6fad29 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910.h -@@ -0,0 +1,31 @@ -+#ifndef _STV0910_H_ -+#define _STV0910_H_ -+ -+#include -+#include -+ -+struct stv0910_cfg { -+ u32 clk; -+ u8 adr; -+ u8 parallel; -+ u8 rptlvl; -+}; -+ -+#if defined(CONFIG_DVB_STV0910) || \ -+ (defined(CONFIG_DVB_STV0910_MODULE) && defined(MODULE)) -+ -+extern struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, int nr); -+#else -+ -+static inline struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, -+ struct stv0910_cfg *cfg, -+ int nr) -+{ -+ pr_warn("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+#endif -+ -+#endif -diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h -new file mode 100644 -index 0000000..305f5da ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0910_regs.h -@@ -0,0 +1,3998 @@ -+// @DVB-S/DVB-S2 STMicroelectronics STV0900 register defintions -+// Author Manfred Völkel, August 2013 -+// (c) 2013 Digital Devices GmbH Germany. All rights reserved -+ -+// $Id: DD_STV0910Register.h 504 2013-09-02 23:02:14Z manfred $ -+ -+/* ======================================================================= -+-- Registers Declaration (Internal ST, All Applications ) -+-- ------------------------- -+-- Each register (RSTV0910__XXXXX) is defined by its address (2 bytes). -+-- -+-- Each field (FSTV0910__XXXXX)is defined as follow: -+-- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] -+ ======================================================================= */ -+ -+/*MID*/ -+#define RSTV0910_MID 0xf100 -+#define FSTV0910_MCHIP_IDENT 0xf10000f0 -+#define FSTV0910_MRELEASE 0xf100000f -+ -+/*DID*/ -+#define RSTV0910_DID 0xf101 -+#define FSTV0910_DEVICE_ID 0xf10100ff -+ -+/*DACR1*/ -+#define RSTV0910_DACR1 0xf113 -+#define FSTV0910_DAC_MODE 0xf11300e0 -+#define FSTV0910_DAC_VALUE1 0xf113000f -+ -+/*DACR2*/ -+#define RSTV0910_DACR2 0xf114 -+#define FSTV0910_DAC_VALUE0 0xf11400ff -+ -+/*PADCFG*/ -+#define RSTV0910_PADCFG 0xf11a -+#define FSTV0910_AGCRF2_OPD 0xf11a0008 -+#define FSTV0910_AGCRF2_XOR 0xf11a0004 -+#define FSTV0910_AGCRF1_OPD 0xf11a0002 -+#define FSTV0910_AGCRF1_XOR 0xf11a0001 -+ -+/*OUTCFG2*/ -+#define RSTV0910_OUTCFG2 0xf11b -+#define FSTV0910_TS2_ERROR_XOR 0xf11b0080 -+#define FSTV0910_TS2_DPN_XOR 0xf11b0040 -+#define FSTV0910_TS2_STROUT_XOR 0xf11b0020 -+#define FSTV0910_TS2_CLOCKOUT_XOR 0xf11b0010 -+#define FSTV0910_TS1_ERROR_XOR 0xf11b0008 -+#define FSTV0910_TS1_DPN_XOR 0xf11b0004 -+#define FSTV0910_TS1_STROUT_XOR 0xf11b0002 -+#define FSTV0910_TS1_CLOCKOUT_XOR 0xf11b0001 -+ -+/*OUTCFG*/ -+#define RSTV0910_OUTCFG 0xf11c -+#define FSTV0910_INV_DATA6 0xf11c0080 -+#define FSTV0910_TS2_OUTSER_HZ 0xf11c0020 -+#define FSTV0910_TS1_OUTSER_HZ 0xf11c0010 -+#define FSTV0910_TS2_OUTPAR_HZ 0xf11c0008 -+#define FSTV0910_TS1_OUTPAR_HZ 0xf11c0004 -+#define FSTV0910_TS_SERDATA0 0xf11c0002 -+ -+/*IRQSTATUS3*/ -+#define RSTV0910_IRQSTATUS3 0xf120 -+#define FSTV0910_SPLL_LOCK 0xf1200020 -+#define FSTV0910_SSTREAM_LCK_1 0xf1200010 -+#define FSTV0910_SSTREAM_LCK_2 0xf1200008 -+#define FSTV0910_SDVBS1_PRF_2 0xf1200002 -+#define FSTV0910_SDVBS1_PRF_1 0xf1200001 -+ -+/*IRQSTATUS2*/ -+#define RSTV0910_IRQSTATUS2 0xf121 -+#define FSTV0910_SSPY_ENDSIM_1 0xf1210080 -+#define FSTV0910_SSPY_ENDSIM_2 0xf1210040 -+#define FSTV0910_SPKTDEL_ERROR_2 0xf1210010 -+#define FSTV0910_SPKTDEL_LOCKB_2 0xf1210008 -+#define FSTV0910_SPKTDEL_LOCK_2 0xf1210004 -+#define FSTV0910_SPKTDEL_ERROR_1 0xf1210002 -+#define FSTV0910_SPKTDEL_LOCKB_1 0xf1210001 -+ -+/*IRQSTATUS1*/ -+#define RSTV0910_IRQSTATUS1 0xf122 -+#define FSTV0910_SPKTDEL_LOCK_1 0xf1220080 -+#define FSTV0910_SFEC_LOCKB_2 0xf1220040 -+#define FSTV0910_SFEC_LOCK_2 0xf1220020 -+#define FSTV0910_SFEC_LOCKB_1 0xf1220010 -+#define FSTV0910_SFEC_LOCK_1 0xf1220008 -+#define FSTV0910_SDEMOD_LOCKB_2 0xf1220004 -+#define FSTV0910_SDEMOD_LOCK_2 0xf1220002 -+#define FSTV0910_SDEMOD_IRQ_2 0xf1220001 -+ -+/*IRQSTATUS0*/ -+#define RSTV0910_IRQSTATUS0 0xf123 -+#define FSTV0910_SDEMOD_LOCKB_1 0xf1230080 -+#define FSTV0910_SDEMOD_LOCK_1 0xf1230040 -+#define FSTV0910_SDEMOD_IRQ_1 0xf1230020 -+#define FSTV0910_SBCH_ERRFLAG 0xf1230010 -+#define FSTV0910_SECW2_IRQ 0xf1230008 -+#define FSTV0910_SDISEQC2_IRQ 0xf1230004 -+#define FSTV0910_SECW1_IRQ 0xf1230002 -+#define FSTV0910_SDISEQC1_IRQ 0xf1230001 -+ -+/*IRQMASK3*/ -+#define RSTV0910_IRQMASK3 0xf124 -+#define FSTV0910_MPLL_LOCK 0xf1240020 -+#define FSTV0910_MSTREAM_LCK_1 0xf1240010 -+#define FSTV0910_MSTREAM_LCK_2 0xf1240008 -+#define FSTV0910_MDVBS1_PRF_2 0xf1240002 -+#define FSTV0910_MDVBS1_PRF_1 0xf1240001 -+ -+/*IRQMASK2*/ -+#define RSTV0910_IRQMASK2 0xf125 -+#define FSTV0910_MSPY_ENDSIM_1 0xf1250080 -+#define FSTV0910_MSPY_ENDSIM_2 0xf1250040 -+#define FSTV0910_MPKTDEL_ERROR_2 0xf1250010 -+#define FSTV0910_MPKTDEL_LOCKB_2 0xf1250008 -+#define FSTV0910_MPKTDEL_LOCK_2 0xf1250004 -+#define FSTV0910_MPKTDEL_ERROR_1 0xf1250002 -+#define FSTV0910_MPKTDEL_LOCKB_1 0xf1250001 -+ -+/*IRQMASK1*/ -+#define RSTV0910_IRQMASK1 0xf126 -+#define FSTV0910_MPKTDEL_LOCK_1 0xf1260080 -+#define FSTV0910_MFEC_LOCKB_2 0xf1260040 -+#define FSTV0910_MFEC_LOCK_2 0xf1260020 -+#define FSTV0910_MFEC_LOCKB_1 0xf1260010 -+#define FSTV0910_MFEC_LOCK_1 0xf1260008 -+#define FSTV0910_MDEMOD_LOCKB_2 0xf1260004 -+#define FSTV0910_MDEMOD_LOCK_2 0xf1260002 -+#define FSTV0910_MDEMOD_IRQ_2 0xf1260001 -+ -+/*IRQMASK0*/ -+#define RSTV0910_IRQMASK0 0xf127 -+#define FSTV0910_MDEMOD_LOCKB_1 0xf1270080 -+#define FSTV0910_MDEMOD_LOCK_1 0xf1270040 -+#define FSTV0910_MDEMOD_IRQ_1 0xf1270020 -+#define FSTV0910_MBCH_ERRFLAG 0xf1270010 -+#define FSTV0910_MECW2_IRQ 0xf1270008 -+#define FSTV0910_MDISEQC2_IRQ 0xf1270004 -+#define FSTV0910_MECW1_IRQ 0xf1270002 -+#define FSTV0910_MDISEQC1_IRQ 0xf1270001 -+ -+/*I2CCFG*/ -+#define RSTV0910_I2CCFG 0xf129 -+#define FSTV0910_I2C2_FASTMODE 0xf1290080 -+#define FSTV0910_STATUS_WR2 0xf1290040 -+#define FSTV0910_I2C2ADDR_INC 0xf1290030 -+#define FSTV0910_I2C_FASTMODE 0xf1290008 -+#define FSTV0910_STATUS_WR 0xf1290004 -+#define FSTV0910_I2CADDR_INC 0xf1290003 -+ -+/*P1_I2CRPT*/ -+#define RSTV0910_P1_I2CRPT 0xf12a -+#define FSTV0910_P1_I2CT_ON 0xf12a0080 -+#define FSTV0910_P1_ENARPT_LEVEL 0xf12a0070 -+#define FSTV0910_P1_SCLT_DELAY 0xf12a0008 -+#define FSTV0910_P1_STOP_ENABLE 0xf12a0004 -+#define FSTV0910_P1_STOP_SDAT2SDA 0xf12a0002 -+ -+/*P2_I2CRPT*/ -+#define RSTV0910_P2_I2CRPT 0xf12b -+#define FSTV0910_P2_I2CT_ON 0xf12b0080 -+#define FSTV0910_P2_ENARPT_LEVEL 0xf12b0070 -+#define FSTV0910_P2_SCLT_DELAY 0xf12b0008 -+#define FSTV0910_P2_STOP_ENABLE 0xf12b0004 -+#define FSTV0910_P2_STOP_SDAT2SDA 0xf12b0002 -+ -+/*GPIO0CFG*/ -+#define RSTV0910_GPIO0CFG 0xf140 -+#define FSTV0910_GPIO0_OPD 0xf1400080 -+#define FSTV0910_GPIO0_CONFIG 0xf140007e -+#define FSTV0910_GPIO0_XOR 0xf1400001 -+ -+/*GPIO1CFG*/ -+#define RSTV0910_GPIO1CFG 0xf141 -+#define FSTV0910_GPIO1_OPD 0xf1410080 -+#define FSTV0910_GPIO1_CONFIG 0xf141007e -+#define FSTV0910_GPIO1_XOR 0xf1410001 -+ -+/*GPIO2CFG*/ -+#define RSTV0910_GPIO2CFG 0xf142 -+#define FSTV0910_GPIO2_OPD 0xf1420080 -+#define FSTV0910_GPIO2_CONFIG 0xf142007e -+#define FSTV0910_GPIO2_XOR 0xf1420001 -+ -+/*GPIO3CFG*/ -+#define RSTV0910_GPIO3CFG 0xf143 -+#define FSTV0910_GPIO3_OPD 0xf1430080 -+#define FSTV0910_GPIO3_CONFIG 0xf143007e -+#define FSTV0910_GPIO3_XOR 0xf1430001 -+ -+/*GPIO4CFG*/ -+#define RSTV0910_GPIO4CFG 0xf144 -+#define FSTV0910_GPIO4_OPD 0xf1440080 -+#define FSTV0910_GPIO4_CONFIG 0xf144007e -+#define FSTV0910_GPIO4_XOR 0xf1440001 -+ -+/*GPIO5CFG*/ -+#define RSTV0910_GPIO5CFG 0xf145 -+#define FSTV0910_GPIO5_OPD 0xf1450080 -+#define FSTV0910_GPIO5_CONFIG 0xf145007e -+#define FSTV0910_GPIO5_XOR 0xf1450001 -+ -+/*GPIO6CFG*/ -+#define RSTV0910_GPIO6CFG 0xf146 -+#define FSTV0910_GPIO6_OPD 0xf1460080 -+#define FSTV0910_GPIO6_CONFIG 0xf146007e -+#define FSTV0910_GPIO6_XOR 0xf1460001 -+ -+/*GPIO7CFG*/ -+#define RSTV0910_GPIO7CFG 0xf147 -+#define FSTV0910_GPIO7_OPD 0xf1470080 -+#define FSTV0910_GPIO7_CONFIG 0xf147007e -+#define FSTV0910_GPIO7_XOR 0xf1470001 -+ -+/*GPIO8CFG*/ -+#define RSTV0910_GPIO8CFG 0xf148 -+#define FSTV0910_GPIO8_OPD 0xf1480080 -+#define FSTV0910_GPIO8_CONFIG 0xf148007e -+#define FSTV0910_GPIO8_XOR 0xf1480001 -+ -+/*GPIO9CFG*/ -+#define RSTV0910_GPIO9CFG 0xf149 -+#define FSTV0910_GPIO9_OPD 0xf1490080 -+#define FSTV0910_GPIO9_CONFIG 0xf149007e -+#define FSTV0910_GPIO9_XOR 0xf1490001 -+ -+/*GPIO10CFG*/ -+#define RSTV0910_GPIO10CFG 0xf14a -+#define FSTV0910_GPIO10_OPD 0xf14a0080 -+#define FSTV0910_GPIO10_CONFIG 0xf14a007e -+#define FSTV0910_GPIO10_XOR 0xf14a0001 -+ -+/*GPIO11CFG*/ -+#define RSTV0910_GPIO11CFG 0xf14b -+#define FSTV0910_GPIO11_OPD 0xf14b0080 -+#define FSTV0910_GPIO11_CONFIG 0xf14b007e -+#define FSTV0910_GPIO11_XOR 0xf14b0001 -+ -+/*GPIO12CFG*/ -+#define RSTV0910_GPIO12CFG 0xf14c -+#define FSTV0910_GPIO12_OPD 0xf14c0080 -+#define FSTV0910_GPIO12_CONFIG 0xf14c007e -+#define FSTV0910_GPIO12_XOR 0xf14c0001 -+ -+/*GPIO13CFG*/ -+#define RSTV0910_GPIO13CFG 0xf14d -+#define FSTV0910_GPIO13_OPD 0xf14d0080 -+#define FSTV0910_GPIO13_CONFIG 0xf14d007e -+#define FSTV0910_GPIO13_XOR 0xf14d0001 -+ -+/*GPIO14CFG*/ -+#define RSTV0910_GPIO14CFG 0xf14e -+#define FSTV0910_GPIO14_OPD 0xf14e0080 -+#define FSTV0910_GPIO14_CONFIG 0xf14e007e -+#define FSTV0910_GPIO14_XOR 0xf14e0001 -+ -+/*GPIO15CFG*/ -+#define RSTV0910_GPIO15CFG 0xf14f -+#define FSTV0910_GPIO15_OPD 0xf14f0080 -+#define FSTV0910_GPIO15_CONFIG 0xf14f007e -+#define FSTV0910_GPIO15_XOR 0xf14f0001 -+ -+/*GPIO16CFG*/ -+#define RSTV0910_GPIO16CFG 0xf150 -+#define FSTV0910_GPIO16_OPD 0xf1500080 -+#define FSTV0910_GPIO16_CONFIG 0xf150007e -+#define FSTV0910_GPIO16_XOR 0xf1500001 -+ -+/*GPIO17CFG*/ -+#define RSTV0910_GPIO17CFG 0xf151 -+#define FSTV0910_GPIO17_OPD 0xf1510080 -+#define FSTV0910_GPIO17_CONFIG 0xf151007e -+#define FSTV0910_GPIO17_XOR 0xf1510001 -+ -+/*GPIO18CFG*/ -+#define RSTV0910_GPIO18CFG 0xf152 -+#define FSTV0910_GPIO18_OPD 0xf1520080 -+#define FSTV0910_GPIO18_CONFIG 0xf152007e -+#define FSTV0910_GPIO18_XOR 0xf1520001 -+ -+/*GPIO19CFG*/ -+#define RSTV0910_GPIO19CFG 0xf153 -+#define FSTV0910_GPIO19_OPD 0xf1530080 -+#define FSTV0910_GPIO19_CONFIG 0xf153007e -+#define FSTV0910_GPIO19_XOR 0xf1530001 -+ -+/*GPIO20CFG*/ -+#define RSTV0910_GPIO20CFG 0xf154 -+#define FSTV0910_GPIO20_OPD 0xf1540080 -+#define FSTV0910_GPIO20_CONFIG 0xf154007e -+#define FSTV0910_GPIO20_XOR 0xf1540001 -+ -+/*GPIO21CFG*/ -+#define RSTV0910_GPIO21CFG 0xf155 -+#define FSTV0910_GPIO21_OPD 0xf1550080 -+#define FSTV0910_GPIO21_CONFIG 0xf155007e -+#define FSTV0910_GPIO21_XOR 0xf1550001 -+ -+/*GPIO22CFG*/ -+#define RSTV0910_GPIO22CFG 0xf156 -+#define FSTV0910_GPIO22_OPD 0xf1560080 -+#define FSTV0910_GPIO22_CONFIG 0xf156007e -+#define FSTV0910_GPIO22_XOR 0xf1560001 -+ -+/*STRSTATUS1*/ -+#define RSTV0910_STRSTATUS1 0xf16a -+#define FSTV0910_STRSTATUS_SEL2 0xf16a00f0 -+#define FSTV0910_STRSTATUS_SEL1 0xf16a000f -+ -+/*STRSTATUS2*/ -+#define RSTV0910_STRSTATUS2 0xf16b -+#define FSTV0910_STRSTATUS_SEL4 0xf16b00f0 -+#define FSTV0910_STRSTATUS_SEL3 0xf16b000f -+ -+/*STRSTATUS3*/ -+#define RSTV0910_STRSTATUS3 0xf16c -+#define FSTV0910_STRSTATUS_SEL6 0xf16c00f0 -+#define FSTV0910_STRSTATUS_SEL5 0xf16c000f -+ -+/*FSKTFC2*/ -+#define RSTV0910_FSKTFC2 0xf170 -+#define FSTV0910_FSKT_KMOD 0xf17000fc -+#define FSTV0910_FSKT_CAR2 0xf1700003 -+ -+/*FSKTFC1*/ -+#define RSTV0910_FSKTFC1 0xf171 -+#define FSTV0910_FSKT_CAR1 0xf17100ff -+ -+/*FSKTFC0*/ -+#define RSTV0910_FSKTFC0 0xf172 -+#define FSTV0910_FSKT_CAR0 0xf17200ff -+ -+/*FSKTDELTAF1*/ -+#define RSTV0910_FSKTDELTAF1 0xf173 -+#define FSTV0910_FSKT_DELTAF1 0xf173000f -+ -+/*FSKTDELTAF0*/ -+#define RSTV0910_FSKTDELTAF0 0xf174 -+#define FSTV0910_FSKT_DELTAF0 0xf17400ff -+ -+/*FSKTCTRL*/ -+#define RSTV0910_FSKTCTRL 0xf175 -+#define FSTV0910_FSKT_PINSEL 0xf1750080 -+#define FSTV0910_FSKT_EN_SGN 0xf1750040 -+#define FSTV0910_FSKT_MOD_SGN 0xf1750020 -+#define FSTV0910_FSKT_MOD_EN 0xf175001c -+#define FSTV0910_FSKT_DACMODE 0xf1750003 -+ -+/*FSKRFC2*/ -+#define RSTV0910_FSKRFC2 0xf176 -+#define FSTV0910_FSKR_DETSGN 0xf1760040 -+#define FSTV0910_FSKR_OUTSGN 0xf1760020 -+#define FSTV0910_FSKR_KAGC 0xf176001c -+#define FSTV0910_FSKR_CAR2 0xf1760003 -+ -+/*FSKRFC1*/ -+#define RSTV0910_FSKRFC1 0xf177 -+#define FSTV0910_FSKR_CAR1 0xf17700ff -+ -+/*FSKRFC0*/ -+#define RSTV0910_FSKRFC0 0xf178 -+#define FSTV0910_FSKR_CAR0 0xf17800ff -+ -+/*FSKRK1*/ -+#define RSTV0910_FSKRK1 0xf179 -+#define FSTV0910_FSKR_K1_EXP 0xf17900e0 -+#define FSTV0910_FSKR_K1_MANT 0xf179001f -+ -+/*FSKRK2*/ -+#define RSTV0910_FSKRK2 0xf17a -+#define FSTV0910_FSKR_K2_EXP 0xf17a00e0 -+#define FSTV0910_FSKR_K2_MANT 0xf17a001f -+ -+/*FSKRAGCR*/ -+#define RSTV0910_FSKRAGCR 0xf17b -+#define FSTV0910_FSKR_OUTCTL 0xf17b00c0 -+#define FSTV0910_FSKR_AGC_REF 0xf17b003f -+ -+/*FSKRAGC*/ -+#define RSTV0910_FSKRAGC 0xf17c -+#define FSTV0910_FSKR_AGC_ACCU 0xf17c00ff -+ -+/*FSKRALPHA*/ -+#define RSTV0910_FSKRALPHA 0xf17d -+#define FSTV0910_FSKR_ALPHA_EXP 0xf17d001c -+#define FSTV0910_FSKR_ALPHA_M 0xf17d0003 -+ -+/*FSKRPLTH1*/ -+#define RSTV0910_FSKRPLTH1 0xf17e -+#define FSTV0910_FSKR_BETA 0xf17e00f0 -+#define FSTV0910_FSKR_PLL_TRESH1 0xf17e000f -+ -+/*FSKRPLTH0*/ -+#define RSTV0910_FSKRPLTH0 0xf17f -+#define FSTV0910_FSKR_PLL_TRESH0 0xf17f00ff -+ -+/*FSKRDF1*/ -+#define RSTV0910_FSKRDF1 0xf180 -+#define FSTV0910_FSKR_OUT 0xf1800080 -+#define FSTV0910_FSKR_STATE 0xf1800060 -+#define FSTV0910_FSKR_DELTAF1 0xf180001f -+ -+/*FSKRDF0*/ -+#define RSTV0910_FSKRDF0 0xf181 -+#define FSTV0910_FSKR_DELTAF0 0xf18100ff -+ -+/*FSKRSTEPP*/ -+#define RSTV0910_FSKRSTEPP 0xf182 -+#define FSTV0910_FSKR_STEP_PLUS 0xf18200ff -+ -+/*FSKRSTEPM*/ -+#define RSTV0910_FSKRSTEPM 0xf183 -+#define FSTV0910_FSKR_STEP_MINUS 0xf18300ff -+ -+/*FSKRDET1*/ -+#define RSTV0910_FSKRDET1 0xf184 -+#define FSTV0910_FSKR_DETECT 0xf1840080 -+#define FSTV0910_FSKR_CARDET_ACCU1 0xf184000f -+ -+/*FSKRDET0*/ -+#define RSTV0910_FSKRDET0 0xf185 -+#define FSTV0910_FSKR_CARDET_ACCU0 0xf18500ff -+ -+/*FSKRDTH1*/ -+#define RSTV0910_FSKRDTH1 0xf186 -+#define FSTV0910_FSKR_CARLOSS_THRESH1 0xf18600f0 -+#define FSTV0910_FSKR_CARDET_THRESH1 0xf186000f -+ -+/*FSKRDTH0*/ -+#define RSTV0910_FSKRDTH0 0xf187 -+#define FSTV0910_FSKR_CARDET_THRESH0 0xf18700ff -+ -+/*FSKRLOSS*/ -+#define RSTV0910_FSKRLOSS 0xf188 -+#define FSTV0910_FSKR_CARLOSS_THRESH0 0xf18800ff -+ -+/*NCOARSE*/ -+#define RSTV0910_NCOARSE 0xf1b3 -+#define FSTV0910_CP 0xf1b300f8 -+#define FSTV0910_IDF 0xf1b30007 -+ -+/*NCOARSE1*/ -+#define RSTV0910_NCOARSE1 0xf1b4 -+#define FSTV0910_N_DIV 0xf1b400ff -+ -+/*NCOARSE2*/ -+#define RSTV0910_NCOARSE2 0xf1b5 -+#define FSTV0910_ODF 0xf1b5003f -+ -+/*SYNTCTRL*/ -+#define RSTV0910_SYNTCTRL 0xf1b6 -+#define FSTV0910_STANDBY 0xf1b60080 -+#define FSTV0910_BYPASSPLLCORE 0xf1b60040 -+#define FSTV0910_STOP_PLL 0xf1b60008 -+#define FSTV0910_OSCI_E 0xf1b60002 -+ -+/*FILTCTRL*/ -+#define RSTV0910_FILTCTRL 0xf1b7 -+#define FSTV0910_INV_CLKFSK 0xf1b70002 -+#define FSTV0910_BYPASS_APPLI 0xf1b70001 -+ -+/*PLLSTAT*/ -+#define RSTV0910_PLLSTAT 0xf1b8 -+#define FSTV0910_PLL_BIST_END 0xf1b80004 -+#define FSTV0910_PLLLOCK 0xf1b80001 -+ -+/*STOPCLK1*/ -+#define RSTV0910_STOPCLK1 0xf1c2 -+#define FSTV0910_INV_CLKADCI2 0xf1c20004 -+#define FSTV0910_INV_CLKADCI1 0xf1c20001 -+ -+/*STOPCLK2*/ -+#define RSTV0910_STOPCLK2 0xf1c3 -+#define FSTV0910_STOP_DVBS2FEC2 0xf1c30020 -+#define FSTV0910_STOP_DVBS2FEC 0xf1c30010 -+#define FSTV0910_STOP_DVBS1FEC2 0xf1c30008 -+#define FSTV0910_STOP_DVBS1FEC 0xf1c30004 -+#define FSTV0910_STOP_DEMOD2 0xf1c30002 -+#define FSTV0910_STOP_DEMOD 0xf1c30001 -+ -+/*PREGCTL*/ -+#define RSTV0910_PREGCTL 0xf1c8 -+#define FSTV0910_REG3V3TO2V5_POFF 0xf1c80080 -+ -+/*TSTTNR0*/ -+#define RSTV0910_TSTTNR0 0xf1df -+#define FSTV0910_FSK_PON 0xf1df0004 -+#define FSTV0910_FSK_OPENLOOP 0xf1df0002 -+ -+/*TSTTNR1*/ -+#define RSTV0910_TSTTNR1 0xf1e0 -+#define FSTV0910_BYPASS_ADC1 0xf1e00080 -+#define FSTV0910_INVADC1_CKOUT 0xf1e00040 -+#define FSTV0910_SELIQSRC1 0xf1e00030 -+#define FSTV0910_DEMOD2_SELADC 0xf1e00008 -+#define FSTV0910_DEMOD1_SELADC 0xf1e00004 -+#define FSTV0910_ADC1_PON 0xf1e00002 -+ -+/*TSTTNR2*/ -+#define RSTV0910_TSTTNR2 0xf1e1 -+#define FSTV0910_I2C_DISEQC_BYPASS 0xf1e10080 -+#define FSTV0910_I2C_DISEQC_ENCH 0xf1e10040 -+#define FSTV0910_I2C_DISEQC_PON 0xf1e10020 -+#define FSTV0910_DISEQC_CLKDIV 0xf1e1000f -+ -+/*TSTTNR3*/ -+#define RSTV0910_TSTTNR3 0xf1e2 -+#define FSTV0910_BYPASS_ADC2 0xf1e20080 -+#define FSTV0910_INVADC2_CKOUT 0xf1e20040 -+#define FSTV0910_SELIQSRC2 0xf1e20030 -+#define FSTV0910_ADC2_PON 0xf1e20002 -+ -+/*P2_IQCONST*/ -+#define RSTV0910_P2_IQCONST 0xf200 -+#define FSTV0910_P2_CONSTEL_SELECT 0xf2000060 -+#define FSTV0910_P2_IQSYMB_SEL 0xf200001f -+ -+/*P2_NOSCFG*/ -+#define RSTV0910_P2_NOSCFG 0xf201 -+#define FSTV0910_P2_DIS_ACMRATIO 0xf2010080 -+#define FSTV0910_P2_NOSIN_EGALSEL 0xf2010040 -+#define FSTV0910_P2_DUMMYPL_NOSDATA 0xf2010020 -+#define FSTV0910_P2_NOSPLH_BETA 0xf2010018 -+#define FSTV0910_P2_NOSDATA_BETA 0xf2010007 -+ -+/*P2_ISYMB*/ -+#define RSTV0910_P2_ISYMB 0xf202 -+#define FSTV0910_P2_I_SYMBOL 0xf20201ff -+ -+/*P2_QSYMB*/ -+#define RSTV0910_P2_QSYMB 0xf203 -+#define FSTV0910_P2_Q_SYMBOL 0xf20301ff -+ -+/*P2_AGC1CFG*/ -+#define RSTV0910_P2_AGC1CFG 0xf204 -+#define FSTV0910_P2_DC_FROZEN 0xf2040080 -+#define FSTV0910_P2_DC_CORRECT 0xf2040040 -+#define FSTV0910_P2_AMM_FROZEN 0xf2040020 -+#define FSTV0910_P2_AMM_CORRECT 0xf2040010 -+#define FSTV0910_P2_QUAD_FROZEN 0xf2040008 -+#define FSTV0910_P2_QUAD_CORRECT 0xf2040004 -+#define FSTV0910_P2_DCCOMP_SLOW 0xf2040002 -+#define FSTV0910_P2_IQMISM_SLOW 0xf2040001 -+ -+/*P2_AGC1CN*/ -+#define RSTV0910_P2_AGC1CN 0xf206 -+#define FSTV0910_P2_AGC1_LOCKED 0xf2060080 -+#define FSTV0910_P2_AGC1_OVERFLOW 0xf2060040 -+#define FSTV0910_P2_AGC1_NOSLOWLK 0xf2060020 -+#define FSTV0910_P2_AGC1_MINPOWER 0xf2060010 -+#define FSTV0910_P2_AGCOUT_FAST 0xf2060008 -+#define FSTV0910_P2_AGCIQ_BETA 0xf2060007 -+ -+/*P2_AGC1REF*/ -+#define RSTV0910_P2_AGC1REF 0xf207 -+#define FSTV0910_P2_AGCIQ_REF 0xf20700ff -+ -+/*P2_IDCCOMP*/ -+#define RSTV0910_P2_IDCCOMP 0xf208 -+#define FSTV0910_P2_IAVERAGE_ADJ 0xf20801ff -+ -+/*P2_QDCCOMP*/ -+#define RSTV0910_P2_QDCCOMP 0xf209 -+#define FSTV0910_P2_QAVERAGE_ADJ 0xf20901ff -+ -+/*P2_POWERI*/ -+#define RSTV0910_P2_POWERI 0xf20a -+#define FSTV0910_P2_POWER_I 0xf20a00ff -+ -+/*P2_POWERQ*/ -+#define RSTV0910_P2_POWERQ 0xf20b -+#define FSTV0910_P2_POWER_Q 0xf20b00ff -+ -+/*P2_AGC1AMM*/ -+#define RSTV0910_P2_AGC1AMM 0xf20c -+#define FSTV0910_P2_AMM_VALUE 0xf20c00ff -+ -+/*P2_AGC1QUAD*/ -+#define RSTV0910_P2_AGC1QUAD 0xf20d -+#define FSTV0910_P2_QUAD_VALUE 0xf20d01ff -+ -+/*P2_AGCIQIN1*/ -+#define RSTV0910_P2_AGCIQIN1 0xf20e -+#define FSTV0910_P2_AGCIQ_VALUE1 0xf20e00ff -+ -+/*P2_AGCIQIN0*/ -+#define RSTV0910_P2_AGCIQIN0 0xf20f -+#define FSTV0910_P2_AGCIQ_VALUE0 0xf20f00ff -+ -+/*P2_DEMOD*/ -+#define RSTV0910_P2_DEMOD 0xf210 -+#define FSTV0910_P2_MANUALS2_ROLLOFF 0xf2100080 -+#define FSTV0910_P2_SPECINV_CONTROL 0xf2100030 -+#define FSTV0910_P2_MANUALSX_ROLLOFF 0xf2100004 -+#define FSTV0910_P2_ROLLOFF_CONTROL 0xf2100003 -+ -+/*P2_DMDMODCOD*/ -+#define RSTV0910_P2_DMDMODCOD 0xf211 -+#define FSTV0910_P2_MANUAL_MODCOD 0xf2110080 -+#define FSTV0910_P2_DEMOD_MODCOD 0xf211007c -+#define FSTV0910_P2_DEMOD_TYPE 0xf2110003 -+ -+/*P2_DSTATUS*/ -+#define RSTV0910_P2_DSTATUS 0xf212 -+#define FSTV0910_P2_CAR_LOCK 0xf2120080 -+#define FSTV0910_P2_TMGLOCK_QUALITY 0xf2120060 -+#define FSTV0910_P2_SDVBS1_ENABLE 0xf2120010 -+#define FSTV0910_P2_LOCK_DEFINITIF 0xf2120008 -+#define FSTV0910_P2_TIMING_IS_LOCKED 0xf2120004 -+#define FSTV0910_P2_DEMOD_SYSCFG 0xf2120002 -+#define FSTV0910_P2_OVADC_DETECT 0xf2120001 -+ -+/*P2_DSTATUS2*/ -+#define RSTV0910_P2_DSTATUS2 0xf213 -+#define FSTV0910_P2_DEMOD_DELOCK 0xf2130080 -+#define FSTV0910_P2_DEMOD_TIMEOUT 0xf2130040 -+#define FSTV0910_P2_MODCODRQ_SYNCTAG 0xf2130020 -+#define FSTV0910_P2_POLYPH_SATEVENT 0xf2130010 -+#define FSTV0910_P2_AGC1_NOSIGNALACK 0xf2130008 -+#define FSTV0910_P2_AGC2_OVERFLOW 0xf2130004 -+#define FSTV0910_P2_CFR_OVERFLOW 0xf2130002 -+#define FSTV0910_P2_GAMMA_OVERUNDER 0xf2130001 -+ -+/*P2_DMDCFGMD*/ -+#define RSTV0910_P2_DMDCFGMD 0xf214 -+#define FSTV0910_P2_DVBS2_ENABLE 0xf2140080 -+#define FSTV0910_P2_DVBS1_ENABLE 0xf2140040 -+#define FSTV0910_P2_SCAN_ENABLE 0xf2140010 -+#define FSTV0910_P2_CFR_AUTOSCAN 0xf2140008 -+#define FSTV0910_P2_NOFORCE_RELOCK 0xf2140004 -+#define FSTV0910_P2_TUN_RNG 0xf2140003 -+ -+/*P2_DMDCFG2*/ -+#define RSTV0910_P2_DMDCFG2 0xf215 -+#define FSTV0910_P2_AGC1_WAITLOCK 0xf2150080 -+#define FSTV0910_P2_S1S2_SEQUENTIAL 0xf2150040 -+#define FSTV0910_P2_BLINDPEA_MODE 0xf2150020 -+#define FSTV0910_P2_INFINITE_RELOCK 0xf2150010 -+#define FSTV0910_P2_BWOFFSET_COLDWARM 0xf2150008 -+#define FSTV0910_P2_TMGLOCK_NSCANSTOP 0xf2150004 -+#define FSTV0910_P2_COARSE_LK3MODE 0xf2150002 -+#define FSTV0910_P2_COARSE_LK2MODE 0xf2150001 -+ -+/*P2_DMDISTATE*/ -+#define RSTV0910_P2_DMDISTATE 0xf216 -+#define FSTV0910_P2_I2C_NORESETDMODE 0xf2160080 -+#define FSTV0910_P2_FORCE_ETAPED 0xf2160040 -+#define FSTV0910_P2_SDMDRST_DIRCLK 0xf2160020 -+#define FSTV0910_P2_I2C_DEMOD_MODE 0xf216001f -+ -+/*P2_DMDT0M*/ -+#define RSTV0910_P2_DMDT0M 0xf217 -+#define FSTV0910_P2_DMDT0_MIN 0xf21700ff -+ -+/*P2_DMDSTATE*/ -+#define RSTV0910_P2_DMDSTATE 0xf21b -+#define FSTV0910_P2_DEMOD_LOCKED 0xf21b0080 -+#define FSTV0910_P2_HEADER_MODE 0xf21b0060 -+#define FSTV0910_P2_DEMOD_MODE 0xf21b001f -+ -+/*P2_DMDFLYW*/ -+#define RSTV0910_P2_DMDFLYW 0xf21c -+#define FSTV0910_P2_I2C_IRQVAL 0xf21c00f0 -+#define FSTV0910_P2_FLYWHEEL_CPT 0xf21c000f -+ -+/*P2_DSTATUS3*/ -+#define RSTV0910_P2_DSTATUS3 0xf21d -+#define FSTV0910_P2_CFR_ZIGZAG 0xf21d0080 -+#define FSTV0910_P2_DEMOD_CFGMODE 0xf21d0060 -+#define FSTV0910_P2_GAMMA_LOWBAUDRATE 0xf21d0010 -+#define FSTV0910_P2_RELOCK_MODE 0xf21d0008 -+#define FSTV0910_P2_DEMOD_FAIL 0xf21d0004 -+#define FSTV0910_P2_ETAPE1A_DVBXMEM 0xf21d0003 -+ -+/*P2_DMDCFG3*/ -+#define RSTV0910_P2_DMDCFG3 0xf21e -+#define FSTV0910_P2_DVBS1_TMGWAIT 0xf21e0080 -+#define FSTV0910_P2_NO_BWCENTERING 0xf21e0040 -+#define FSTV0910_P2_INV_SEQSRCH 0xf21e0020 -+#define FSTV0910_P2_DIS_SFRUPLOW_TRK 0xf21e0010 -+#define FSTV0910_P2_NOSTOP_FIFOFULL 0xf21e0008 -+#define FSTV0910_P2_LOCKTIME_MODE 0xf21e0007 -+ -+/*P2_DMDCFG4*/ -+#define RSTV0910_P2_DMDCFG4 0xf21f -+#define FSTV0910_P2_DIS_VITLOCK 0xf21f0080 -+#define FSTV0910_P2_S1S2TOUT_FAST 0xf21f0040 -+#define FSTV0910_P2_DEMOD_FASTLOCK 0xf21f0020 -+#define FSTV0910_P2_S1HIER_ENABLE 0xf21f0010 -+#define FSTV0910_P2_TUNER_NRELAUNCH 0xf21f0008 -+#define FSTV0910_P2_DIS_CLKENABLE 0xf21f0004 -+#define FSTV0910_P2_DIS_HDRDIVLOCK 0xf21f0002 -+#define FSTV0910_P2_NO_TNRWBINIT 0xf21f0001 -+ -+/*P2_CORRELMANT*/ -+#define RSTV0910_P2_CORRELMANT 0xf220 -+#define FSTV0910_P2_CORREL_MANT 0xf22000ff -+ -+/*P2_CORRELABS*/ -+#define RSTV0910_P2_CORRELABS 0xf221 -+#define FSTV0910_P2_CORREL_ABS 0xf22100ff -+ -+/*P2_CORRELEXP*/ -+#define RSTV0910_P2_CORRELEXP 0xf222 -+#define FSTV0910_P2_CORREL_ABSEXP 0xf22200f0 -+#define FSTV0910_P2_CORREL_EXP 0xf222000f -+ -+/*P2_PLHMODCOD*/ -+#define RSTV0910_P2_PLHMODCOD 0xf224 -+#define FSTV0910_P2_SPECINV_DEMOD 0xf2240080 -+#define FSTV0910_P2_PLH_MODCOD 0xf224007c -+#define FSTV0910_P2_PLH_TYPE 0xf2240003 -+ -+/*P2_DMDREG*/ -+#define RSTV0910_P2_DMDREG 0xf225 -+#define FSTV0910_P2_EXTPSK_MODE 0xf2250080 -+#define FSTV0910_P2_HIER_SHORTFRAME 0xf2250002 -+#define FSTV0910_P2_DECIM_PLFRAMES 0xf2250001 -+ -+/*P2_AGC2O*/ -+#define RSTV0910_P2_AGC2O 0xf22c -+#define FSTV0910_P2_CSTENV_MODE 0xf22c00c0 -+#define FSTV0910_P2_AGC2_LKSQRT 0xf22c0020 -+#define FSTV0910_P2_AGC2_LKMODE 0xf22c0010 -+#define FSTV0910_P2_AGC2_LKEQUA 0xf22c0008 -+#define FSTV0910_P2_AGC2_COEF 0xf22c0007 -+ -+/*P2_AGC2REF*/ -+#define RSTV0910_P2_AGC2REF 0xf22d -+#define FSTV0910_P2_AGC2_REF 0xf22d00ff -+ -+/*P2_AGC1ADJ*/ -+#define RSTV0910_P2_AGC1ADJ 0xf22e -+#define FSTV0910_P2_AGC1ADJ_MANUAL 0xf22e0080 -+#define FSTV0910_P2_AGC1_ADJUSTED 0xf22e007f -+ -+/*P2_AGC2I1*/ -+#define RSTV0910_P2_AGC2I1 0xf236 -+#define FSTV0910_P2_AGC2_INTEGRATOR1 0xf23600ff -+ -+/*P2_AGC2I0*/ -+#define RSTV0910_P2_AGC2I0 0xf237 -+#define FSTV0910_P2_AGC2_INTEGRATOR0 0xf23700ff -+ -+/*P2_CARCFG*/ -+#define RSTV0910_P2_CARCFG 0xf238 -+#define FSTV0910_P2_CFRUPLOW_AUTO 0xf2380080 -+#define FSTV0910_P2_CFRUPLOW_TEST 0xf2380040 -+#define FSTV0910_P2_WIDE_FREQDET 0xf2380020 -+#define FSTV0910_P2_CARHDR_NODIV8 0xf2380010 -+#define FSTV0910_P2_I2C_ROTA 0xf2380008 -+#define FSTV0910_P2_ROTAON 0xf2380004 -+#define FSTV0910_P2_PH_DET_ALGO 0xf2380003 -+ -+/*P2_ACLC*/ -+#define RSTV0910_P2_ACLC 0xf239 -+#define FSTV0910_P2_CARS1_ANOSAUTO 0xf2390040 -+#define FSTV0910_P2_CAR_ALPHA_MANT 0xf2390030 -+#define FSTV0910_P2_CAR_ALPHA_EXP 0xf239000f -+ -+/*P2_BCLC*/ -+#define RSTV0910_P2_BCLC 0xf23a -+#define FSTV0910_P2_CARS1_BNOSAUTO 0xf23a0040 -+#define FSTV0910_P2_CAR_BETA_MANT 0xf23a0030 -+#define FSTV0910_P2_CAR_BETA_EXP 0xf23a000f -+ -+/*P2_CARFREQ*/ -+#define RSTV0910_P2_CARFREQ 0xf23d -+#define FSTV0910_P2_KC_COARSE_EXP 0xf23d00f0 -+#define FSTV0910_P2_BETA_FREQ 0xf23d000f -+ -+/*P2_CARHDR*/ -+#define RSTV0910_P2_CARHDR 0xf23e -+#define FSTV0910_P2_K_FREQ_HDR 0xf23e00ff -+ -+/*P2_LDT*/ -+#define RSTV0910_P2_LDT 0xf23f -+#define FSTV0910_P2_CARLOCK_THRES 0xf23f01ff -+ -+/*P2_LDT2*/ -+#define RSTV0910_P2_LDT2 0xf240 -+#define FSTV0910_P2_CARLOCK_THRES2 0xf24001ff -+ -+/*P2_CFRICFG*/ -+#define RSTV0910_P2_CFRICFG 0xf241 -+#define FSTV0910_P2_CFRINIT_UNVALRNG 0xf2410080 -+#define FSTV0910_P2_CFRINIT_LUNVALCPT 0xf2410040 -+#define FSTV0910_P2_CFRINIT_ABORTDBL 0xf2410020 -+#define FSTV0910_P2_CFRINIT_ABORTPRED 0xf2410010 -+#define FSTV0910_P2_CFRINIT_UNVALSKIP 0xf2410008 -+#define FSTV0910_P2_CFRINIT_CSTINC 0xf2410004 -+#define FSTV0910_P2_CFRIROLL_GARDER 0xf2410002 -+#define FSTV0910_P2_NEG_CFRSTEP 0xf2410001 -+ -+/*P2_CFRUP1*/ -+#define RSTV0910_P2_CFRUP1 0xf242 -+#define FSTV0910_P2_CFR_UP1 0xf24201ff -+ -+/*P2_CFRUP0*/ -+#define RSTV0910_P2_CFRUP0 0xf243 -+#define FSTV0910_P2_CFR_UP0 0xf24300ff -+ -+/*P2_CFRIBASE1*/ -+#define RSTV0910_P2_CFRIBASE1 0xf244 -+#define FSTV0910_P2_CFRINIT_BASE1 0xf24400ff -+ -+/*P2_CFRIBASE0*/ -+#define RSTV0910_P2_CFRIBASE0 0xf245 -+#define FSTV0910_P2_CFRINIT_BASE0 0xf24500ff -+ -+/*P2_CFRLOW1*/ -+#define RSTV0910_P2_CFRLOW1 0xf246 -+#define FSTV0910_P2_CFR_LOW1 0xf24601ff -+ -+/*P2_CFRLOW0*/ -+#define RSTV0910_P2_CFRLOW0 0xf247 -+#define FSTV0910_P2_CFR_LOW0 0xf24700ff -+ -+/*P2_CFRINIT1*/ -+#define RSTV0910_P2_CFRINIT1 0xf248 -+#define FSTV0910_P2_CFR_INIT1 0xf24801ff -+ -+/*P2_CFRINIT0*/ -+#define RSTV0910_P2_CFRINIT0 0xf249 -+#define FSTV0910_P2_CFR_INIT0 0xf24900ff -+ -+/*P2_CFRINC1*/ -+#define RSTV0910_P2_CFRINC1 0xf24a -+#define FSTV0910_P2_MANUAL_CFRINC 0xf24a0080 -+#define FSTV0910_P2_CFR_INC1 0xf24a003f -+ -+/*P2_CFRINC0*/ -+#define RSTV0910_P2_CFRINC0 0xf24b -+#define FSTV0910_P2_CFR_INC0 0xf24b00ff -+ -+/*P2_CFR2*/ -+#define RSTV0910_P2_CFR2 0xf24c -+#define FSTV0910_P2_CAR_FREQ2 0xf24c01ff -+ -+/*P2_CFR1*/ -+#define RSTV0910_P2_CFR1 0xf24d -+#define FSTV0910_P2_CAR_FREQ1 0xf24d00ff -+ -+/*P2_CFR0*/ -+#define RSTV0910_P2_CFR0 0xf24e -+#define FSTV0910_P2_CAR_FREQ0 0xf24e00ff -+ -+/*P2_LDI*/ -+#define RSTV0910_P2_LDI 0xf24f -+#define FSTV0910_P2_LOCK_DET_INTEGR 0xf24f01ff -+ -+/*P2_TMGCFG*/ -+#define RSTV0910_P2_TMGCFG 0xf250 -+#define FSTV0910_P2_TMGLOCK_BETA 0xf25000c0 -+#define FSTV0910_P2_DO_TIMING_CORR 0xf2500010 -+#define FSTV0910_P2_MANUAL_SCAN 0xf250000c -+#define FSTV0910_P2_TMG_MINFREQ 0xf2500003 -+ -+/*P2_RTC*/ -+#define RSTV0910_P2_RTC 0xf251 -+#define FSTV0910_P2_TMGALPHA_EXP 0xf25100f0 -+#define FSTV0910_P2_TMGBETA_EXP 0xf251000f -+ -+/*P2_RTCS2*/ -+#define RSTV0910_P2_RTCS2 0xf252 -+#define FSTV0910_P2_TMGALPHAS2_EXP 0xf25200f0 -+#define FSTV0910_P2_TMGBETAS2_EXP 0xf252000f -+ -+/*P2_TMGTHRISE*/ -+#define RSTV0910_P2_TMGTHRISE 0xf253 -+#define FSTV0910_P2_TMGLOCK_THRISE 0xf25300ff -+ -+/*P2_TMGTHFALL*/ -+#define RSTV0910_P2_TMGTHFALL 0xf254 -+#define FSTV0910_P2_TMGLOCK_THFALL 0xf25400ff -+ -+/*P2_SFRUPRATIO*/ -+#define RSTV0910_P2_SFRUPRATIO 0xf255 -+#define FSTV0910_P2_SFR_UPRATIO 0xf25500ff -+ -+/*P2_SFRLOWRATIO*/ -+#define RSTV0910_P2_SFRLOWRATIO 0xf256 -+#define FSTV0910_P2_SFR_LOWRATIO 0xf25600ff -+ -+/*P2_KTTMG*/ -+#define RSTV0910_P2_KTTMG 0xf257 -+#define FSTV0910_P2_KT_TMG_EXP 0xf25700f0 -+ -+/*P2_KREFTMG*/ -+#define RSTV0910_P2_KREFTMG 0xf258 -+#define FSTV0910_P2_KREF_TMG 0xf25800ff -+ -+/*P2_SFRSTEP*/ -+#define RSTV0910_P2_SFRSTEP 0xf259 -+#define FSTV0910_P2_SFR_SCANSTEP 0xf25900f0 -+#define FSTV0910_P2_SFR_CENTERSTEP 0xf259000f -+ -+/*P2_TMGCFG2*/ -+#define RSTV0910_P2_TMGCFG2 0xf25a -+#define FSTV0910_P2_KREFTMG2_DECMODE 0xf25a00c0 -+#define FSTV0910_P2_DIS_AUTOSAMP 0xf25a0008 -+#define FSTV0910_P2_SCANINIT_QUART 0xf25a0004 -+#define FSTV0910_P2_NOTMG_DVBS1DERAT 0xf25a0002 -+#define FSTV0910_P2_SFRRATIO_FINE 0xf25a0001 -+ -+/*P2_KREFTMG2*/ -+#define RSTV0910_P2_KREFTMG2 0xf25b -+#define FSTV0910_P2_KREF_TMG2 0xf25b00ff -+ -+/*P2_TMGCFG3*/ -+#define RSTV0910_P2_TMGCFG3 0xf25d -+#define FSTV0910_P2_CFRINC_MODE 0xf25d0070 -+#define FSTV0910_P2_CONT_TMGCENTER 0xf25d0008 -+#define FSTV0910_P2_AUTO_GUP 0xf25d0004 -+#define FSTV0910_P2_AUTO_GLOW 0xf25d0002 -+#define FSTV0910_P2_SFRVAL_MINMODE 0xf25d0001 -+ -+/*P2_SFRINIT1*/ -+#define RSTV0910_P2_SFRINIT1 0xf25e -+#define FSTV0910_P2_SFR_INIT1 0xf25e00ff -+ -+/*P2_SFRINIT0*/ -+#define RSTV0910_P2_SFRINIT0 0xf25f -+#define FSTV0910_P2_SFR_INIT0 0xf25f00ff -+ -+/*P2_SFRUP1*/ -+#define RSTV0910_P2_SFRUP1 0xf260 -+#define FSTV0910_P2_SYMB_FREQ_UP1 0xf26000ff -+ -+/*P2_SFRUP0*/ -+#define RSTV0910_P2_SFRUP0 0xf261 -+#define FSTV0910_P2_SYMB_FREQ_UP0 0xf26100ff -+ -+/*P2_SFRLOW1*/ -+#define RSTV0910_P2_SFRLOW1 0xf262 -+#define FSTV0910_P2_SYMB_FREQ_LOW1 0xf26200ff -+ -+/*P2_SFRLOW0*/ -+#define RSTV0910_P2_SFRLOW0 0xf263 -+#define FSTV0910_P2_SYMB_FREQ_LOW0 0xf26300ff -+ -+/*P2_SFR3*/ -+#define RSTV0910_P2_SFR3 0xf264 -+#define FSTV0910_P2_SYMB_FREQ3 0xf26400ff -+ -+/*P2_SFR2*/ -+#define RSTV0910_P2_SFR2 0xf265 -+#define FSTV0910_P2_SYMB_FREQ2 0xf26500ff -+ -+/*P2_SFR1*/ -+#define RSTV0910_P2_SFR1 0xf266 -+#define FSTV0910_P2_SYMB_FREQ1 0xf26600ff -+ -+/*P2_SFR0*/ -+#define RSTV0910_P2_SFR0 0xf267 -+#define FSTV0910_P2_SYMB_FREQ0 0xf26700ff -+ -+/*P2_TMGREG2*/ -+#define RSTV0910_P2_TMGREG2 0xf268 -+#define FSTV0910_P2_TMGREG2 0xf26800ff -+ -+/*P2_TMGREG1*/ -+#define RSTV0910_P2_TMGREG1 0xf269 -+#define FSTV0910_P2_TMGREG1 0xf26900ff -+ -+/*P2_TMGREG0*/ -+#define RSTV0910_P2_TMGREG0 0xf26a -+#define FSTV0910_P2_TMGREG0 0xf26a00ff -+ -+/*P2_TMGLOCK1*/ -+#define RSTV0910_P2_TMGLOCK1 0xf26b -+#define FSTV0910_P2_TMGLOCK_LEVEL1 0xf26b01ff -+ -+/*P2_TMGLOCK0*/ -+#define RSTV0910_P2_TMGLOCK0 0xf26c -+#define FSTV0910_P2_TMGLOCK_LEVEL0 0xf26c00ff -+ -+/*P2_TMGOBS*/ -+#define RSTV0910_P2_TMGOBS 0xf26d -+#define FSTV0910_P2_ROLLOFF_STATUS 0xf26d00c0 -+#define FSTV0910_P2_SCAN_SIGN 0xf26d0030 -+#define FSTV0910_P2_TMG_SCANNING 0xf26d0008 -+#define FSTV0910_P2_CHCENTERING_MODE 0xf26d0004 -+#define FSTV0910_P2_TMG_SCANFAIL 0xf26d0002 -+ -+/*P2_EQUALCFG*/ -+#define RSTV0910_P2_EQUALCFG 0xf26f -+#define FSTV0910_P2_NOTMG_NEGALWAIT 0xf26f0080 -+#define FSTV0910_P2_EQUAL_ON 0xf26f0040 -+#define FSTV0910_P2_SEL_EQUALCOR 0xf26f0038 -+#define FSTV0910_P2_MU_EQUALDFE 0xf26f0007 -+ -+/*P2_EQUAI1*/ -+#define RSTV0910_P2_EQUAI1 0xf270 -+#define FSTV0910_P2_EQUA_ACCI1 0xf27001ff -+ -+/*P2_EQUAQ1*/ -+#define RSTV0910_P2_EQUAQ1 0xf271 -+#define FSTV0910_P2_EQUA_ACCQ1 0xf27101ff -+ -+/*P2_EQUAI2*/ -+#define RSTV0910_P2_EQUAI2 0xf272 -+#define FSTV0910_P2_EQUA_ACCI2 0xf27201ff -+ -+/*P2_EQUAQ2*/ -+#define RSTV0910_P2_EQUAQ2 0xf273 -+#define FSTV0910_P2_EQUA_ACCQ2 0xf27301ff -+ -+/*P2_EQUAI3*/ -+#define RSTV0910_P2_EQUAI3 0xf274 -+#define FSTV0910_P2_EQUA_ACCI3 0xf27401ff -+ -+/*P2_EQUAQ3*/ -+#define RSTV0910_P2_EQUAQ3 0xf275 -+#define FSTV0910_P2_EQUA_ACCQ3 0xf27501ff -+ -+/*P2_EQUAI4*/ -+#define RSTV0910_P2_EQUAI4 0xf276 -+#define FSTV0910_P2_EQUA_ACCI4 0xf27601ff -+ -+/*P2_EQUAQ4*/ -+#define RSTV0910_P2_EQUAQ4 0xf277 -+#define FSTV0910_P2_EQUA_ACCQ4 0xf27701ff -+ -+/*P2_EQUAI5*/ -+#define RSTV0910_P2_EQUAI5 0xf278 -+#define FSTV0910_P2_EQUA_ACCI5 0xf27801ff -+ -+/*P2_EQUAQ5*/ -+#define RSTV0910_P2_EQUAQ5 0xf279 -+#define FSTV0910_P2_EQUA_ACCQ5 0xf27901ff -+ -+/*P2_EQUAI6*/ -+#define RSTV0910_P2_EQUAI6 0xf27a -+#define FSTV0910_P2_EQUA_ACCI6 0xf27a01ff -+ -+/*P2_EQUAQ6*/ -+#define RSTV0910_P2_EQUAQ6 0xf27b -+#define FSTV0910_P2_EQUA_ACCQ6 0xf27b01ff -+ -+/*P2_EQUAI7*/ -+#define RSTV0910_P2_EQUAI7 0xf27c -+#define FSTV0910_P2_EQUA_ACCI7 0xf27c01ff -+ -+/*P2_EQUAQ7*/ -+#define RSTV0910_P2_EQUAQ7 0xf27d -+#define FSTV0910_P2_EQUA_ACCQ7 0xf27d01ff -+ -+/*P2_EQUAI8*/ -+#define RSTV0910_P2_EQUAI8 0xf27e -+#define FSTV0910_P2_EQUA_ACCI8 0xf27e01ff -+ -+/*P2_EQUAQ8*/ -+#define RSTV0910_P2_EQUAQ8 0xf27f -+#define FSTV0910_P2_EQUA_ACCQ8 0xf27f01ff -+ -+/*P2_NNOSDATAT1*/ -+#define RSTV0910_P2_NNOSDATAT1 0xf280 -+#define FSTV0910_P2_NOSDATAT_NORMED1 0xf28000ff -+ -+/*P2_NNOSDATAT0*/ -+#define RSTV0910_P2_NNOSDATAT0 0xf281 -+#define FSTV0910_P2_NOSDATAT_NORMED0 0xf28100ff -+ -+/*P2_NNOSDATA1*/ -+#define RSTV0910_P2_NNOSDATA1 0xf282 -+#define FSTV0910_P2_NOSDATA_NORMED1 0xf28200ff -+ -+/*P2_NNOSDATA0*/ -+#define RSTV0910_P2_NNOSDATA0 0xf283 -+#define FSTV0910_P2_NOSDATA_NORMED0 0xf28300ff -+ -+/*P2_NNOSPLHT1*/ -+#define RSTV0910_P2_NNOSPLHT1 0xf284 -+#define FSTV0910_P2_NOSPLHT_NORMED1 0xf28400ff -+ -+/*P2_NNOSPLHT0*/ -+#define RSTV0910_P2_NNOSPLHT0 0xf285 -+#define FSTV0910_P2_NOSPLHT_NORMED0 0xf28500ff -+ -+/*P2_NNOSPLH1*/ -+#define RSTV0910_P2_NNOSPLH1 0xf286 -+#define FSTV0910_P2_NOSPLH_NORMED1 0xf28600ff -+ -+/*P2_NNOSPLH0*/ -+#define RSTV0910_P2_NNOSPLH0 0xf287 -+#define FSTV0910_P2_NOSPLH_NORMED0 0xf28700ff -+ -+/*P2_NOSDATAT1*/ -+#define RSTV0910_P2_NOSDATAT1 0xf288 -+#define FSTV0910_P2_NOSDATAT_UNNORMED1 0xf28800ff -+ -+/*P2_NOSDATAT0*/ -+#define RSTV0910_P2_NOSDATAT0 0xf289 -+#define FSTV0910_P2_NOSDATAT_UNNORMED0 0xf28900ff -+ -+/*P2_NNOSFRAME1*/ -+#define RSTV0910_P2_NNOSFRAME1 0xf28a -+#define FSTV0910_P2_NOSFRAME_NORMED1 0xf28a00ff -+ -+/*P2_NNOSFRAME0*/ -+#define RSTV0910_P2_NNOSFRAME0 0xf28b -+#define FSTV0910_P2_NOSFRAME_NORMED0 0xf28b00ff -+ -+/*P2_NNOSRAD1*/ -+#define RSTV0910_P2_NNOSRAD1 0xf28c -+#define FSTV0910_P2_NOSRADIAL_NORMED1 0xf28c00ff -+ -+/*P2_NNOSRAD0*/ -+#define RSTV0910_P2_NNOSRAD0 0xf28d -+#define FSTV0910_P2_NOSRADIAL_NORMED0 0xf28d00ff -+ -+/*P2_NOSCFGF1*/ -+#define RSTV0910_P2_NOSCFGF1 0xf28e -+#define FSTV0910_P2_LOWNOISE_MESURE 0xf28e0080 -+#define FSTV0910_P2_NOS_DELFRAME 0xf28e0040 -+#define FSTV0910_P2_NOSDATA_MODE 0xf28e0030 -+#define FSTV0910_P2_FRAMESEL_TYPESEL 0xf28e000c -+#define FSTV0910_P2_FRAMESEL_TYPE 0xf28e0003 -+ -+/*P2_CAR2CFG*/ -+#define RSTV0910_P2_CAR2CFG 0xf290 -+#define FSTV0910_P2_DESCRAMB_OFF 0xf2900080 -+#define FSTV0910_P2_EN_PHNOSRAM 0xf2900020 -+#define FSTV0910_P2_STOP_CFR2UPDATE 0xf2900010 -+#define FSTV0910_P2_STOP_NCO2UPDATE 0xf2900008 -+#define FSTV0910_P2_ROTA2ON 0xf2900004 -+#define FSTV0910_P2_PH_DET_ALGO2 0xf2900003 -+ -+/*P2_CFR2CFR1*/ -+#define RSTV0910_P2_CFR2CFR1 0xf291 -+#define FSTV0910_P2_CFR2_S2CONTROL 0xf29100c0 -+#define FSTV0910_P2_EN_S2CAR2CENTER 0xf2910020 -+#define FSTV0910_P2_BCHERRCFR2_MODE 0xf2910018 -+#define FSTV0910_P2_CFR2TOCFR1_BETA 0xf2910007 -+ -+/*P2_CAR3CFG*/ -+#define RSTV0910_P2_CAR3CFG 0xf292 -+#define FSTV0910_P2_CARRIER23_MODE 0xf29200c0 -+#define FSTV0910_P2_CAR3INTERM_DVBS1 0xf2920020 -+#define FSTV0910_P2_ABAMPLIF_MODE 0xf2920018 -+#define FSTV0910_P2_CARRIER3_ALPHA3DL 0xf2920007 -+ -+/*P2_CFR22*/ -+#define RSTV0910_P2_CFR22 0xf293 -+#define FSTV0910_P2_CAR2_FREQ2 0xf29301ff -+ -+/*P2_CFR21*/ -+#define RSTV0910_P2_CFR21 0xf294 -+#define FSTV0910_P2_CAR2_FREQ1 0xf29400ff -+ -+/*P2_CFR20*/ -+#define RSTV0910_P2_CFR20 0xf295 -+#define FSTV0910_P2_CAR2_FREQ0 0xf29500ff -+ -+/*P2_ACLC2S2Q*/ -+#define RSTV0910_P2_ACLC2S2Q 0xf297 -+#define FSTV0910_P2_ENAB_SPSKSYMB 0xf2970080 -+#define FSTV0910_P2_CAR2S2_QANOSAUTO 0xf2970040 -+#define FSTV0910_P2_CAR2S2_Q_ALPH_M 0xf2970030 -+#define FSTV0910_P2_CAR2S2_Q_ALPH_E 0xf297000f -+ -+/*P2_ACLC2S28*/ -+#define RSTV0910_P2_ACLC2S28 0xf298 -+#define FSTV0910_P2_OLDI3Q_MODE 0xf2980080 -+#define FSTV0910_P2_CAR2S2_8ANOSAUTO 0xf2980040 -+#define FSTV0910_P2_CAR2S2_8_ALPH_M 0xf2980030 -+#define FSTV0910_P2_CAR2S2_8_ALPH_E 0xf298000f -+ -+/*P2_ACLC2S216A*/ -+#define RSTV0910_P2_ACLC2S216A 0xf299 -+#define FSTV0910_P2_CAR2S2_16ANOSAUTO 0xf2990040 -+#define FSTV0910_P2_CAR2S2_16A_ALPH_M 0xf2990030 -+#define FSTV0910_P2_CAR2S2_16A_ALPH_E 0xf299000f -+ -+/*P2_ACLC2S232A*/ -+#define RSTV0910_P2_ACLC2S232A 0xf29a -+#define FSTV0910_P2_CAR2S2_32ANOSUATO 0xf29a0040 -+#define FSTV0910_P2_CAR2S2_32A_ALPH_M 0xf29a0030 -+#define FSTV0910_P2_CAR2S2_32A_ALPH_E 0xf29a000f -+ -+/*P2_BCLC2S2Q*/ -+#define RSTV0910_P2_BCLC2S2Q 0xf29c -+#define FSTV0910_P2_DVBS2S2Q_NIP 0xf29c0080 -+#define FSTV0910_P2_CAR2S2_QBNOSAUTO 0xf29c0040 -+#define FSTV0910_P2_CAR2S2_Q_BETA_M 0xf29c0030 -+#define FSTV0910_P2_CAR2S2_Q_BETA_E 0xf29c000f -+ -+/*P2_BCLC2S28*/ -+#define RSTV0910_P2_BCLC2S28 0xf29d -+#define FSTV0910_P2_DVBS2S28_NIP 0xf29d0080 -+#define FSTV0910_P2_CAR2S2_8BNOSAUTO 0xf29d0040 -+#define FSTV0910_P2_CAR2S2_8_BETA_M 0xf29d0030 -+#define FSTV0910_P2_CAR2S2_8_BETA_E 0xf29d000f -+ -+/*P2_PLROOT2*/ -+#define RSTV0910_P2_PLROOT2 0xf2ac -+#define FSTV0910_P2_PLHAUTO_DISPLH 0xf2ac0040 -+#define FSTV0910_P2_PLHAUTO_FASTMODE 0xf2ac0020 -+#define FSTV0910_P2_PLHAUTO_ENABLE 0xf2ac0010 -+#define FSTV0910_P2_PLSCRAMB_MODE 0xf2ac000c -+#define FSTV0910_P2_PLSCRAMB_ROOT2 0xf2ac0003 -+ -+/*P2_PLROOT1*/ -+#define RSTV0910_P2_PLROOT1 0xf2ad -+#define FSTV0910_P2_PLSCRAMB_ROOT1 0xf2ad00ff -+ -+/*P2_PLROOT0*/ -+#define RSTV0910_P2_PLROOT0 0xf2ae -+#define FSTV0910_P2_PLSCRAMB_ROOT0 0xf2ae00ff -+ -+/*P2_MODCODLST7*/ -+#define RSTV0910_P2_MODCODLST7 0xf2b7 -+#define FSTV0910_P2_MODCOD_NNOSFILTER 0xf2b70080 -+#define FSTV0910_P2_MODCODLST_NOSTYPE 0xf2b70040 -+#define FSTV0910_P2_DIS_8PSK_9_10 0xf2b70030 -+#define FSTV0910_P2_DIS_8P_8_9 0xf2b7000f -+ -+/*P2_MODCODLST8*/ -+#define RSTV0910_P2_MODCODLST8 0xf2b8 -+#define FSTV0910_P2_DIS_8P_5_6 0xf2b800f0 -+#define FSTV0910_P2_DIS_8P_3_4 0xf2b8000f -+ -+/*P2_MODCODLST9*/ -+#define RSTV0910_P2_MODCODLST9 0xf2b9 -+#define FSTV0910_P2_DIS_8P_2_3 0xf2b900f0 -+#define FSTV0910_P2_DIS_8P_3_5 0xf2b9000f -+ -+/*P2_MODCODLSTA*/ -+#define RSTV0910_P2_MODCODLSTA 0xf2ba -+#define FSTV0910_P2_NOSFILTER_LIMITE 0xf2ba0080 -+#define FSTV0910_P2_NOSFILTER_MODE 0xf2ba0040 -+#define FSTV0910_P2_DIS_QPSK_9_10 0xf2ba0030 -+#define FSTV0910_P2_DIS_QP_8_9 0xf2ba000f -+ -+/*P2_MODCODLSTB*/ -+#define RSTV0910_P2_MODCODLSTB 0xf2bb -+#define FSTV0910_P2_DIS_QP_5_6 0xf2bb00f0 -+#define FSTV0910_P2_DIS_QP_4_5 0xf2bb000f -+ -+/*P2_MODCODLSTC*/ -+#define RSTV0910_P2_MODCODLSTC 0xf2bc -+#define FSTV0910_P2_DIS_QP_3_4 0xf2bc00f0 -+#define FSTV0910_P2_DIS_QP_2_3 0xf2bc000f -+ -+/*P2_MODCODLSTD*/ -+#define RSTV0910_P2_MODCODLSTD 0xf2bd -+#define FSTV0910_P2_DIS_QPSK_3_5 0xf2bd00f0 -+#define FSTV0910_P2_DIS_QPSK_1_2 0xf2bd000f -+ -+/*P2_GAUSSR0*/ -+#define RSTV0910_P2_GAUSSR0 0xf2c0 -+#define FSTV0910_P2_EN_CCIMODE 0xf2c00080 -+#define FSTV0910_P2_R0_GAUSSIEN 0xf2c0007f -+ -+/*P2_CCIR0*/ -+#define RSTV0910_P2_CCIR0 0xf2c1 -+#define FSTV0910_P2_CCIDETECT_PLHONLY 0xf2c10080 -+#define FSTV0910_P2_R0_CCI 0xf2c1007f -+ -+/*P2_CCIQUANT*/ -+#define RSTV0910_P2_CCIQUANT 0xf2c2 -+#define FSTV0910_P2_CCI_BETA 0xf2c200e0 -+#define FSTV0910_P2_CCI_QUANT 0xf2c2001f -+ -+/*P2_CCITHRES*/ -+#define RSTV0910_P2_CCITHRES 0xf2c3 -+#define FSTV0910_P2_CCI_THRESHOLD 0xf2c300ff -+ -+/*P2_CCIACC*/ -+#define RSTV0910_P2_CCIACC 0xf2c4 -+#define FSTV0910_P2_CCI_VALUE 0xf2c400ff -+ -+/*P2_DSTATUS4*/ -+#define RSTV0910_P2_DSTATUS4 0xf2c5 -+#define FSTV0910_P2_RAINFADE_DETECT 0xf2c50080 -+#define FSTV0910_P2_NOTHRES2_FAIL 0xf2c50040 -+#define FSTV0910_P2_NOTHRES1_FAIL 0xf2c50020 -+#define FSTV0910_P2_PILOT_FAILDETECT 0xf2c50010 -+#define FSTV0910_P2_HIER_DETECT 0xf2c50008 -+#define FSTV0910_P2_DMDPROG_ERROR 0xf2c50004 -+#define FSTV0910_P2_CSTENV_DETECT 0xf2c50002 -+#define FSTV0910_P2_DETECTION_TRIAX 0xf2c50001 -+ -+/*P2_DMDRESCFG*/ -+#define RSTV0910_P2_DMDRESCFG 0xf2c6 -+#define FSTV0910_P2_DMDRES_RESET 0xf2c60080 -+#define FSTV0910_P2_DMDRES_NOISESQR 0xf2c60010 -+#define FSTV0910_P2_DMDRES_STRALL 0xf2c60008 -+#define FSTV0910_P2_DMDRES_NEWONLY 0xf2c60004 -+#define FSTV0910_P2_DMDRES_NOSTORE 0xf2c60002 -+#define FSTV0910_P2_DMDRES_AGC2MEM 0xf2c60001 -+ -+/*P2_DMDRESADR*/ -+#define RSTV0910_P2_DMDRESADR 0xf2c7 -+#define FSTV0910_P2_SUSP_PREDCANAL 0xf2c70080 -+#define FSTV0910_P2_DMDRES_VALIDCFR 0xf2c70040 -+#define FSTV0910_P2_DMDRES_MEMFULL 0xf2c70030 -+#define FSTV0910_P2_DMDRES_RESNBR 0xf2c7000f -+ -+/*P2_DMDRESDATA7*/ -+#define RSTV0910_P2_DMDRESDATA7 0xf2c8 -+#define FSTV0910_P2_DMDRES_DATA7 0xf2c800ff -+ -+/*P2_DMDRESDATA6*/ -+#define RSTV0910_P2_DMDRESDATA6 0xf2c9 -+#define FSTV0910_P2_DMDRES_DATA6 0xf2c900ff -+ -+/*P2_DMDRESDATA5*/ -+#define RSTV0910_P2_DMDRESDATA5 0xf2ca -+#define FSTV0910_P2_DMDRES_DATA5 0xf2ca00ff -+ -+/*P2_DMDRESDATA4*/ -+#define RSTV0910_P2_DMDRESDATA4 0xf2cb -+#define FSTV0910_P2_DMDRES_DATA4 0xf2cb00ff -+ -+/*P2_DMDRESDATA3*/ -+#define RSTV0910_P2_DMDRESDATA3 0xf2cc -+#define FSTV0910_P2_DMDRES_DATA3 0xf2cc00ff -+ -+/*P2_DMDRESDATA2*/ -+#define RSTV0910_P2_DMDRESDATA2 0xf2cd -+#define FSTV0910_P2_DMDRES_DATA2 0xf2cd00ff -+ -+/*P2_DMDRESDATA1*/ -+#define RSTV0910_P2_DMDRESDATA1 0xf2ce -+#define FSTV0910_P2_DMDRES_DATA1 0xf2ce00ff -+ -+/*P2_DMDRESDATA0*/ -+#define RSTV0910_P2_DMDRESDATA0 0xf2cf -+#define FSTV0910_P2_DMDRES_DATA0 0xf2cf00ff -+ -+/*P2_FFEI1*/ -+#define RSTV0910_P2_FFEI1 0xf2d0 -+#define FSTV0910_P2_FFE_ACCI1 0xf2d001ff -+ -+/*P2_FFEQ1*/ -+#define RSTV0910_P2_FFEQ1 0xf2d1 -+#define FSTV0910_P2_FFE_ACCQ1 0xf2d101ff -+ -+/*P2_FFEI2*/ -+#define RSTV0910_P2_FFEI2 0xf2d2 -+#define FSTV0910_P2_FFE_ACCI2 0xf2d201ff -+ -+/*P2_FFEQ2*/ -+#define RSTV0910_P2_FFEQ2 0xf2d3 -+#define FSTV0910_P2_FFE_ACCQ2 0xf2d301ff -+ -+/*P2_FFEI3*/ -+#define RSTV0910_P2_FFEI3 0xf2d4 -+#define FSTV0910_P2_FFE_ACCI3 0xf2d401ff -+ -+/*P2_FFEQ3*/ -+#define RSTV0910_P2_FFEQ3 0xf2d5 -+#define FSTV0910_P2_FFE_ACCQ3 0xf2d501ff -+ -+/*P2_FFEI4*/ -+#define RSTV0910_P2_FFEI4 0xf2d6 -+#define FSTV0910_P2_FFE_ACCI4 0xf2d601ff -+ -+/*P2_FFEQ4*/ -+#define RSTV0910_P2_FFEQ4 0xf2d7 -+#define FSTV0910_P2_FFE_ACCQ4 0xf2d701ff -+ -+/*P2_FFECFG*/ -+#define RSTV0910_P2_FFECFG 0xf2d8 -+#define FSTV0910_P2_EQUALFFE_ON 0xf2d80040 -+#define FSTV0910_P2_EQUAL_USEDSYMB 0xf2d80030 -+#define FSTV0910_P2_MU_EQUALFFE 0xf2d80007 -+ -+/*P2_TNRCFG2*/ -+#define RSTV0910_P2_TNRCFG2 0xf2e1 -+#define FSTV0910_P2_TUN_IQSWAP 0xf2e10080 -+#define FSTV0910_P2_STB6110_STEP2MHZ 0xf2e10040 -+#define FSTV0910_P2_STB6120_DBLI2C 0xf2e10020 -+#define FSTV0910_P2_TUNER_WIDEBAND 0xf2e10010 -+#define FSTV0910_P2_TUNER_OBSPAGE 0xf2e10008 -+#define FSTV0910_P2_DIS_BWCALC 0xf2e10004 -+#define FSTV0910_P2_SHORT_WAITSTATES 0xf2e10002 -+#define FSTV0910_P2_DIS_2BWAGC1 0xf2e10001 -+ -+/*P2_SMAPCOEF7*/ -+#define RSTV0910_P2_SMAPCOEF7 0xf300 -+#define FSTV0910_P2_DIS_QSCALE 0xf3000080 -+#define FSTV0910_P2_SMAPCOEF_Q_LLR12 0xf300017f -+ -+/*P2_SMAPCOEF6*/ -+#define RSTV0910_P2_SMAPCOEF6 0xf301 -+#define FSTV0910_P2_DIS_AGC2SCALE 0xf3010080 -+#define FSTV0910_P2_DIS_16IQMULT 0xf3010040 -+#define FSTV0910_P2_OLD_16APSK47 0xf3010020 -+#define FSTV0910_P2_OLD_16APSK12 0xf3010010 -+#define FSTV0910_P2_DIS_NEWSCALE 0xf3010008 -+#define FSTV0910_P2_ADJ_8PSKLLR1 0xf3010004 -+#define FSTV0910_P2_OLD_8PSKLLR1 0xf3010002 -+#define FSTV0910_P2_DIS_AB8PSK 0xf3010001 -+ -+/*P2_SMAPCOEF5*/ -+#define RSTV0910_P2_SMAPCOEF5 0xf302 -+#define FSTV0910_P2_DIS_8SCALE 0xf3020080 -+#define FSTV0910_P2_SMAPCOEF_8P_LLR23 0xf302017f -+ -+/*P2_NOSTHRES1*/ -+#define RSTV0910_P2_NOSTHRES1 0xf309 -+#define FSTV0910_P2_NOS_THRESHOLD1 0xf30900ff -+ -+/*P2_NOSTHRES2*/ -+#define RSTV0910_P2_NOSTHRES2 0xf30a -+#define FSTV0910_P2_NOS_THRESHOLD2 0xf30a00ff -+ -+/*P2_NOSDIFF1*/ -+#define RSTV0910_P2_NOSDIFF1 0xf30b -+#define FSTV0910_P2_NOSTHRES1_DIFF 0xf30b00ff -+ -+/*P2_RAINFADE*/ -+#define RSTV0910_P2_RAINFADE 0xf30c -+#define FSTV0910_P2_NOSTHRES_DATAT 0xf30c0080 -+#define FSTV0910_P2_RAINFADE_CNLIMIT 0xf30c0070 -+#define FSTV0910_P2_RAINFADE_TIMEOUT 0xf30c0007 -+ -+/*P2_NOSRAMCFG*/ -+#define RSTV0910_P2_NOSRAMCFG 0xf30d -+#define FSTV0910_P2_NOSRAM_DVBS2DATA 0xf30d0080 -+#define FSTV0910_P2_NOSRAM_QUADRAT 0xf30d0040 -+#define FSTV0910_P2_NOSRAM_ACTIVATION 0xf30d0030 -+#define FSTV0910_P2_NOSRAM_CNRONLY 0xf30d0008 -+#define FSTV0910_P2_NOSRAM_LGNCNR1 0xf30d0007 -+ -+/*P2_NOSRAMPOS*/ -+#define RSTV0910_P2_NOSRAMPOS 0xf30e -+#define FSTV0910_P2_NOSRAM_LGNCNR0 0xf30e00f0 -+#define FSTV0910_P2_NOSRAM_VALIDE 0xf30e0004 -+#define FSTV0910_P2_NOSRAM_CNRVAL1 0xf30e0003 -+ -+/*P2_NOSRAMVAL*/ -+#define RSTV0910_P2_NOSRAMVAL 0xf30f -+#define FSTV0910_P2_NOSRAM_CNRVAL0 0xf30f00ff -+ -+/*P2_DMDPLHSTAT*/ -+#define RSTV0910_P2_DMDPLHSTAT 0xf320 -+#define FSTV0910_P2_PLH_STATISTIC 0xf32000ff -+ -+/*P2_LOCKTIME3*/ -+#define RSTV0910_P2_LOCKTIME3 0xf322 -+#define FSTV0910_P2_DEMOD_LOCKTIME3 0xf32200ff -+ -+/*P2_LOCKTIME2*/ -+#define RSTV0910_P2_LOCKTIME2 0xf323 -+#define FSTV0910_P2_DEMOD_LOCKTIME2 0xf32300ff -+ -+/*P2_LOCKTIME1*/ -+#define RSTV0910_P2_LOCKTIME1 0xf324 -+#define FSTV0910_P2_DEMOD_LOCKTIME1 0xf32400ff -+ -+/*P2_LOCKTIME0*/ -+#define RSTV0910_P2_LOCKTIME0 0xf325 -+#define FSTV0910_P2_DEMOD_LOCKTIME0 0xf32500ff -+ -+/*P2_VITSCALE*/ -+#define RSTV0910_P2_VITSCALE 0xf332 -+#define FSTV0910_P2_NVTH_NOSRANGE 0xf3320080 -+#define FSTV0910_P2_VERROR_MAXMODE 0xf3320040 -+#define FSTV0910_P2_KDIV_MODE 0xf3320030 -+#define FSTV0910_P2_NSLOWSN_LOCKED 0xf3320008 -+#define FSTV0910_P2_DELOCK_PRFLOSS 0xf3320004 -+#define FSTV0910_P2_DIS_RSFLOCK 0xf3320002 -+ -+/*P2_FECM*/ -+#define RSTV0910_P2_FECM 0xf333 -+#define FSTV0910_P2_DSS_DVB 0xf3330080 -+#define FSTV0910_P2_DEMOD_BYPASS 0xf3330040 -+#define FSTV0910_P2_CMP_SLOWMODE 0xf3330020 -+#define FSTV0910_P2_DSS_SRCH 0xf3330010 -+#define FSTV0910_P2_DIFF_MODEVIT 0xf3330004 -+#define FSTV0910_P2_SYNCVIT 0xf3330002 -+#define FSTV0910_P2_IQINV 0xf3330001 -+ -+/*P2_VTH12*/ -+#define RSTV0910_P2_VTH12 0xf334 -+#define FSTV0910_P2_VTH12 0xf33400ff -+ -+/*P2_VTH23*/ -+#define RSTV0910_P2_VTH23 0xf335 -+#define FSTV0910_P2_VTH23 0xf33500ff -+ -+/*P2_VTH34*/ -+#define RSTV0910_P2_VTH34 0xf336 -+#define FSTV0910_P2_VTH34 0xf33600ff -+ -+/*P2_VTH56*/ -+#define RSTV0910_P2_VTH56 0xf337 -+#define FSTV0910_P2_VTH56 0xf33700ff -+ -+/*P2_VTH67*/ -+#define RSTV0910_P2_VTH67 0xf338 -+#define FSTV0910_P2_VTH67 0xf33800ff -+ -+/*P2_VTH78*/ -+#define RSTV0910_P2_VTH78 0xf339 -+#define FSTV0910_P2_VTH78 0xf33900ff -+ -+/*P2_VITCURPUN*/ -+#define RSTV0910_P2_VITCURPUN 0xf33a -+#define FSTV0910_P2_CYCLESLIP_VIT 0xf33a0080 -+#define FSTV0910_P2_VIT_ROTA180 0xf33a0040 -+#define FSTV0910_P2_VIT_ROTA90 0xf33a0020 -+#define FSTV0910_P2_VIT_CURPUN 0xf33a001f -+ -+/*P2_VERROR*/ -+#define RSTV0910_P2_VERROR 0xf33b -+#define FSTV0910_P2_REGERR_VIT 0xf33b00ff -+ -+/*P2_PRVIT*/ -+#define RSTV0910_P2_PRVIT 0xf33c -+#define FSTV0910_P2_DIS_VTHLOCK 0xf33c0040 -+#define FSTV0910_P2_E7_8VIT 0xf33c0020 -+#define FSTV0910_P2_E6_7VIT 0xf33c0010 -+#define FSTV0910_P2_E5_6VIT 0xf33c0008 -+#define FSTV0910_P2_E3_4VIT 0xf33c0004 -+#define FSTV0910_P2_E2_3VIT 0xf33c0002 -+#define FSTV0910_P2_E1_2VIT 0xf33c0001 -+ -+/*P2_VAVSRVIT*/ -+#define RSTV0910_P2_VAVSRVIT 0xf33d -+#define FSTV0910_P2_AMVIT 0xf33d0080 -+#define FSTV0910_P2_FROZENVIT 0xf33d0040 -+#define FSTV0910_P2_SNVIT 0xf33d0030 -+#define FSTV0910_P2_TOVVIT 0xf33d000c -+#define FSTV0910_P2_HYPVIT 0xf33d0003 -+ -+/*P2_VSTATUSVIT*/ -+#define RSTV0910_P2_VSTATUSVIT 0xf33e -+#define FSTV0910_P2_VITERBI_ON 0xf33e0080 -+#define FSTV0910_P2_END_LOOPVIT 0xf33e0040 -+#define FSTV0910_P2_VITERBI_DEPRF 0xf33e0020 -+#define FSTV0910_P2_PRFVIT 0xf33e0010 -+#define FSTV0910_P2_LOCKEDVIT 0xf33e0008 -+#define FSTV0910_P2_VITERBI_DELOCK 0xf33e0004 -+#define FSTV0910_P2_VIT_DEMODSEL 0xf33e0002 -+#define FSTV0910_P2_VITERBI_COMPOUT 0xf33e0001 -+ -+/*P2_VTHINUSE*/ -+#define RSTV0910_P2_VTHINUSE 0xf33f -+#define FSTV0910_P2_VIT_INUSE 0xf33f00ff -+ -+/*P2_KDIV12*/ -+#define RSTV0910_P2_KDIV12 0xf340 -+#define FSTV0910_P2_KDIV12_MANUAL 0xf3400080 -+#define FSTV0910_P2_K_DIVIDER_12 0xf340007f -+ -+/*P2_KDIV23*/ -+#define RSTV0910_P2_KDIV23 0xf341 -+#define FSTV0910_P2_KDIV23_MANUAL 0xf3410080 -+#define FSTV0910_P2_K_DIVIDER_23 0xf341007f -+ -+/*P2_KDIV34*/ -+#define RSTV0910_P2_KDIV34 0xf342 -+#define FSTV0910_P2_KDIV34_MANUAL 0xf3420080 -+#define FSTV0910_P2_K_DIVIDER_34 0xf342007f -+ -+/*P2_KDIV56*/ -+#define RSTV0910_P2_KDIV56 0xf343 -+#define FSTV0910_P2_KDIV56_MANUAL 0xf3430080 -+#define FSTV0910_P2_K_DIVIDER_56 0xf343007f -+ -+/*P2_KDIV67*/ -+#define RSTV0910_P2_KDIV67 0xf344 -+#define FSTV0910_P2_KDIV67_MANUAL 0xf3440080 -+#define FSTV0910_P2_K_DIVIDER_67 0xf344007f -+ -+/*P2_KDIV78*/ -+#define RSTV0910_P2_KDIV78 0xf345 -+#define FSTV0910_P2_KDIV78_MANUAL 0xf3450080 -+#define FSTV0910_P2_K_DIVIDER_78 0xf345007f -+ -+/*P2_PDELCTRL0*/ -+#define RSTV0910_P2_PDELCTRL0 0xf34f -+#define FSTV0910_P2_ISIOBS_MODE 0xf34f0030 -+#define FSTV0910_P2_PDELDIS_BITWISE 0xf34f0004 -+ -+/*P2_PDELCTRL1*/ -+#define RSTV0910_P2_PDELCTRL1 0xf350 -+#define FSTV0910_P2_INV_MISMASK 0xf3500080 -+#define FSTV0910_P2_FORCE_ACCEPTED 0xf3500040 -+#define FSTV0910_P2_FILTER_EN 0xf3500020 -+#define FSTV0910_P2_FORCE_PKTDELINUSE 0xf3500010 -+#define FSTV0910_P2_HYSTEN 0xf3500008 -+#define FSTV0910_P2_HYSTSWRST 0xf3500004 -+#define FSTV0910_P2_EN_MIS00 0xf3500002 -+#define FSTV0910_P2_ALGOSWRST 0xf3500001 -+ -+/*P2_PDELCTRL2*/ -+#define RSTV0910_P2_PDELCTRL2 0xf351 -+#define FSTV0910_P2_FORCE_CONTINUOUS 0xf3510080 -+#define FSTV0910_P2_RESET_UPKO_COUNT 0xf3510040 -+#define FSTV0910_P2_USER_PKTDELIN_NB 0xf3510020 -+#define FSTV0910_P2_DATA_UNBBSCRAMBLED 0xf3510008 -+#define FSTV0910_P2_FORCE_LONGPKT 0xf3510004 -+#define FSTV0910_P2_FRAME_MODE 0xf3510002 -+ -+/*P2_HYSTTHRESH*/ -+#define RSTV0910_P2_HYSTTHRESH 0xf354 -+#define FSTV0910_P2_DELIN_LOCKTHRES 0xf35400f0 -+#define FSTV0910_P2_DELIN_UNLOCKTHRES 0xf354000f -+ -+/*P2_ISIENTRY*/ -+#define RSTV0910_P2_ISIENTRY 0xf35e -+#define FSTV0910_P2_ISI_ENTRY 0xf35e00ff -+ -+/*P2_ISIBITENA*/ -+#define RSTV0910_P2_ISIBITENA 0xf35f -+#define FSTV0910_P2_ISI_BIT_EN 0xf35f00ff -+ -+/*P2_MATSTR1*/ -+#define RSTV0910_P2_MATSTR1 0xf360 -+#define FSTV0910_P2_MATYPE_CURRENT1 0xf36000ff -+ -+/*P2_MATSTR0*/ -+#define RSTV0910_P2_MATSTR0 0xf361 -+#define FSTV0910_P2_MATYPE_CURRENT0 0xf36100ff -+ -+/*P2_UPLSTR1*/ -+#define RSTV0910_P2_UPLSTR1 0xf362 -+#define FSTV0910_P2_UPL_CURRENT1 0xf36200ff -+ -+/*P2_UPLSTR0*/ -+#define RSTV0910_P2_UPLSTR0 0xf363 -+#define FSTV0910_P2_UPL_CURRENT0 0xf36300ff -+ -+/*P2_DFLSTR1*/ -+#define RSTV0910_P2_DFLSTR1 0xf364 -+#define FSTV0910_P2_DFL_CURRENT1 0xf36400ff -+ -+/*P2_DFLSTR0*/ -+#define RSTV0910_P2_DFLSTR0 0xf365 -+#define FSTV0910_P2_DFL_CURRENT0 0xf36500ff -+ -+/*P2_SYNCSTR*/ -+#define RSTV0910_P2_SYNCSTR 0xf366 -+#define FSTV0910_P2_SYNC_CURRENT 0xf36600ff -+ -+/*P2_SYNCDSTR1*/ -+#define RSTV0910_P2_SYNCDSTR1 0xf367 -+#define FSTV0910_P2_SYNCD_CURRENT1 0xf36700ff -+ -+/*P2_SYNCDSTR0*/ -+#define RSTV0910_P2_SYNCDSTR0 0xf368 -+#define FSTV0910_P2_SYNCD_CURRENT0 0xf36800ff -+ -+/*P2_PDELSTATUS1*/ -+#define RSTV0910_P2_PDELSTATUS1 0xf369 -+#define FSTV0910_P2_PKTDELIN_DELOCK 0xf3690080 -+#define FSTV0910_P2_SYNCDUPDFL_BADDFL 0xf3690040 -+#define FSTV0910_P2_CONTINUOUS_STREAM 0xf3690020 -+#define FSTV0910_P2_UNACCEPTED_STREAM 0xf3690010 -+#define FSTV0910_P2_BCH_ERROR_FLAG 0xf3690008 -+#define FSTV0910_P2_BBHCRCKO 0xf3690004 -+#define FSTV0910_P2_PKTDELIN_LOCK 0xf3690002 -+#define FSTV0910_P2_FIRST_LOCK 0xf3690001 -+ -+/*P2_PDELSTATUS2*/ -+#define RSTV0910_P2_PDELSTATUS2 0xf36a -+#define FSTV0910_P2_PKTDEL_DEMODSEL 0xf36a0080 -+#define FSTV0910_P2_FRAME_MODCOD 0xf36a007c -+#define FSTV0910_P2_FRAME_TYPE 0xf36a0003 -+ -+/*P2_BBFCRCKO1*/ -+#define RSTV0910_P2_BBFCRCKO1 0xf36b -+#define FSTV0910_P2_BBHCRC_KOCNT1 0xf36b00ff -+ -+/*P2_BBFCRCKO0*/ -+#define RSTV0910_P2_BBFCRCKO0 0xf36c -+#define FSTV0910_P2_BBHCRC_KOCNT0 0xf36c00ff -+ -+/*P2_UPCRCKO1*/ -+#define RSTV0910_P2_UPCRCKO1 0xf36d -+#define FSTV0910_P2_PKTCRC_KOCNT1 0xf36d00ff -+ -+/*P2_UPCRCKO0*/ -+#define RSTV0910_P2_UPCRCKO0 0xf36e -+#define FSTV0910_P2_PKTCRC_KOCNT0 0xf36e00ff -+ -+/*P2_PDELCTRL3*/ -+#define RSTV0910_P2_PDELCTRL3 0xf36f -+#define FSTV0910_P2_PKTDEL_CONTFAIL 0xf36f0080 -+#define FSTV0910_P2_PKTDEL_ENLONGPKT 0xf36f0040 -+#define FSTV0910_P2_NOFIFO_BCHERR 0xf36f0020 -+#define FSTV0910_P2_PKTDELIN_DELACMERR 0xf36f0010 -+#define FSTV0910_P2_SATURATE_BBPKTKO 0xf36f0004 -+#define FSTV0910_P2_PKTDEL_BCHERRCONT 0xf36f0002 -+#define FSTV0910_P2_ETHERNET_DISFCS 0xf36f0001 -+ -+/*P2_TSSTATEM*/ -+#define RSTV0910_P2_TSSTATEM 0xf370 -+#define FSTV0910_P2_TSDIL_ON 0xf3700080 -+#define FSTV0910_P2_TSSKIPRS_ON 0xf3700040 -+#define FSTV0910_P2_TSRS_ON 0xf3700020 -+#define FSTV0910_P2_TSDESCRAMB_ON 0xf3700010 -+#define FSTV0910_P2_TSFRAME_MODE 0xf3700008 -+#define FSTV0910_P2_TS_DISABLE 0xf3700004 -+#define FSTV0910_P2_TSACM_MODE 0xf3700002 -+#define FSTV0910_P2_TSOUT_NOSYNC 0xf3700001 -+ -+/*P2_TSCFGH*/ -+#define RSTV0910_P2_TSCFGH 0xf372 -+#define FSTV0910_P2_TSFIFO_DVBCI 0xf3720080 -+#define FSTV0910_P2_TSFIFO_SERIAL 0xf3720040 -+#define FSTV0910_P2_TSFIFO_TEIUPDATE 0xf3720020 -+#define FSTV0910_P2_TSFIFO_DUTY50 0xf3720010 -+#define FSTV0910_P2_TSFIFO_HSGNLOUT 0xf3720008 -+#define FSTV0910_P2_TSFIFO_ERRMODE 0xf3720006 -+#define FSTV0910_P2_RST_HWARE 0xf3720001 -+ -+/*P2_TSCFGM*/ -+#define RSTV0910_P2_TSCFGM 0xf373 -+#define FSTV0910_P2_TSFIFO_MANSPEED 0xf37300c0 -+#define FSTV0910_P2_TSFIFO_PERMDATA 0xf3730020 -+#define FSTV0910_P2_TSFIFO_NONEWSGNL 0xf3730010 -+#define FSTV0910_P2_NPD_SPECDVBS2 0xf3730004 -+#define FSTV0910_P2_TSFIFO_DPUNACTIVE 0xf3730002 -+#define FSTV0910_P2_TSFIFO_INVDATA 0xf3730001 -+ -+/*P2_TSCFGL*/ -+#define RSTV0910_P2_TSCFGL 0xf374 -+#define FSTV0910_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 -+#define FSTV0910_P2_BCHERROR_MODE 0xf3740030 -+#define FSTV0910_P2_TSFIFO_NSGNL2DATA 0xf3740008 -+#define FSTV0910_P2_TSFIFO_EMBINDVB 0xf3740004 -+#define FSTV0910_P2_TSFIFO_BITSPEED 0xf3740003 -+ -+/*P2_TSINSDELH*/ -+#define RSTV0910_P2_TSINSDELH 0xf376 -+#define FSTV0910_P2_TSDEL_SYNCBYTE 0xf3760080 -+#define FSTV0910_P2_TSDEL_XXHEADER 0xf3760040 -+#define FSTV0910_P2_TSDEL_BBHEADER 0xf3760020 -+#define FSTV0910_P2_TSDEL_DATAFIELD 0xf3760010 -+#define FSTV0910_P2_TSINSDEL_ISCR 0xf3760008 -+#define FSTV0910_P2_TSINSDEL_NPD 0xf3760004 -+#define FSTV0910_P2_TSINSDEL_RSPARITY 0xf3760002 -+#define FSTV0910_P2_TSINSDEL_CRC8 0xf3760001 -+ -+/*P2_TSDIVN*/ -+#define RSTV0910_P2_TSDIVN 0xf379 -+#define FSTV0910_P2_TSFIFO_SPEEDMODE 0xf37900c0 -+#define FSTV0910_P2_BYTE_OVERSAMPLING 0xf3790038 -+#define FSTV0910_P2_TSFIFO_RISEOK 0xf3790007 -+ -+/*P2_TSCFG4*/ -+#define RSTV0910_P2_TSCFG4 0xf37a -+#define FSTV0910_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0 -+#define FSTV0910_P2_TSFIFO_HIERSEL 0xf37a0020 -+#define FSTV0910_P2_TSFIFO_SPECTOKEN 0xf37a0010 -+#define FSTV0910_P2_TSFIFO_MAXMODE 0xf37a0008 -+#define FSTV0910_P2_TSFIFO_FRFORCEPKT 0xf37a0004 -+#define FSTV0910_P2_EXT_FECSPYIN 0xf37a0002 -+#define FSTV0910_P2_TSFIFO_DELSPEEDUP 0xf37a0001 -+ -+/*P2_TSSPEED*/ -+#define RSTV0910_P2_TSSPEED 0xf380 -+#define FSTV0910_P2_TSFIFO_OUTSPEED 0xf38000ff -+ -+/*P2_TSSTATUS*/ -+#define RSTV0910_P2_TSSTATUS 0xf381 -+#define FSTV0910_P2_TSFIFO_LINEOK 0xf3810080 -+#define FSTV0910_P2_TSFIFO_ERROR 0xf3810040 -+#define FSTV0910_P2_TSFIFO_DATA7 0xf3810020 -+#define FSTV0910_P2_TSFIFO_NOSYNC 0xf3810010 -+#define FSTV0910_P2_ISCR_INITIALIZED 0xf3810008 -+#define FSTV0910_P2_TSREGUL_ERROR 0xf3810004 -+#define FSTV0910_P2_SOFFIFO_UNREGUL 0xf3810002 -+#define FSTV0910_P2_DIL_READY 0xf3810001 -+ -+/*P2_TSSTATUS2*/ -+#define RSTV0910_P2_TSSTATUS2 0xf382 -+#define FSTV0910_P2_TSFIFO_DEMODSEL 0xf3820080 -+#define FSTV0910_P2_TSFIFOSPEED_STORE 0xf3820040 -+#define FSTV0910_P2_DILXX_RESET 0xf3820020 -+#define FSTV0910_P2_TSSPEED_IMPOSSIBLE 0xf3820010 -+#define FSTV0910_P2_TSFIFO_LINENOK 0xf3820008 -+#define FSTV0910_P2_TSFIFO_MUXSTREAM 0xf3820004 -+#define FSTV0910_P2_SCRAMBDETECT 0xf3820002 -+#define FSTV0910_P2_ULDTV67_FALSELOCK 0xf3820001 -+ -+/*P2_TSBITRATE1*/ -+#define RSTV0910_P2_TSBITRATE1 0xf383 -+#define FSTV0910_P2_TSFIFO_BITRATE1 0xf38300ff -+ -+/*P2_TSBITRATE0*/ -+#define RSTV0910_P2_TSBITRATE0 0xf384 -+#define FSTV0910_P2_TSFIFO_BITRATE0 0xf38400ff -+ -+/*P2_ERRCTRL1*/ -+#define RSTV0910_P2_ERRCTRL1 0xf398 -+#define FSTV0910_P2_ERR_SOURCE1 0xf39800f0 -+#define FSTV0910_P2_NUM_EVENT1 0xf3980007 -+ -+/*P2_ERRCNT12*/ -+#define RSTV0910_P2_ERRCNT12 0xf399 -+#define FSTV0910_P2_ERRCNT1_OLDVALUE 0xf3990080 -+#define FSTV0910_P2_ERR_CNT12 0xf399007f -+ -+/*P2_ERRCNT11*/ -+#define RSTV0910_P2_ERRCNT11 0xf39a -+#define FSTV0910_P2_ERR_CNT11 0xf39a00ff -+ -+/*P2_ERRCNT10*/ -+#define RSTV0910_P2_ERRCNT10 0xf39b -+#define FSTV0910_P2_ERR_CNT10 0xf39b00ff -+ -+/*P2_ERRCTRL2*/ -+#define RSTV0910_P2_ERRCTRL2 0xf39c -+#define FSTV0910_P2_ERR_SOURCE2 0xf39c00f0 -+#define FSTV0910_P2_NUM_EVENT2 0xf39c0007 -+ -+/*P2_ERRCNT22*/ -+#define RSTV0910_P2_ERRCNT22 0xf39d -+#define FSTV0910_P2_ERRCNT2_OLDVALUE 0xf39d0080 -+#define FSTV0910_P2_ERR_CNT22 0xf39d007f -+ -+/*P2_ERRCNT21*/ -+#define RSTV0910_P2_ERRCNT21 0xf39e -+#define FSTV0910_P2_ERR_CNT21 0xf39e00ff -+ -+/*P2_ERRCNT20*/ -+#define RSTV0910_P2_ERRCNT20 0xf39f -+#define FSTV0910_P2_ERR_CNT20 0xf39f00ff -+ -+/*P2_FECSPY*/ -+#define RSTV0910_P2_FECSPY 0xf3a0 -+#define FSTV0910_P2_SPY_ENABLE 0xf3a00080 -+#define FSTV0910_P2_NO_SYNCBYTE 0xf3a00040 -+#define FSTV0910_P2_SERIAL_MODE 0xf3a00020 -+#define FSTV0910_P2_UNUSUAL_PACKET 0xf3a00010 -+#define FSTV0910_P2_BERMETER_DATAMODE 0xf3a0000c -+#define FSTV0910_P2_BERMETER_LMODE 0xf3a00002 -+#define FSTV0910_P2_BERMETER_RESET 0xf3a00001 -+ -+/*P2_FSPYCFG*/ -+#define RSTV0910_P2_FSPYCFG 0xf3a1 -+#define FSTV0910_P2_FECSPY_INPUT 0xf3a100c0 -+#define FSTV0910_P2_RST_ON_ERROR 0xf3a10020 -+#define FSTV0910_P2_ONE_SHOT 0xf3a10010 -+#define FSTV0910_P2_I2C_MODE 0xf3a1000c -+#define FSTV0910_P2_SPY_HYSTERESIS 0xf3a10003 -+ -+/*P2_FSPYDATA*/ -+#define RSTV0910_P2_FSPYDATA 0xf3a2 -+#define FSTV0910_P2_SPY_STUFFING 0xf3a20080 -+#define FSTV0910_P2_NOERROR_PKTJITTER 0xf3a20040 -+#define FSTV0910_P2_SPY_CNULLPKT 0xf3a20020 -+#define FSTV0910_P2_SPY_OUTDATA_MODE 0xf3a2001f -+ -+/*P2_FSPYOUT*/ -+#define RSTV0910_P2_FSPYOUT 0xf3a3 -+#define FSTV0910_P2_FSPY_DIRECT 0xf3a30080 -+#define FSTV0910_P2_SPY_OUTDATA_BUS 0xf3a30038 -+#define FSTV0910_P2_STUFF_MODE 0xf3a30007 -+ -+/*P2_FSTATUS*/ -+#define RSTV0910_P2_FSTATUS 0xf3a4 -+#define FSTV0910_P2_SPY_ENDSIM 0xf3a40080 -+#define FSTV0910_P2_VALID_SIM 0xf3a40040 -+#define FSTV0910_P2_FOUND_SIGNAL 0xf3a40020 -+#define FSTV0910_P2_DSS_SYNCBYTE 0xf3a40010 -+#define FSTV0910_P2_RESULT_STATE 0xf3a4000f -+ -+/*P2_FBERCPT4*/ -+#define RSTV0910_P2_FBERCPT4 0xf3a8 -+#define FSTV0910_P2_FBERMETER_CPT4 0xf3a800ff -+ -+/*P2_FBERCPT3*/ -+#define RSTV0910_P2_FBERCPT3 0xf3a9 -+#define FSTV0910_P2_FBERMETER_CPT3 0xf3a900ff -+ -+/*P2_FBERCPT2*/ -+#define RSTV0910_P2_FBERCPT2 0xf3aa -+#define FSTV0910_P2_FBERMETER_CPT2 0xf3aa00ff -+ -+/*P2_FBERCPT1*/ -+#define RSTV0910_P2_FBERCPT1 0xf3ab -+#define FSTV0910_P2_FBERMETER_CPT1 0xf3ab00ff -+ -+/*P2_FBERCPT0*/ -+#define RSTV0910_P2_FBERCPT0 0xf3ac -+#define FSTV0910_P2_FBERMETER_CPT0 0xf3ac00ff -+ -+/*P2_FBERERR2*/ -+#define RSTV0910_P2_FBERERR2 0xf3ad -+#define FSTV0910_P2_FBERMETER_ERR2 0xf3ad00ff -+ -+/*P2_FBERERR1*/ -+#define RSTV0910_P2_FBERERR1 0xf3ae -+#define FSTV0910_P2_FBERMETER_ERR1 0xf3ae00ff -+ -+/*P2_FBERERR0*/ -+#define RSTV0910_P2_FBERERR0 0xf3af -+#define FSTV0910_P2_FBERMETER_ERR0 0xf3af00ff -+ -+/*P2_FSPYBER*/ -+#define RSTV0910_P2_FSPYBER 0xf3b2 -+#define FSTV0910_P2_FSPYOBS_XORREAD 0xf3b20040 -+#define FSTV0910_P2_FSPYBER_OBSMODE 0xf3b20020 -+#define FSTV0910_P2_FSPYBER_SYNCBYTE 0xf3b20010 -+#define FSTV0910_P2_FSPYBER_UNSYNC 0xf3b20008 -+#define FSTV0910_P2_FSPYBER_CTIME 0xf3b20007 -+ -+/*P2_SFERROR*/ -+#define RSTV0910_P2_SFERROR 0xf3c1 -+#define FSTV0910_P2_SFEC_REGERR_VIT 0xf3c100ff -+ -+/*P2_SFECSTATUS*/ -+#define RSTV0910_P2_SFECSTATUS 0xf3c3 -+#define FSTV0910_P2_SFEC_ON 0xf3c30080 -+#define FSTV0910_P2_SFEC_OFF 0xf3c30040 -+#define FSTV0910_P2_LOCKEDSFEC 0xf3c30008 -+#define FSTV0910_P2_SFEC_DELOCK 0xf3c30004 -+#define FSTV0910_P2_SFEC_DEMODSEL 0xf3c30002 -+#define FSTV0910_P2_SFEC_OVFON 0xf3c30001 -+ -+/*P2_SFKDIV12*/ -+#define RSTV0910_P2_SFKDIV12 0xf3c4 -+#define FSTV0910_P2_SFECKDIV12_MAN 0xf3c40080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_12 0xf3c4007f -+ -+/*P2_SFKDIV23*/ -+#define RSTV0910_P2_SFKDIV23 0xf3c5 -+#define FSTV0910_P2_SFECKDIV23_MAN 0xf3c50080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_23 0xf3c5007f -+ -+/*P2_SFKDIV34*/ -+#define RSTV0910_P2_SFKDIV34 0xf3c6 -+#define FSTV0910_P2_SFECKDIV34_MAN 0xf3c60080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_34 0xf3c6007f -+ -+/*P2_SFKDIV56*/ -+#define RSTV0910_P2_SFKDIV56 0xf3c7 -+#define FSTV0910_P2_SFECKDIV56_MAN 0xf3c70080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_56 0xf3c7007f -+ -+/*P2_SFKDIV67*/ -+#define RSTV0910_P2_SFKDIV67 0xf3c8 -+#define FSTV0910_P2_SFECKDIV67_MAN 0xf3c80080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_67 0xf3c8007f -+ -+/*P2_SFKDIV78*/ -+#define RSTV0910_P2_SFKDIV78 0xf3c9 -+#define FSTV0910_P2_SFECKDIV78_MAN 0xf3c90080 -+#define FSTV0910_P2_SFEC_K_DIVIDER_78 0xf3c9007f -+ -+/*P2_SFSTATUS*/ -+#define RSTV0910_P2_SFSTATUS 0xf3cc -+#define FSTV0910_P2_SFEC_LINEOK 0xf3cc0080 -+#define FSTV0910_P2_SFEC_ERROR 0xf3cc0040 -+#define FSTV0910_P2_SFEC_DATA7 0xf3cc0020 -+#define FSTV0910_P2_SFEC_PKTDNBRFAIL 0xf3cc0010 -+#define FSTV0910_P2_TSSFEC_DEMODSEL 0xf3cc0008 -+#define FSTV0910_P2_SFEC_NOSYNC 0xf3cc0004 -+#define FSTV0910_P2_SFEC_UNREGULA 0xf3cc0002 -+#define FSTV0910_P2_SFEC_READY 0xf3cc0001 -+ -+/*P2_SFDLYSET2*/ -+#define RSTV0910_P2_SFDLYSET2 0xf3d0 -+#define FSTV0910_P2_SFEC_OFFSET 0xf3d000c0 -+#define FSTV0910_P2_RST_SFEC 0xf3d00008 -+#define FSTV0910_P2_DILDLINE_ERROR 0xf3d00004 -+#define FSTV0910_P2_SFEC_DISABLE 0xf3d00002 -+#define FSTV0910_P2_SFEC_UNREGUL 0xf3d00001 -+ -+/*P2_SFERRCTRL*/ -+#define RSTV0910_P2_SFERRCTRL 0xf3d8 -+#define FSTV0910_P2_SFEC_ERR_SOURCE 0xf3d800f0 -+#define FSTV0910_P2_SFEC_NUM_EVENT 0xf3d80007 -+ -+/*P2_SFERRCNT2*/ -+#define RSTV0910_P2_SFERRCNT2 0xf3d9 -+#define FSTV0910_P2_SFERRC_OLDVALUE 0xf3d90080 -+#define FSTV0910_P2_SFEC_ERR_CNT2 0xf3d9007f -+ -+/*P2_SFERRCNT1*/ -+#define RSTV0910_P2_SFERRCNT1 0xf3da -+#define FSTV0910_P2_SFEC_ERR_CNT1 0xf3da00ff -+ -+/*P2_SFERRCNT0*/ -+#define RSTV0910_P2_SFERRCNT0 0xf3db -+#define FSTV0910_P2_SFEC_ERR_CNT0 0xf3db00ff -+ -+/*P1_IQCONST*/ -+#define RSTV0910_P1_IQCONST 0xf400 -+#define FSTV0910_P1_CONSTEL_SELECT 0xf4000060 -+#define FSTV0910_P1_IQSYMB_SEL 0xf400001f -+ -+/*P1_NOSCFG*/ -+#define RSTV0910_P1_NOSCFG 0xf401 -+#define FSTV0910_P1_DIS_ACMRATIO 0xf4010080 -+#define FSTV0910_P1_NOSIN_EGALSEL 0xf4010040 -+#define FSTV0910_P1_DUMMYPL_NOSDATA 0xf4010020 -+#define FSTV0910_P1_NOSPLH_BETA 0xf4010018 -+#define FSTV0910_P1_NOSDATA_BETA 0xf4010007 -+ -+/*P1_ISYMB*/ -+#define RSTV0910_P1_ISYMB 0xf402 -+#define FSTV0910_P1_I_SYMBOL 0xf40201ff -+ -+/*P1_QSYMB*/ -+#define RSTV0910_P1_QSYMB 0xf403 -+#define FSTV0910_P1_Q_SYMBOL 0xf40301ff -+ -+/*P1_AGC1CFG*/ -+#define RSTV0910_P1_AGC1CFG 0xf404 -+#define FSTV0910_P1_DC_FROZEN 0xf4040080 -+#define FSTV0910_P1_DC_CORRECT 0xf4040040 -+#define FSTV0910_P1_AMM_FROZEN 0xf4040020 -+#define FSTV0910_P1_AMM_CORRECT 0xf4040010 -+#define FSTV0910_P1_QUAD_FROZEN 0xf4040008 -+#define FSTV0910_P1_QUAD_CORRECT 0xf4040004 -+#define FSTV0910_P1_DCCOMP_SLOW 0xf4040002 -+#define FSTV0910_P1_IQMISM_SLOW 0xf4040001 -+ -+/*P1_AGC1CN*/ -+#define RSTV0910_P1_AGC1CN 0xf406 -+#define FSTV0910_P1_AGC1_LOCKED 0xf4060080 -+#define FSTV0910_P1_AGC1_OVERFLOW 0xf4060040 -+#define FSTV0910_P1_AGC1_NOSLOWLK 0xf4060020 -+#define FSTV0910_P1_AGC1_MINPOWER 0xf4060010 -+#define FSTV0910_P1_AGCOUT_FAST 0xf4060008 -+#define FSTV0910_P1_AGCIQ_BETA 0xf4060007 -+ -+/*P1_AGC1REF*/ -+#define RSTV0910_P1_AGC1REF 0xf407 -+#define FSTV0910_P1_AGCIQ_REF 0xf40700ff -+ -+/*P1_IDCCOMP*/ -+#define RSTV0910_P1_IDCCOMP 0xf408 -+#define FSTV0910_P1_IAVERAGE_ADJ 0xf40801ff -+ -+/*P1_QDCCOMP*/ -+#define RSTV0910_P1_QDCCOMP 0xf409 -+#define FSTV0910_P1_QAVERAGE_ADJ 0xf40901ff -+ -+/*P1_POWERI*/ -+#define RSTV0910_P1_POWERI 0xf40a -+#define FSTV0910_P1_POWER_I 0xf40a00ff -+ -+/*P1_POWERQ*/ -+#define RSTV0910_P1_POWERQ 0xf40b -+#define FSTV0910_P1_POWER_Q 0xf40b00ff -+ -+/*P1_AGC1AMM*/ -+#define RSTV0910_P1_AGC1AMM 0xf40c -+#define FSTV0910_P1_AMM_VALUE 0xf40c00ff -+ -+/*P1_AGC1QUAD*/ -+#define RSTV0910_P1_AGC1QUAD 0xf40d -+#define FSTV0910_P1_QUAD_VALUE 0xf40d01ff -+ -+/*P1_AGCIQIN1*/ -+#define RSTV0910_P1_AGCIQIN1 0xf40e -+#define FSTV0910_P1_AGCIQ_VALUE1 0xf40e00ff -+ -+/*P1_AGCIQIN0*/ -+#define RSTV0910_P1_AGCIQIN0 0xf40f -+#define FSTV0910_P1_AGCIQ_VALUE0 0xf40f00ff -+ -+/*P1_DEMOD*/ -+#define RSTV0910_P1_DEMOD 0xf410 -+#define FSTV0910_P1_MANUALS2_ROLLOFF 0xf4100080 -+#define FSTV0910_P1_SPECINV_CONTROL 0xf4100030 -+#define FSTV0910_P1_MANUALSX_ROLLOFF 0xf4100004 -+#define FSTV0910_P1_ROLLOFF_CONTROL 0xf4100003 -+ -+/*P1_DMDMODCOD*/ -+#define RSTV0910_P1_DMDMODCOD 0xf411 -+#define FSTV0910_P1_MANUAL_MODCOD 0xf4110080 -+#define FSTV0910_P1_DEMOD_MODCOD 0xf411007c -+#define FSTV0910_P1_DEMOD_TYPE 0xf4110003 -+ -+/*P1_DSTATUS*/ -+#define RSTV0910_P1_DSTATUS 0xf412 -+#define FSTV0910_P1_CAR_LOCK 0xf4120080 -+#define FSTV0910_P1_TMGLOCK_QUALITY 0xf4120060 -+#define FSTV0910_P1_SDVBS1_ENABLE 0xf4120010 -+#define FSTV0910_P1_LOCK_DEFINITIF 0xf4120008 -+#define FSTV0910_P1_TIMING_IS_LOCKED 0xf4120004 -+#define FSTV0910_P1_DEMOD_SYSCFG 0xf4120002 -+#define FSTV0910_P1_OVADC_DETECT 0xf4120001 -+ -+/*P1_DSTATUS2*/ -+#define RSTV0910_P1_DSTATUS2 0xf413 -+#define FSTV0910_P1_DEMOD_DELOCK 0xf4130080 -+#define FSTV0910_P1_DEMOD_TIMEOUT 0xf4130040 -+#define FSTV0910_P1_MODCODRQ_SYNCTAG 0xf4130020 -+#define FSTV0910_P1_POLYPH_SATEVENT 0xf4130010 -+#define FSTV0910_P1_AGC1_NOSIGNALACK 0xf4130008 -+#define FSTV0910_P1_AGC2_OVERFLOW 0xf4130004 -+#define FSTV0910_P1_CFR_OVERFLOW 0xf4130002 -+#define FSTV0910_P1_GAMMA_OVERUNDER 0xf4130001 -+ -+/*P1_DMDCFGMD*/ -+#define RSTV0910_P1_DMDCFGMD 0xf414 -+#define FSTV0910_P1_DVBS2_ENABLE 0xf4140080 -+#define FSTV0910_P1_DVBS1_ENABLE 0xf4140040 -+#define FSTV0910_P1_SCAN_ENABLE 0xf4140010 -+#define FSTV0910_P1_CFR_AUTOSCAN 0xf4140008 -+#define FSTV0910_P1_NOFORCE_RELOCK 0xf4140004 -+#define FSTV0910_P1_TUN_RNG 0xf4140003 -+ -+/*P1_DMDCFG2*/ -+#define RSTV0910_P1_DMDCFG2 0xf415 -+#define FSTV0910_P1_AGC1_WAITLOCK 0xf4150080 -+#define FSTV0910_P1_S1S2_SEQUENTIAL 0xf4150040 -+#define FSTV0910_P1_BLINDPEA_MODE 0xf4150020 -+#define FSTV0910_P1_INFINITE_RELOCK 0xf4150010 -+#define FSTV0910_P1_BWOFFSET_COLDWARM 0xf4150008 -+#define FSTV0910_P1_TMGLOCK_NSCANSTOP 0xf4150004 -+#define FSTV0910_P1_COARSE_LK3MODE 0xf4150002 -+#define FSTV0910_P1_COARSE_LK2MODE 0xf4150001 -+ -+/*P1_DMDISTATE*/ -+#define RSTV0910_P1_DMDISTATE 0xf416 -+#define FSTV0910_P1_I2C_NORESETDMODE 0xf4160080 -+#define FSTV0910_P1_FORCE_ETAPED 0xf4160040 -+#define FSTV0910_P1_SDMDRST_DIRCLK 0xf4160020 -+#define FSTV0910_P1_I2C_DEMOD_MODE 0xf416001f -+ -+/*P1_DMDT0M*/ -+#define RSTV0910_P1_DMDT0M 0xf417 -+#define FSTV0910_P1_DMDT0_MIN 0xf41700ff -+ -+/*P1_DMDSTATE*/ -+#define RSTV0910_P1_DMDSTATE 0xf41b -+#define FSTV0910_P1_DEMOD_LOCKED 0xf41b0080 -+#define FSTV0910_P1_HEADER_MODE 0xf41b0060 -+#define FSTV0910_P1_DEMOD_MODE 0xf41b001f -+ -+/*P1_DMDFLYW*/ -+#define RSTV0910_P1_DMDFLYW 0xf41c -+#define FSTV0910_P1_I2C_IRQVAL 0xf41c00f0 -+#define FSTV0910_P1_FLYWHEEL_CPT 0xf41c000f -+ -+/*P1_DSTATUS3*/ -+#define RSTV0910_P1_DSTATUS3 0xf41d -+#define FSTV0910_P1_CFR_ZIGZAG 0xf41d0080 -+#define FSTV0910_P1_DEMOD_CFGMODE 0xf41d0060 -+#define FSTV0910_P1_GAMMA_LOWBAUDRATE 0xf41d0010 -+#define FSTV0910_P1_RELOCK_MODE 0xf41d0008 -+#define FSTV0910_P1_DEMOD_FAIL 0xf41d0004 -+#define FSTV0910_P1_ETAPE1A_DVBXMEM 0xf41d0003 -+ -+/*P1_DMDCFG3*/ -+#define RSTV0910_P1_DMDCFG3 0xf41e -+#define FSTV0910_P1_DVBS1_TMGWAIT 0xf41e0080 -+#define FSTV0910_P1_NO_BWCENTERING 0xf41e0040 -+#define FSTV0910_P1_INV_SEQSRCH 0xf41e0020 -+#define FSTV0910_P1_DIS_SFRUPLOW_TRK 0xf41e0010 -+#define FSTV0910_P1_NOSTOP_FIFOFULL 0xf41e0008 -+#define FSTV0910_P1_LOCKTIME_MODE 0xf41e0007 -+ -+/*P1_DMDCFG4*/ -+#define RSTV0910_P1_DMDCFG4 0xf41f -+#define FSTV0910_P1_DIS_VITLOCK 0xf41f0080 -+#define FSTV0910_P1_S1S2TOUT_FAST 0xf41f0040 -+#define FSTV0910_P1_DEMOD_FASTLOCK 0xf41f0020 -+#define FSTV0910_P1_S1HIER_ENABLE 0xf41f0010 -+#define FSTV0910_P1_TUNER_NRELAUNCH 0xf41f0008 -+#define FSTV0910_P1_DIS_CLKENABLE 0xf41f0004 -+#define FSTV0910_P1_DIS_HDRDIVLOCK 0xf41f0002 -+#define FSTV0910_P1_NO_TNRWBINIT 0xf41f0001 -+ -+/*P1_CORRELMANT*/ -+#define RSTV0910_P1_CORRELMANT 0xf420 -+#define FSTV0910_P1_CORREL_MANT 0xf42000ff -+ -+/*P1_CORRELABS*/ -+#define RSTV0910_P1_CORRELABS 0xf421 -+#define FSTV0910_P1_CORREL_ABS 0xf42100ff -+ -+/*P1_CORRELEXP*/ -+#define RSTV0910_P1_CORRELEXP 0xf422 -+#define FSTV0910_P1_CORREL_ABSEXP 0xf42200f0 -+#define FSTV0910_P1_CORREL_EXP 0xf422000f -+ -+/*P1_PLHMODCOD*/ -+#define RSTV0910_P1_PLHMODCOD 0xf424 -+#define FSTV0910_P1_SPECINV_DEMOD 0xf4240080 -+#define FSTV0910_P1_PLH_MODCOD 0xf424007c -+#define FSTV0910_P1_PLH_TYPE 0xf4240003 -+ -+/*P1_DMDREG*/ -+#define RSTV0910_P1_DMDREG 0xf425 -+#define FSTV0910_P1_EXTPSK_MODE 0xf4250080 -+#define FSTV0910_P1_HIER_SHORTFRAME 0xf4250002 -+#define FSTV0910_P1_DECIM_PLFRAMES 0xf4250001 -+ -+/*P1_AGC2O*/ -+#define RSTV0910_P1_AGC2O 0xf42c -+#define FSTV0910_P1_CSTENV_MODE 0xf42c00c0 -+#define FSTV0910_P1_AGC2_LKSQRT 0xf42c0020 -+#define FSTV0910_P1_AGC2_LKMODE 0xf42c0010 -+#define FSTV0910_P1_AGC2_LKEQUA 0xf42c0008 -+#define FSTV0910_P1_AGC2_COEF 0xf42c0007 -+ -+/*P1_AGC2REF*/ -+#define RSTV0910_P1_AGC2REF 0xf42d -+#define FSTV0910_P1_AGC2_REF 0xf42d00ff -+ -+/*P1_AGC1ADJ*/ -+#define RSTV0910_P1_AGC1ADJ 0xf42e -+#define FSTV0910_P1_AGC1ADJ_MANUAL 0xf42e0080 -+#define FSTV0910_P1_AGC1_ADJUSTED 0xf42e007f -+ -+/*P1_AGC2I1*/ -+#define RSTV0910_P1_AGC2I1 0xf436 -+#define FSTV0910_P1_AGC2_INTEGRATOR1 0xf43600ff -+ -+/*P1_AGC2I0*/ -+#define RSTV0910_P1_AGC2I0 0xf437 -+#define FSTV0910_P1_AGC2_INTEGRATOR0 0xf43700ff -+ -+/*P1_CARCFG*/ -+#define RSTV0910_P1_CARCFG 0xf438 -+#define FSTV0910_P1_CFRUPLOW_AUTO 0xf4380080 -+#define FSTV0910_P1_CFRUPLOW_TEST 0xf4380040 -+#define FSTV0910_P1_WIDE_FREQDET 0xf4380020 -+#define FSTV0910_P1_CARHDR_NODIV8 0xf4380010 -+#define FSTV0910_P1_I2C_ROTA 0xf4380008 -+#define FSTV0910_P1_ROTAON 0xf4380004 -+#define FSTV0910_P1_PH_DET_ALGO 0xf4380003 -+ -+/*P1_ACLC*/ -+#define RSTV0910_P1_ACLC 0xf439 -+#define FSTV0910_P1_CARS1_ANOSAUTO 0xf4390040 -+#define FSTV0910_P1_CAR_ALPHA_MANT 0xf4390030 -+#define FSTV0910_P1_CAR_ALPHA_EXP 0xf439000f -+ -+/*P1_BCLC*/ -+#define RSTV0910_P1_BCLC 0xf43a -+#define FSTV0910_P1_CARS1_BNOSAUTO 0xf43a0040 -+#define FSTV0910_P1_CAR_BETA_MANT 0xf43a0030 -+#define FSTV0910_P1_CAR_BETA_EXP 0xf43a000f -+ -+/*P1_CARFREQ*/ -+#define RSTV0910_P1_CARFREQ 0xf43d -+#define FSTV0910_P1_KC_COARSE_EXP 0xf43d00f0 -+#define FSTV0910_P1_BETA_FREQ 0xf43d000f -+ -+/*P1_CARHDR*/ -+#define RSTV0910_P1_CARHDR 0xf43e -+#define FSTV0910_P1_K_FREQ_HDR 0xf43e00ff -+ -+/*P1_LDT*/ -+#define RSTV0910_P1_LDT 0xf43f -+#define FSTV0910_P1_CARLOCK_THRES 0xf43f01ff -+ -+/*P1_LDT2*/ -+#define RSTV0910_P1_LDT2 0xf440 -+#define FSTV0910_P1_CARLOCK_THRES2 0xf44001ff -+ -+/*P1_CFRICFG*/ -+#define RSTV0910_P1_CFRICFG 0xf441 -+#define FSTV0910_P1_CFRINIT_UNVALRNG 0xf4410080 -+#define FSTV0910_P1_CFRINIT_LUNVALCPT 0xf4410040 -+#define FSTV0910_P1_CFRINIT_ABORTDBL 0xf4410020 -+#define FSTV0910_P1_CFRINIT_ABORTPRED 0xf4410010 -+#define FSTV0910_P1_CFRINIT_UNVALSKIP 0xf4410008 -+#define FSTV0910_P1_CFRINIT_CSTINC 0xf4410004 -+#define FSTV0910_P1_CFRIROLL_GARDER 0xf4410002 -+#define FSTV0910_P1_NEG_CFRSTEP 0xf4410001 -+ -+/*P1_CFRUP1*/ -+#define RSTV0910_P1_CFRUP1 0xf442 -+#define FSTV0910_P1_CFR_UP1 0xf44201ff -+ -+/*P1_CFRUP0*/ -+#define RSTV0910_P1_CFRUP0 0xf443 -+#define FSTV0910_P1_CFR_UP0 0xf44300ff -+ -+/*P1_CFRIBASE1*/ -+#define RSTV0910_P1_CFRIBASE1 0xf444 -+#define FSTV0910_P1_CFRINIT_BASE1 0xf44400ff -+ -+/*P1_CFRIBASE0*/ -+#define RSTV0910_P1_CFRIBASE0 0xf445 -+#define FSTV0910_P1_CFRINIT_BASE0 0xf44500ff -+ -+/*P1_CFRLOW1*/ -+#define RSTV0910_P1_CFRLOW1 0xf446 -+#define FSTV0910_P1_CFR_LOW1 0xf44601ff -+ -+/*P1_CFRLOW0*/ -+#define RSTV0910_P1_CFRLOW0 0xf447 -+#define FSTV0910_P1_CFR_LOW0 0xf44700ff -+ -+/*P1_CFRINIT1*/ -+#define RSTV0910_P1_CFRINIT1 0xf448 -+#define FSTV0910_P1_CFR_INIT1 0xf44801ff -+ -+/*P1_CFRINIT0*/ -+#define RSTV0910_P1_CFRINIT0 0xf449 -+#define FSTV0910_P1_CFR_INIT0 0xf44900ff -+ -+/*P1_CFRINC1*/ -+#define RSTV0910_P1_CFRINC1 0xf44a -+#define FSTV0910_P1_MANUAL_CFRINC 0xf44a0080 -+#define FSTV0910_P1_CFR_INC1 0xf44a003f -+ -+/*P1_CFRINC0*/ -+#define RSTV0910_P1_CFRINC0 0xf44b -+#define FSTV0910_P1_CFR_INC0 0xf44b00ff -+ -+/*P1_CFR2*/ -+#define RSTV0910_P1_CFR2 0xf44c -+#define FSTV0910_P1_CAR_FREQ2 0xf44c01ff -+ -+/*P1_CFR1*/ -+#define RSTV0910_P1_CFR1 0xf44d -+#define FSTV0910_P1_CAR_FREQ1 0xf44d00ff -+ -+/*P1_CFR0*/ -+#define RSTV0910_P1_CFR0 0xf44e -+#define FSTV0910_P1_CAR_FREQ0 0xf44e00ff -+ -+/*P1_LDI*/ -+#define RSTV0910_P1_LDI 0xf44f -+#define FSTV0910_P1_LOCK_DET_INTEGR 0xf44f01ff -+ -+/*P1_TMGCFG*/ -+#define RSTV0910_P1_TMGCFG 0xf450 -+#define FSTV0910_P1_TMGLOCK_BETA 0xf45000c0 -+#define FSTV0910_P1_DO_TIMING_CORR 0xf4500010 -+#define FSTV0910_P1_MANUAL_SCAN 0xf450000c -+#define FSTV0910_P1_TMG_MINFREQ 0xf4500003 -+ -+/*P1_RTC*/ -+#define RSTV0910_P1_RTC 0xf451 -+#define FSTV0910_P1_TMGALPHA_EXP 0xf45100f0 -+#define FSTV0910_P1_TMGBETA_EXP 0xf451000f -+ -+/*P1_RTCS2*/ -+#define RSTV0910_P1_RTCS2 0xf452 -+#define FSTV0910_P1_TMGALPHAS2_EXP 0xf45200f0 -+#define FSTV0910_P1_TMGBETAS2_EXP 0xf452000f -+ -+/*P1_TMGTHRISE*/ -+#define RSTV0910_P1_TMGTHRISE 0xf453 -+#define FSTV0910_P1_TMGLOCK_THRISE 0xf45300ff -+ -+/*P1_TMGTHFALL*/ -+#define RSTV0910_P1_TMGTHFALL 0xf454 -+#define FSTV0910_P1_TMGLOCK_THFALL 0xf45400ff -+ -+/*P1_SFRUPRATIO*/ -+#define RSTV0910_P1_SFRUPRATIO 0xf455 -+#define FSTV0910_P1_SFR_UPRATIO 0xf45500ff -+ -+/*P1_SFRLOWRATIO*/ -+#define RSTV0910_P1_SFRLOWRATIO 0xf456 -+#define FSTV0910_P1_SFR_LOWRATIO 0xf45600ff -+ -+/*P1_KTTMG*/ -+#define RSTV0910_P1_KTTMG 0xf457 -+#define FSTV0910_P1_KT_TMG_EXP 0xf45700f0 -+ -+/*P1_KREFTMG*/ -+#define RSTV0910_P1_KREFTMG 0xf458 -+#define FSTV0910_P1_KREF_TMG 0xf45800ff -+ -+/*P1_SFRSTEP*/ -+#define RSTV0910_P1_SFRSTEP 0xf459 -+#define FSTV0910_P1_SFR_SCANSTEP 0xf45900f0 -+#define FSTV0910_P1_SFR_CENTERSTEP 0xf459000f -+ -+/*P1_TMGCFG2*/ -+#define RSTV0910_P1_TMGCFG2 0xf45a -+#define FSTV0910_P1_KREFTMG2_DECMODE 0xf45a00c0 -+#define FSTV0910_P1_DIS_AUTOSAMP 0xf45a0008 -+#define FSTV0910_P1_SCANINIT_QUART 0xf45a0004 -+#define FSTV0910_P1_NOTMG_DVBS1DERAT 0xf45a0002 -+#define FSTV0910_P1_SFRRATIO_FINE 0xf45a0001 -+ -+/*P1_KREFTMG2*/ -+#define RSTV0910_P1_KREFTMG2 0xf45b -+#define FSTV0910_P1_KREF_TMG2 0xf45b00ff -+ -+/*P1_TMGCFG3*/ -+#define RSTV0910_P1_TMGCFG3 0xf45d -+#define FSTV0910_P1_CFRINC_MODE 0xf45d0070 -+#define FSTV0910_P1_CONT_TMGCENTER 0xf45d0008 -+#define FSTV0910_P1_AUTO_GUP 0xf45d0004 -+#define FSTV0910_P1_AUTO_GLOW 0xf45d0002 -+#define FSTV0910_P1_SFRVAL_MINMODE 0xf45d0001 -+ -+/*P1_SFRINIT1*/ -+#define RSTV0910_P1_SFRINIT1 0xf45e -+#define FSTV0910_P1_SFR_INIT1 0xf45e00ff -+ -+/*P1_SFRINIT0*/ -+#define RSTV0910_P1_SFRINIT0 0xf45f -+#define FSTV0910_P1_SFR_INIT0 0xf45f00ff -+ -+/*P1_SFRUP1*/ -+#define RSTV0910_P1_SFRUP1 0xf460 -+#define FSTV0910_P1_SYMB_FREQ_UP1 0xf46000ff -+ -+/*P1_SFRUP0*/ -+#define RSTV0910_P1_SFRUP0 0xf461 -+#define FSTV0910_P1_SYMB_FREQ_UP0 0xf46100ff -+ -+/*P1_SFRLOW1*/ -+#define RSTV0910_P1_SFRLOW1 0xf462 -+#define FSTV0910_P1_SYMB_FREQ_LOW1 0xf46200ff -+ -+/*P1_SFRLOW0*/ -+#define RSTV0910_P1_SFRLOW0 0xf463 -+#define FSTV0910_P1_SYMB_FREQ_LOW0 0xf46300ff -+ -+/*P1_SFR3*/ -+#define RSTV0910_P1_SFR3 0xf464 -+#define FSTV0910_P1_SYMB_FREQ3 0xf46400ff -+ -+/*P1_SFR2*/ -+#define RSTV0910_P1_SFR2 0xf465 -+#define FSTV0910_P1_SYMB_FREQ2 0xf46500ff -+ -+/*P1_SFR1*/ -+#define RSTV0910_P1_SFR1 0xf466 -+#define FSTV0910_P1_SYMB_FREQ1 0xf46600ff -+ -+/*P1_SFR0*/ -+#define RSTV0910_P1_SFR0 0xf467 -+#define FSTV0910_P1_SYMB_FREQ0 0xf46700ff -+ -+/*P1_TMGREG2*/ -+#define RSTV0910_P1_TMGREG2 0xf468 -+#define FSTV0910_P1_TMGREG2 0xf46800ff -+ -+/*P1_TMGREG1*/ -+#define RSTV0910_P1_TMGREG1 0xf469 -+#define FSTV0910_P1_TMGREG1 0xf46900ff -+ -+/*P1_TMGREG0*/ -+#define RSTV0910_P1_TMGREG0 0xf46a -+#define FSTV0910_P1_TMGREG0 0xf46a00ff -+ -+/*P1_TMGLOCK1*/ -+#define RSTV0910_P1_TMGLOCK1 0xf46b -+#define FSTV0910_P1_TMGLOCK_LEVEL1 0xf46b01ff -+ -+/*P1_TMGLOCK0*/ -+#define RSTV0910_P1_TMGLOCK0 0xf46c -+#define FSTV0910_P1_TMGLOCK_LEVEL0 0xf46c00ff -+ -+/*P1_TMGOBS*/ -+#define RSTV0910_P1_TMGOBS 0xf46d -+#define FSTV0910_P1_ROLLOFF_STATUS 0xf46d00c0 -+#define FSTV0910_P1_SCAN_SIGN 0xf46d0030 -+#define FSTV0910_P1_TMG_SCANNING 0xf46d0008 -+#define FSTV0910_P1_CHCENTERING_MODE 0xf46d0004 -+#define FSTV0910_P1_TMG_SCANFAIL 0xf46d0002 -+ -+/*P1_EQUALCFG*/ -+#define RSTV0910_P1_EQUALCFG 0xf46f -+#define FSTV0910_P1_NOTMG_NEGALWAIT 0xf46f0080 -+#define FSTV0910_P1_EQUAL_ON 0xf46f0040 -+#define FSTV0910_P1_SEL_EQUALCOR 0xf46f0038 -+#define FSTV0910_P1_MU_EQUALDFE 0xf46f0007 -+ -+/*P1_EQUAI1*/ -+#define RSTV0910_P1_EQUAI1 0xf470 -+#define FSTV0910_P1_EQUA_ACCI1 0xf47001ff -+ -+/*P1_EQUAQ1*/ -+#define RSTV0910_P1_EQUAQ1 0xf471 -+#define FSTV0910_P1_EQUA_ACCQ1 0xf47101ff -+ -+/*P1_EQUAI2*/ -+#define RSTV0910_P1_EQUAI2 0xf472 -+#define FSTV0910_P1_EQUA_ACCI2 0xf47201ff -+ -+/*P1_EQUAQ2*/ -+#define RSTV0910_P1_EQUAQ2 0xf473 -+#define FSTV0910_P1_EQUA_ACCQ2 0xf47301ff -+ -+/*P1_EQUAI3*/ -+#define RSTV0910_P1_EQUAI3 0xf474 -+#define FSTV0910_P1_EQUA_ACCI3 0xf47401ff -+ -+/*P1_EQUAQ3*/ -+#define RSTV0910_P1_EQUAQ3 0xf475 -+#define FSTV0910_P1_EQUA_ACCQ3 0xf47501ff -+ -+/*P1_EQUAI4*/ -+#define RSTV0910_P1_EQUAI4 0xf476 -+#define FSTV0910_P1_EQUA_ACCI4 0xf47601ff -+ -+/*P1_EQUAQ4*/ -+#define RSTV0910_P1_EQUAQ4 0xf477 -+#define FSTV0910_P1_EQUA_ACCQ4 0xf47701ff -+ -+/*P1_EQUAI5*/ -+#define RSTV0910_P1_EQUAI5 0xf478 -+#define FSTV0910_P1_EQUA_ACCI5 0xf47801ff -+ -+/*P1_EQUAQ5*/ -+#define RSTV0910_P1_EQUAQ5 0xf479 -+#define FSTV0910_P1_EQUA_ACCQ5 0xf47901ff -+ -+/*P1_EQUAI6*/ -+#define RSTV0910_P1_EQUAI6 0xf47a -+#define FSTV0910_P1_EQUA_ACCI6 0xf47a01ff -+ -+/*P1_EQUAQ6*/ -+#define RSTV0910_P1_EQUAQ6 0xf47b -+#define FSTV0910_P1_EQUA_ACCQ6 0xf47b01ff -+ -+/*P1_EQUAI7*/ -+#define RSTV0910_P1_EQUAI7 0xf47c -+#define FSTV0910_P1_EQUA_ACCI7 0xf47c01ff -+ -+/*P1_EQUAQ7*/ -+#define RSTV0910_P1_EQUAQ7 0xf47d -+#define FSTV0910_P1_EQUA_ACCQ7 0xf47d01ff -+ -+/*P1_EQUAI8*/ -+#define RSTV0910_P1_EQUAI8 0xf47e -+#define FSTV0910_P1_EQUA_ACCI8 0xf47e01ff -+ -+/*P1_EQUAQ8*/ -+#define RSTV0910_P1_EQUAQ8 0xf47f -+#define FSTV0910_P1_EQUA_ACCQ8 0xf47f01ff -+ -+/*P1_NNOSDATAT1*/ -+#define RSTV0910_P1_NNOSDATAT1 0xf480 -+#define FSTV0910_P1_NOSDATAT_NORMED1 0xf48000ff -+ -+/*P1_NNOSDATAT0*/ -+#define RSTV0910_P1_NNOSDATAT0 0xf481 -+#define FSTV0910_P1_NOSDATAT_NORMED0 0xf48100ff -+ -+/*P1_NNOSDATA1*/ -+#define RSTV0910_P1_NNOSDATA1 0xf482 -+#define FSTV0910_P1_NOSDATA_NORMED1 0xf48200ff -+ -+/*P1_NNOSDATA0*/ -+#define RSTV0910_P1_NNOSDATA0 0xf483 -+#define FSTV0910_P1_NOSDATA_NORMED0 0xf48300ff -+ -+/*P1_NNOSPLHT1*/ -+#define RSTV0910_P1_NNOSPLHT1 0xf484 -+#define FSTV0910_P1_NOSPLHT_NORMED1 0xf48400ff -+ -+/*P1_NNOSPLHT0*/ -+#define RSTV0910_P1_NNOSPLHT0 0xf485 -+#define FSTV0910_P1_NOSPLHT_NORMED0 0xf48500ff -+ -+/*P1_NNOSPLH1*/ -+#define RSTV0910_P1_NNOSPLH1 0xf486 -+#define FSTV0910_P1_NOSPLH_NORMED1 0xf48600ff -+ -+/*P1_NNOSPLH0*/ -+#define RSTV0910_P1_NNOSPLH0 0xf487 -+#define FSTV0910_P1_NOSPLH_NORMED0 0xf48700ff -+ -+/*P1_NOSDATAT1*/ -+#define RSTV0910_P1_NOSDATAT1 0xf488 -+#define FSTV0910_P1_NOSDATAT_UNNORMED1 0xf48800ff -+ -+/*P1_NOSDATAT0*/ -+#define RSTV0910_P1_NOSDATAT0 0xf489 -+#define FSTV0910_P1_NOSDATAT_UNNORMED0 0xf48900ff -+ -+/*P1_NNOSFRAME1*/ -+#define RSTV0910_P1_NNOSFRAME1 0xf48a -+#define FSTV0910_P1_NOSFRAME_NORMED1 0xf48a00ff -+ -+/*P1_NNOSFRAME0*/ -+#define RSTV0910_P1_NNOSFRAME0 0xf48b -+#define FSTV0910_P1_NOSFRAME_NORMED0 0xf48b00ff -+ -+/*P1_NNOSRAD1*/ -+#define RSTV0910_P1_NNOSRAD1 0xf48c -+#define FSTV0910_P1_NOSRADIAL_NORMED1 0xf48c00ff -+ -+/*P1_NNOSRAD0*/ -+#define RSTV0910_P1_NNOSRAD0 0xf48d -+#define FSTV0910_P1_NOSRADIAL_NORMED0 0xf48d00ff -+ -+/*P1_NOSCFGF1*/ -+#define RSTV0910_P1_NOSCFGF1 0xf48e -+#define FSTV0910_P1_LOWNOISE_MESURE 0xf48e0080 -+#define FSTV0910_P1_NOS_DELFRAME 0xf48e0040 -+#define FSTV0910_P1_NOSDATA_MODE 0xf48e0030 -+#define FSTV0910_P1_FRAMESEL_TYPESEL 0xf48e000c -+#define FSTV0910_P1_FRAMESEL_TYPE 0xf48e0003 -+ -+/*P1_CAR2CFG*/ -+#define RSTV0910_P1_CAR2CFG 0xf490 -+#define FSTV0910_P1_DESCRAMB_OFF 0xf4900080 -+#define FSTV0910_P1_EN_PHNOSRAM 0xf4900020 -+#define FSTV0910_P1_STOP_CFR2UPDATE 0xf4900010 -+#define FSTV0910_P1_STOP_NCO2UPDATE 0xf4900008 -+#define FSTV0910_P1_ROTA2ON 0xf4900004 -+#define FSTV0910_P1_PH_DET_ALGO2 0xf4900003 -+ -+/*P1_CFR2CFR1*/ -+#define RSTV0910_P1_CFR2CFR1 0xf491 -+#define FSTV0910_P1_CFR2_S2CONTROL 0xf49100c0 -+#define FSTV0910_P1_EN_S2CAR2CENTER 0xf4910020 -+#define FSTV0910_P1_BCHERRCFR2_MODE 0xf4910018 -+#define FSTV0910_P1_CFR2TOCFR1_BETA 0xf4910007 -+ -+/*P1_CAR3CFG*/ -+#define RSTV0910_P1_CAR3CFG 0xf492 -+#define FSTV0910_P1_CARRIER23_MODE 0xf49200c0 -+#define FSTV0910_P1_CAR3INTERM_DVBS1 0xf4920020 -+#define FSTV0910_P1_ABAMPLIF_MODE 0xf4920018 -+#define FSTV0910_P1_CARRIER3_ALPHA3DL 0xf4920007 -+ -+/*P1_CFR22*/ -+#define RSTV0910_P1_CFR22 0xf493 -+#define FSTV0910_P1_CAR2_FREQ2 0xf49301ff -+ -+/*P1_CFR21*/ -+#define RSTV0910_P1_CFR21 0xf494 -+#define FSTV0910_P1_CAR2_FREQ1 0xf49400ff -+ -+/*P1_CFR20*/ -+#define RSTV0910_P1_CFR20 0xf495 -+#define FSTV0910_P1_CAR2_FREQ0 0xf49500ff -+ -+/*P1_ACLC2S2Q*/ -+#define RSTV0910_P1_ACLC2S2Q 0xf497 -+#define FSTV0910_P1_ENAB_SPSKSYMB 0xf4970080 -+#define FSTV0910_P1_CAR2S2_QANOSAUTO 0xf4970040 -+#define FSTV0910_P1_CAR2S2_Q_ALPH_M 0xf4970030 -+#define FSTV0910_P1_CAR2S2_Q_ALPH_E 0xf497000f -+ -+/*P1_ACLC2S28*/ -+#define RSTV0910_P1_ACLC2S28 0xf498 -+#define FSTV0910_P1_OLDI3Q_MODE 0xf4980080 -+#define FSTV0910_P1_CAR2S2_8ANOSAUTO 0xf4980040 -+#define FSTV0910_P1_CAR2S2_8_ALPH_M 0xf4980030 -+#define FSTV0910_P1_CAR2S2_8_ALPH_E 0xf498000f -+ -+/*P1_ACLC2S216A*/ -+#define RSTV0910_P1_ACLC2S216A 0xf499 -+#define FSTV0910_P1_CAR2S2_16ANOSAUTO 0xf4990040 -+#define FSTV0910_P1_CAR2S2_16A_ALPH_M 0xf4990030 -+#define FSTV0910_P1_CAR2S2_16A_ALPH_E 0xf499000f -+ -+/*P1_ACLC2S232A*/ -+#define RSTV0910_P1_ACLC2S232A 0xf49a -+#define FSTV0910_P1_CAR2S2_32ANOSUATO 0xf49a0040 -+#define FSTV0910_P1_CAR2S2_32A_ALPH_M 0xf49a0030 -+#define FSTV0910_P1_CAR2S2_32A_ALPH_E 0xf49a000f -+ -+/*P1_BCLC2S2Q*/ -+#define RSTV0910_P1_BCLC2S2Q 0xf49c -+#define FSTV0910_P1_DVBS2S2Q_NIP 0xf49c0080 -+#define FSTV0910_P1_CAR2S2_QBNOSAUTO 0xf49c0040 -+#define FSTV0910_P1_CAR2S2_Q_BETA_M 0xf49c0030 -+#define FSTV0910_P1_CAR2S2_Q_BETA_E 0xf49c000f -+ -+/*P1_BCLC2S28*/ -+#define RSTV0910_P1_BCLC2S28 0xf49d -+#define FSTV0910_P1_DVBS2S28_NIP 0xf49d0080 -+#define FSTV0910_P1_CAR2S2_8BNOSAUTO 0xf49d0040 -+#define FSTV0910_P1_CAR2S2_8_BETA_M 0xf49d0030 -+#define FSTV0910_P1_CAR2S2_8_BETA_E 0xf49d000f -+ -+/*P1_PLROOT2*/ -+#define RSTV0910_P1_PLROOT2 0xf4ac -+#define FSTV0910_P1_PLHAUTO_DISPLH 0xf4ac0040 -+#define FSTV0910_P1_PLHAUTO_FASTMODE 0xf4ac0020 -+#define FSTV0910_P1_PLHAUTO_ENABLE 0xf4ac0010 -+#define FSTV0910_P1_PLSCRAMB_MODE 0xf4ac000c -+#define FSTV0910_P1_PLSCRAMB_ROOT2 0xf4ac0003 -+ -+/*P1_PLROOT1*/ -+#define RSTV0910_P1_PLROOT1 0xf4ad -+#define FSTV0910_P1_PLSCRAMB_ROOT1 0xf4ad00ff -+ -+/*P1_PLROOT0*/ -+#define RSTV0910_P1_PLROOT0 0xf4ae -+#define FSTV0910_P1_PLSCRAMB_ROOT0 0xf4ae00ff -+ -+/*P1_MODCODLST7*/ -+#define RSTV0910_P1_MODCODLST7 0xf4b7 -+#define FSTV0910_P1_MODCOD_NNOSFILTER 0xf4b70080 -+#define FSTV0910_P1_MODCODLST_NOSTYPE 0xf4b70040 -+#define FSTV0910_P1_DIS_8PSK_9_10 0xf4b70030 -+#define FSTV0910_P1_DIS_8P_8_9 0xf4b7000f -+ -+/*P1_MODCODLST8*/ -+#define RSTV0910_P1_MODCODLST8 0xf4b8 -+#define FSTV0910_P1_DIS_8P_5_6 0xf4b800f0 -+#define FSTV0910_P1_DIS_8P_3_4 0xf4b8000f -+ -+/*P1_MODCODLST9*/ -+#define RSTV0910_P1_MODCODLST9 0xf4b9 -+#define FSTV0910_P1_DIS_8P_2_3 0xf4b900f0 -+#define FSTV0910_P1_DIS_8P_3_5 0xf4b9000f -+ -+/*P1_MODCODLSTA*/ -+#define RSTV0910_P1_MODCODLSTA 0xf4ba -+#define FSTV0910_P1_NOSFILTER_LIMITE 0xf4ba0080 -+#define FSTV0910_P1_NOSFILTER_MODE 0xf4ba0040 -+#define FSTV0910_P1_DIS_QPSK_9_10 0xf4ba0030 -+#define FSTV0910_P1_DIS_QP_8_9 0xf4ba000f -+ -+/*P1_MODCODLSTB*/ -+#define RSTV0910_P1_MODCODLSTB 0xf4bb -+#define FSTV0910_P1_DIS_QP_5_6 0xf4bb00f0 -+#define FSTV0910_P1_DIS_QP_4_5 0xf4bb000f -+ -+/*P1_MODCODLSTC*/ -+#define RSTV0910_P1_MODCODLSTC 0xf4bc -+#define FSTV0910_P1_DIS_QP_3_4 0xf4bc00f0 -+#define FSTV0910_P1_DIS_QP_2_3 0xf4bc000f -+ -+/*P1_MODCODLSTD*/ -+#define RSTV0910_P1_MODCODLSTD 0xf4bd -+#define FSTV0910_P1_DIS_QPSK_3_5 0xf4bd00f0 -+#define FSTV0910_P1_DIS_QPSK_1_2 0xf4bd000f -+ -+/*P1_GAUSSR0*/ -+#define RSTV0910_P1_GAUSSR0 0xf4c0 -+#define FSTV0910_P1_EN_CCIMODE 0xf4c00080 -+#define FSTV0910_P1_R0_GAUSSIEN 0xf4c0007f -+ -+/*P1_CCIR0*/ -+#define RSTV0910_P1_CCIR0 0xf4c1 -+#define FSTV0910_P1_CCIDETECT_PLHONLY 0xf4c10080 -+#define FSTV0910_P1_R0_CCI 0xf4c1007f -+ -+/*P1_CCIQUANT*/ -+#define RSTV0910_P1_CCIQUANT 0xf4c2 -+#define FSTV0910_P1_CCI_BETA 0xf4c200e0 -+#define FSTV0910_P1_CCI_QUANT 0xf4c2001f -+ -+/*P1_CCITHRES*/ -+#define RSTV0910_P1_CCITHRES 0xf4c3 -+#define FSTV0910_P1_CCI_THRESHOLD 0xf4c300ff -+ -+/*P1_CCIACC*/ -+#define RSTV0910_P1_CCIACC 0xf4c4 -+#define FSTV0910_P1_CCI_VALUE 0xf4c400ff -+ -+/*P1_DSTATUS4*/ -+#define RSTV0910_P1_DSTATUS4 0xf4c5 -+#define FSTV0910_P1_RAINFADE_DETECT 0xf4c50080 -+#define FSTV0910_P1_NOTHRES2_FAIL 0xf4c50040 -+#define FSTV0910_P1_NOTHRES1_FAIL 0xf4c50020 -+#define FSTV0910_P1_PILOT_FAILDETECT 0xf4c50010 -+#define FSTV0910_P1_HIER_DETECT 0xf4c50008 -+#define FSTV0910_P1_DMDPROG_ERROR 0xf4c50004 -+#define FSTV0910_P1_CSTENV_DETECT 0xf4c50002 -+#define FSTV0910_P1_DETECTION_TRIAX 0xf4c50001 -+ -+/*P1_DMDRESCFG*/ -+#define RSTV0910_P1_DMDRESCFG 0xf4c6 -+#define FSTV0910_P1_DMDRES_RESET 0xf4c60080 -+#define FSTV0910_P1_DMDRES_NOISESQR 0xf4c60010 -+#define FSTV0910_P1_DMDRES_STRALL 0xf4c60008 -+#define FSTV0910_P1_DMDRES_NEWONLY 0xf4c60004 -+#define FSTV0910_P1_DMDRES_NOSTORE 0xf4c60002 -+#define FSTV0910_P1_DMDRES_AGC2MEM 0xf4c60001 -+ -+/*P1_DMDRESADR*/ -+#define RSTV0910_P1_DMDRESADR 0xf4c7 -+#define FSTV0910_P1_SUSP_PREDCANAL 0xf4c70080 -+#define FSTV0910_P1_DMDRES_VALIDCFR 0xf4c70040 -+#define FSTV0910_P1_DMDRES_MEMFULL 0xf4c70030 -+#define FSTV0910_P1_DMDRES_RESNBR 0xf4c7000f -+ -+/*P1_DMDRESDATA7*/ -+#define RSTV0910_P1_DMDRESDATA7 0xf4c8 -+#define FSTV0910_P1_DMDRES_DATA7 0xf4c800ff -+ -+/*P1_DMDRESDATA6*/ -+#define RSTV0910_P1_DMDRESDATA6 0xf4c9 -+#define FSTV0910_P1_DMDRES_DATA6 0xf4c900ff -+ -+/*P1_DMDRESDATA5*/ -+#define RSTV0910_P1_DMDRESDATA5 0xf4ca -+#define FSTV0910_P1_DMDRES_DATA5 0xf4ca00ff -+ -+/*P1_DMDRESDATA4*/ -+#define RSTV0910_P1_DMDRESDATA4 0xf4cb -+#define FSTV0910_P1_DMDRES_DATA4 0xf4cb00ff -+ -+/*P1_DMDRESDATA3*/ -+#define RSTV0910_P1_DMDRESDATA3 0xf4cc -+#define FSTV0910_P1_DMDRES_DATA3 0xf4cc00ff -+ -+/*P1_DMDRESDATA2*/ -+#define RSTV0910_P1_DMDRESDATA2 0xf4cd -+#define FSTV0910_P1_DMDRES_DATA2 0xf4cd00ff -+ -+/*P1_DMDRESDATA1*/ -+#define RSTV0910_P1_DMDRESDATA1 0xf4ce -+#define FSTV0910_P1_DMDRES_DATA1 0xf4ce00ff -+ -+/*P1_DMDRESDATA0*/ -+#define RSTV0910_P1_DMDRESDATA0 0xf4cf -+#define FSTV0910_P1_DMDRES_DATA0 0xf4cf00ff -+ -+/*P1_FFEI1*/ -+#define RSTV0910_P1_FFEI1 0xf4d0 -+#define FSTV0910_P1_FFE_ACCI1 0xf4d001ff -+ -+/*P1_FFEQ1*/ -+#define RSTV0910_P1_FFEQ1 0xf4d1 -+#define FSTV0910_P1_FFE_ACCQ1 0xf4d101ff -+ -+/*P1_FFEI2*/ -+#define RSTV0910_P1_FFEI2 0xf4d2 -+#define FSTV0910_P1_FFE_ACCI2 0xf4d201ff -+ -+/*P1_FFEQ2*/ -+#define RSTV0910_P1_FFEQ2 0xf4d3 -+#define FSTV0910_P1_FFE_ACCQ2 0xf4d301ff -+ -+/*P1_FFEI3*/ -+#define RSTV0910_P1_FFEI3 0xf4d4 -+#define FSTV0910_P1_FFE_ACCI3 0xf4d401ff -+ -+/*P1_FFEQ3*/ -+#define RSTV0910_P1_FFEQ3 0xf4d5 -+#define FSTV0910_P1_FFE_ACCQ3 0xf4d501ff -+ -+/*P1_FFEI4*/ -+#define RSTV0910_P1_FFEI4 0xf4d6 -+#define FSTV0910_P1_FFE_ACCI4 0xf4d601ff -+ -+/*P1_FFEQ4*/ -+#define RSTV0910_P1_FFEQ4 0xf4d7 -+#define FSTV0910_P1_FFE_ACCQ4 0xf4d701ff -+ -+/*P1_FFECFG*/ -+#define RSTV0910_P1_FFECFG 0xf4d8 -+#define FSTV0910_P1_EQUALFFE_ON 0xf4d80040 -+#define FSTV0910_P1_EQUAL_USEDSYMB 0xf4d80030 -+#define FSTV0910_P1_MU_EQUALFFE 0xf4d80007 -+ -+/*P1_TNRCFG2*/ -+#define RSTV0910_P1_TNRCFG2 0xf4e1 -+#define FSTV0910_P1_TUN_IQSWAP 0xf4e10080 -+#define FSTV0910_P1_STB6110_STEP2MHZ 0xf4e10040 -+#define FSTV0910_P1_STB6120_DBLI2C 0xf4e10020 -+#define FSTV0910_P1_TUNER_WIDEBAND 0xf4e10010 -+#define FSTV0910_P1_TUNER_OBSPAGE 0xf4e10008 -+#define FSTV0910_P1_DIS_BWCALC 0xf4e10004 -+#define FSTV0910_P1_SHORT_WAITSTATES 0xf4e10002 -+#define FSTV0910_P1_DIS_2BWAGC1 0xf4e10001 -+ -+/*P1_SMAPCOEF7*/ -+#define RSTV0910_P1_SMAPCOEF7 0xf500 -+#define FSTV0910_P1_DIS_QSCALE 0xf5000080 -+#define FSTV0910_P1_SMAPCOEF_Q_LLR12 0xf500017f -+ -+/*P1_SMAPCOEF6*/ -+#define RSTV0910_P1_SMAPCOEF6 0xf501 -+#define FSTV0910_P1_DIS_AGC2SCALE 0xf5010080 -+#define FSTV0910_P1_DIS_16IQMULT 0xf5010040 -+#define FSTV0910_P1_OLD_16APSK47 0xf5010020 -+#define FSTV0910_P1_OLD_16APSK12 0xf5010010 -+#define FSTV0910_P1_DIS_NEWSCALE 0xf5010008 -+#define FSTV0910_P1_ADJ_8PSKLLR1 0xf5010004 -+#define FSTV0910_P1_OLD_8PSKLLR1 0xf5010002 -+#define FSTV0910_P1_DIS_AB8PSK 0xf5010001 -+ -+/*P1_SMAPCOEF5*/ -+#define RSTV0910_P1_SMAPCOEF5 0xf502 -+#define FSTV0910_P1_DIS_8SCALE 0xf5020080 -+#define FSTV0910_P1_SMAPCOEF_8P_LLR23 0xf502017f -+ -+/*P1_NOSTHRES1*/ -+#define RSTV0910_P1_NOSTHRES1 0xf509 -+#define FSTV0910_P1_NOS_THRESHOLD1 0xf50900ff -+ -+/*P1_NOSTHRES2*/ -+#define RSTV0910_P1_NOSTHRES2 0xf50a -+#define FSTV0910_P1_NOS_THRESHOLD2 0xf50a00ff -+ -+/*P1_NOSDIFF1*/ -+#define RSTV0910_P1_NOSDIFF1 0xf50b -+#define FSTV0910_P1_NOSTHRES1_DIFF 0xf50b00ff -+ -+/*P1_RAINFADE*/ -+#define RSTV0910_P1_RAINFADE 0xf50c -+#define FSTV0910_P1_NOSTHRES_DATAT 0xf50c0080 -+#define FSTV0910_P1_RAINFADE_CNLIMIT 0xf50c0070 -+#define FSTV0910_P1_RAINFADE_TIMEOUT 0xf50c0007 -+ -+/*P1_NOSRAMCFG*/ -+#define RSTV0910_P1_NOSRAMCFG 0xf50d -+#define FSTV0910_P1_NOSRAM_DVBS2DATA 0xf50d0080 -+#define FSTV0910_P1_NOSRAM_QUADRAT 0xf50d0040 -+#define FSTV0910_P1_NOSRAM_ACTIVATION 0xf50d0030 -+#define FSTV0910_P1_NOSRAM_CNRONLY 0xf50d0008 -+#define FSTV0910_P1_NOSRAM_LGNCNR1 0xf50d0007 -+ -+/*P1_NOSRAMPOS*/ -+#define RSTV0910_P1_NOSRAMPOS 0xf50e -+#define FSTV0910_P1_NOSRAM_LGNCNR0 0xf50e00f0 -+#define FSTV0910_P1_NOSRAM_VALIDE 0xf50e0004 -+#define FSTV0910_P1_NOSRAM_CNRVAL1 0xf50e0003 -+ -+/*P1_NOSRAMVAL*/ -+#define RSTV0910_P1_NOSRAMVAL 0xf50f -+#define FSTV0910_P1_NOSRAM_CNRVAL0 0xf50f00ff -+ -+/*P1_DMDPLHSTAT*/ -+#define RSTV0910_P1_DMDPLHSTAT 0xf520 -+#define FSTV0910_P1_PLH_STATISTIC 0xf52000ff -+ -+/*P1_LOCKTIME3*/ -+#define RSTV0910_P1_LOCKTIME3 0xf522 -+#define FSTV0910_P1_DEMOD_LOCKTIME3 0xf52200ff -+ -+/*P1_LOCKTIME2*/ -+#define RSTV0910_P1_LOCKTIME2 0xf523 -+#define FSTV0910_P1_DEMOD_LOCKTIME2 0xf52300ff -+ -+/*P1_LOCKTIME1*/ -+#define RSTV0910_P1_LOCKTIME1 0xf524 -+#define FSTV0910_P1_DEMOD_LOCKTIME1 0xf52400ff -+ -+/*P1_LOCKTIME0*/ -+#define RSTV0910_P1_LOCKTIME0 0xf525 -+#define FSTV0910_P1_DEMOD_LOCKTIME0 0xf52500ff -+ -+/*P1_VITSCALE*/ -+#define RSTV0910_P1_VITSCALE 0xf532 -+#define FSTV0910_P1_NVTH_NOSRANGE 0xf5320080 -+#define FSTV0910_P1_VERROR_MAXMODE 0xf5320040 -+#define FSTV0910_P1_KDIV_MODE 0xf5320030 -+#define FSTV0910_P1_NSLOWSN_LOCKED 0xf5320008 -+#define FSTV0910_P1_DELOCK_PRFLOSS 0xf5320004 -+#define FSTV0910_P1_DIS_RSFLOCK 0xf5320002 -+ -+/*P1_FECM*/ -+#define RSTV0910_P1_FECM 0xf533 -+#define FSTV0910_P1_DSS_DVB 0xf5330080 -+#define FSTV0910_P1_DEMOD_BYPASS 0xf5330040 -+#define FSTV0910_P1_CMP_SLOWMODE 0xf5330020 -+#define FSTV0910_P1_DSS_SRCH 0xf5330010 -+#define FSTV0910_P1_DIFF_MODEVIT 0xf5330004 -+#define FSTV0910_P1_SYNCVIT 0xf5330002 -+#define FSTV0910_P1_IQINV 0xf5330001 -+ -+/*P1_VTH12*/ -+#define RSTV0910_P1_VTH12 0xf534 -+#define FSTV0910_P1_VTH12 0xf53400ff -+ -+/*P1_VTH23*/ -+#define RSTV0910_P1_VTH23 0xf535 -+#define FSTV0910_P1_VTH23 0xf53500ff -+ -+/*P1_VTH34*/ -+#define RSTV0910_P1_VTH34 0xf536 -+#define FSTV0910_P1_VTH34 0xf53600ff -+ -+/*P1_VTH56*/ -+#define RSTV0910_P1_VTH56 0xf537 -+#define FSTV0910_P1_VTH56 0xf53700ff -+ -+/*P1_VTH67*/ -+#define RSTV0910_P1_VTH67 0xf538 -+#define FSTV0910_P1_VTH67 0xf53800ff -+ -+/*P1_VTH78*/ -+#define RSTV0910_P1_VTH78 0xf539 -+#define FSTV0910_P1_VTH78 0xf53900ff -+ -+/*P1_VITCURPUN*/ -+#define RSTV0910_P1_VITCURPUN 0xf53a -+#define FSTV0910_P1_CYCLESLIP_VIT 0xf53a0080 -+#define FSTV0910_P1_VIT_ROTA180 0xf53a0040 -+#define FSTV0910_P1_VIT_ROTA90 0xf53a0020 -+#define FSTV0910_P1_VIT_CURPUN 0xf53a001f -+ -+/*P1_VERROR*/ -+#define RSTV0910_P1_VERROR 0xf53b -+#define FSTV0910_P1_REGERR_VIT 0xf53b00ff -+ -+/*P1_PRVIT*/ -+#define RSTV0910_P1_PRVIT 0xf53c -+#define FSTV0910_P1_DIS_VTHLOCK 0xf53c0040 -+#define FSTV0910_P1_E7_8VIT 0xf53c0020 -+#define FSTV0910_P1_E6_7VIT 0xf53c0010 -+#define FSTV0910_P1_E5_6VIT 0xf53c0008 -+#define FSTV0910_P1_E3_4VIT 0xf53c0004 -+#define FSTV0910_P1_E2_3VIT 0xf53c0002 -+#define FSTV0910_P1_E1_2VIT 0xf53c0001 -+ -+/*P1_VAVSRVIT*/ -+#define RSTV0910_P1_VAVSRVIT 0xf53d -+#define FSTV0910_P1_AMVIT 0xf53d0080 -+#define FSTV0910_P1_FROZENVIT 0xf53d0040 -+#define FSTV0910_P1_SNVIT 0xf53d0030 -+#define FSTV0910_P1_TOVVIT 0xf53d000c -+#define FSTV0910_P1_HYPVIT 0xf53d0003 -+ -+/*P1_VSTATUSVIT*/ -+#define RSTV0910_P1_VSTATUSVIT 0xf53e -+#define FSTV0910_P1_VITERBI_ON 0xf53e0080 -+#define FSTV0910_P1_END_LOOPVIT 0xf53e0040 -+#define FSTV0910_P1_VITERBI_DEPRF 0xf53e0020 -+#define FSTV0910_P1_PRFVIT 0xf53e0010 -+#define FSTV0910_P1_LOCKEDVIT 0xf53e0008 -+#define FSTV0910_P1_VITERBI_DELOCK 0xf53e0004 -+#define FSTV0910_P1_VIT_DEMODSEL 0xf53e0002 -+#define FSTV0910_P1_VITERBI_COMPOUT 0xf53e0001 -+ -+/*P1_VTHINUSE*/ -+#define RSTV0910_P1_VTHINUSE 0xf53f -+#define FSTV0910_P1_VIT_INUSE 0xf53f00ff -+ -+/*P1_KDIV12*/ -+#define RSTV0910_P1_KDIV12 0xf540 -+#define FSTV0910_P1_KDIV12_MANUAL 0xf5400080 -+#define FSTV0910_P1_K_DIVIDER_12 0xf540007f -+ -+/*P1_KDIV23*/ -+#define RSTV0910_P1_KDIV23 0xf541 -+#define FSTV0910_P1_KDIV23_MANUAL 0xf5410080 -+#define FSTV0910_P1_K_DIVIDER_23 0xf541007f -+ -+/*P1_KDIV34*/ -+#define RSTV0910_P1_KDIV34 0xf542 -+#define FSTV0910_P1_KDIV34_MANUAL 0xf5420080 -+#define FSTV0910_P1_K_DIVIDER_34 0xf542007f -+ -+/*P1_KDIV56*/ -+#define RSTV0910_P1_KDIV56 0xf543 -+#define FSTV0910_P1_KDIV56_MANUAL 0xf5430080 -+#define FSTV0910_P1_K_DIVIDER_56 0xf543007f -+ -+/*P1_KDIV67*/ -+#define RSTV0910_P1_KDIV67 0xf544 -+#define FSTV0910_P1_KDIV67_MANUAL 0xf5440080 -+#define FSTV0910_P1_K_DIVIDER_67 0xf544007f -+ -+/*P1_KDIV78*/ -+#define RSTV0910_P1_KDIV78 0xf545 -+#define FSTV0910_P1_KDIV78_MANUAL 0xf5450080 -+#define FSTV0910_P1_K_DIVIDER_78 0xf545007f -+ -+/*P1_PDELCTRL0*/ -+#define RSTV0910_P1_PDELCTRL0 0xf54f -+#define FSTV0910_P1_ISIOBS_MODE 0xf54f0030 -+#define FSTV0910_P1_PDELDIS_BITWISE 0xf54f0004 -+ -+/*P1_PDELCTRL1*/ -+#define RSTV0910_P1_PDELCTRL1 0xf550 -+#define FSTV0910_P1_INV_MISMASK 0xf5500080 -+#define FSTV0910_P1_FORCE_ACCEPTED 0xf5500040 -+#define FSTV0910_P1_FILTER_EN 0xf5500020 -+#define FSTV0910_P1_FORCE_PKTDELINUSE 0xf5500010 -+#define FSTV0910_P1_HYSTEN 0xf5500008 -+#define FSTV0910_P1_HYSTSWRST 0xf5500004 -+#define FSTV0910_P1_EN_MIS00 0xf5500002 -+#define FSTV0910_P1_ALGOSWRST 0xf5500001 -+ -+/*P1_PDELCTRL2*/ -+#define RSTV0910_P1_PDELCTRL2 0xf551 -+#define FSTV0910_P1_FORCE_CONTINUOUS 0xf5510080 -+#define FSTV0910_P1_RESET_UPKO_COUNT 0xf5510040 -+#define FSTV0910_P1_USER_PKTDELIN_NB 0xf5510020 -+#define FSTV0910_P1_DATA_UNBBSCRAMBLED 0xf5510008 -+#define FSTV0910_P1_FORCE_LONGPKT 0xf5510004 -+#define FSTV0910_P1_FRAME_MODE 0xf5510002 -+ -+/*P1_HYSTTHRESH*/ -+#define RSTV0910_P1_HYSTTHRESH 0xf554 -+#define FSTV0910_P1_DELIN_LOCKTHRES 0xf55400f0 -+#define FSTV0910_P1_DELIN_UNLOCKTHRES 0xf554000f -+ -+/*P1_ISIENTRY*/ -+#define RSTV0910_P1_ISIENTRY 0xf55e -+#define FSTV0910_P1_ISI_ENTRY 0xf55e00ff -+ -+/*P1_ISIBITENA*/ -+#define RSTV0910_P1_ISIBITENA 0xf55f -+#define FSTV0910_P1_ISI_BIT_EN 0xf55f00ff -+ -+/*P1_MATSTR1*/ -+#define RSTV0910_P1_MATSTR1 0xf560 -+#define FSTV0910_P1_MATYPE_CURRENT1 0xf56000ff -+ -+/*P1_MATSTR0*/ -+#define RSTV0910_P1_MATSTR0 0xf561 -+#define FSTV0910_P1_MATYPE_CURRENT0 0xf56100ff -+ -+/*P1_UPLSTR1*/ -+#define RSTV0910_P1_UPLSTR1 0xf562 -+#define FSTV0910_P1_UPL_CURRENT1 0xf56200ff -+ -+/*P1_UPLSTR0*/ -+#define RSTV0910_P1_UPLSTR0 0xf563 -+#define FSTV0910_P1_UPL_CURRENT0 0xf56300ff -+ -+/*P1_DFLSTR1*/ -+#define RSTV0910_P1_DFLSTR1 0xf564 -+#define FSTV0910_P1_DFL_CURRENT1 0xf56400ff -+ -+/*P1_DFLSTR0*/ -+#define RSTV0910_P1_DFLSTR0 0xf565 -+#define FSTV0910_P1_DFL_CURRENT0 0xf56500ff -+ -+/*P1_SYNCSTR*/ -+#define RSTV0910_P1_SYNCSTR 0xf566 -+#define FSTV0910_P1_SYNC_CURRENT 0xf56600ff -+ -+/*P1_SYNCDSTR1*/ -+#define RSTV0910_P1_SYNCDSTR1 0xf567 -+#define FSTV0910_P1_SYNCD_CURRENT1 0xf56700ff -+ -+/*P1_SYNCDSTR0*/ -+#define RSTV0910_P1_SYNCDSTR0 0xf568 -+#define FSTV0910_P1_SYNCD_CURRENT0 0xf56800ff -+ -+/*P1_PDELSTATUS1*/ -+#define RSTV0910_P1_PDELSTATUS1 0xf569 -+#define FSTV0910_P1_PKTDELIN_DELOCK 0xf5690080 -+#define FSTV0910_P1_SYNCDUPDFL_BADDFL 0xf5690040 -+#define FSTV0910_P1_CONTINUOUS_STREAM 0xf5690020 -+#define FSTV0910_P1_UNACCEPTED_STREAM 0xf5690010 -+#define FSTV0910_P1_BCH_ERROR_FLAG 0xf5690008 -+#define FSTV0910_P1_BBHCRCKO 0xf5690004 -+#define FSTV0910_P1_PKTDELIN_LOCK 0xf5690002 -+#define FSTV0910_P1_FIRST_LOCK 0xf5690001 -+ -+/*P1_PDELSTATUS2*/ -+#define RSTV0910_P1_PDELSTATUS2 0xf56a -+#define FSTV0910_P1_PKTDEL_DEMODSEL 0xf56a0080 -+#define FSTV0910_P1_FRAME_MODCOD 0xf56a007c -+#define FSTV0910_P1_FRAME_TYPE 0xf56a0003 -+ -+/*P1_BBFCRCKO1*/ -+#define RSTV0910_P1_BBFCRCKO1 0xf56b -+#define FSTV0910_P1_BBHCRC_KOCNT1 0xf56b00ff -+ -+/*P1_BBFCRCKO0*/ -+#define RSTV0910_P1_BBFCRCKO0 0xf56c -+#define FSTV0910_P1_BBHCRC_KOCNT0 0xf56c00ff -+ -+/*P1_UPCRCKO1*/ -+#define RSTV0910_P1_UPCRCKO1 0xf56d -+#define FSTV0910_P1_PKTCRC_KOCNT1 0xf56d00ff -+ -+/*P1_UPCRCKO0*/ -+#define RSTV0910_P1_UPCRCKO0 0xf56e -+#define FSTV0910_P1_PKTCRC_KOCNT0 0xf56e00ff -+ -+/*P1_PDELCTRL3*/ -+#define RSTV0910_P1_PDELCTRL3 0xf56f -+#define FSTV0910_P1_PKTDEL_CONTFAIL 0xf56f0080 -+#define FSTV0910_P1_PKTDEL_ENLONGPKT 0xf56f0040 -+#define FSTV0910_P1_NOFIFO_BCHERR 0xf56f0020 -+#define FSTV0910_P1_PKTDELIN_DELACMERR 0xf56f0010 -+#define FSTV0910_P1_SATURATE_BBPKTKO 0xf56f0004 -+#define FSTV0910_P1_PKTDEL_BCHERRCONT 0xf56f0002 -+#define FSTV0910_P1_ETHERNET_DISFCS 0xf56f0001 -+ -+/*P1_TSSTATEM*/ -+#define RSTV0910_P1_TSSTATEM 0xf570 -+#define FSTV0910_P1_TSDIL_ON 0xf5700080 -+#define FSTV0910_P1_TSSKIPRS_ON 0xf5700040 -+#define FSTV0910_P1_TSRS_ON 0xf5700020 -+#define FSTV0910_P1_TSDESCRAMB_ON 0xf5700010 -+#define FSTV0910_P1_TSFRAME_MODE 0xf5700008 -+#define FSTV0910_P1_TS_DISABLE 0xf5700004 -+#define FSTV0910_P1_TSACM_MODE 0xf5700002 -+#define FSTV0910_P1_TSOUT_NOSYNC 0xf5700001 -+ -+/*P1_TSCFGH*/ -+#define RSTV0910_P1_TSCFGH 0xf572 -+#define FSTV0910_P1_TSFIFO_DVBCI 0xf5720080 -+#define FSTV0910_P1_TSFIFO_SERIAL 0xf5720040 -+#define FSTV0910_P1_TSFIFO_TEIUPDATE 0xf5720020 -+#define FSTV0910_P1_TSFIFO_DUTY50 0xf5720010 -+#define FSTV0910_P1_TSFIFO_HSGNLOUT 0xf5720008 -+#define FSTV0910_P1_TSFIFO_ERRMODE 0xf5720006 -+#define FSTV0910_P1_RST_HWARE 0xf5720001 -+ -+/*P1_TSCFGM*/ -+#define RSTV0910_P1_TSCFGM 0xf573 -+#define FSTV0910_P1_TSFIFO_MANSPEED 0xf57300c0 -+#define FSTV0910_P1_TSFIFO_PERMDATA 0xf5730020 -+#define FSTV0910_P1_TSFIFO_NONEWSGNL 0xf5730010 -+#define FSTV0910_P1_NPD_SPECDVBS2 0xf5730004 -+#define FSTV0910_P1_TSFIFO_DPUNACTIVE 0xf5730002 -+#define FSTV0910_P1_TSFIFO_INVDATA 0xf5730001 -+ -+/*P1_TSCFGL*/ -+#define RSTV0910_P1_TSCFGL 0xf574 -+#define FSTV0910_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 -+#define FSTV0910_P1_BCHERROR_MODE 0xf5740030 -+#define FSTV0910_P1_TSFIFO_NSGNL2DATA 0xf5740008 -+#define FSTV0910_P1_TSFIFO_EMBINDVB 0xf5740004 -+#define FSTV0910_P1_TSFIFO_BITSPEED 0xf5740003 -+ -+/*P1_TSINSDELH*/ -+#define RSTV0910_P1_TSINSDELH 0xf576 -+#define FSTV0910_P1_TSDEL_SYNCBYTE 0xf5760080 -+#define FSTV0910_P1_TSDEL_XXHEADER 0xf5760040 -+#define FSTV0910_P1_TSDEL_BBHEADER 0xf5760020 -+#define FSTV0910_P1_TSDEL_DATAFIELD 0xf5760010 -+#define FSTV0910_P1_TSINSDEL_ISCR 0xf5760008 -+#define FSTV0910_P1_TSINSDEL_NPD 0xf5760004 -+#define FSTV0910_P1_TSINSDEL_RSPARITY 0xf5760002 -+#define FSTV0910_P1_TSINSDEL_CRC8 0xf5760001 -+ -+/*P1_TSDIVN*/ -+#define RSTV0910_P1_TSDIVN 0xf579 -+#define FSTV0910_P1_TSFIFO_SPEEDMODE 0xf57900c0 -+#define FSTV0910_P1_BYTE_OVERSAMPLING 0xf5790038 -+#define FSTV0910_P1_TSFIFO_RISEOK 0xf5790007 -+ -+/*P1_TSCFG4*/ -+#define RSTV0910_P1_TSCFG4 0xf57a -+#define FSTV0910_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0 -+#define FSTV0910_P1_TSFIFO_HIERSEL 0xf57a0020 -+#define FSTV0910_P1_TSFIFO_SPECTOKEN 0xf57a0010 -+#define FSTV0910_P1_TSFIFO_MAXMODE 0xf57a0008 -+#define FSTV0910_P1_TSFIFO_FRFORCEPKT 0xf57a0004 -+#define FSTV0910_P1_EXT_FECSPYIN 0xf57a0002 -+#define FSTV0910_P1_TSFIFO_DELSPEEDUP 0xf57a0001 -+ -+/*P1_TSSPEED*/ -+#define RSTV0910_P1_TSSPEED 0xf580 -+#define FSTV0910_P1_TSFIFO_OUTSPEED 0xf58000ff -+ -+/*P1_TSSTATUS*/ -+#define RSTV0910_P1_TSSTATUS 0xf581 -+#define FSTV0910_P1_TSFIFO_LINEOK 0xf5810080 -+#define FSTV0910_P1_TSFIFO_ERROR 0xf5810040 -+#define FSTV0910_P1_TSFIFO_DATA7 0xf5810020 -+#define FSTV0910_P1_TSFIFO_NOSYNC 0xf5810010 -+#define FSTV0910_P1_ISCR_INITIALIZED 0xf5810008 -+#define FSTV0910_P1_TSREGUL_ERROR 0xf5810004 -+#define FSTV0910_P1_SOFFIFO_UNREGUL 0xf5810002 -+#define FSTV0910_P1_DIL_READY 0xf5810001 -+ -+/*P1_TSSTATUS2*/ -+#define RSTV0910_P1_TSSTATUS2 0xf582 -+#define FSTV0910_P1_TSFIFO_DEMODSEL 0xf5820080 -+#define FSTV0910_P1_TSFIFOSPEED_STORE 0xf5820040 -+#define FSTV0910_P1_DILXX_RESET 0xf5820020 -+#define FSTV0910_P1_TSSPEED_IMPOSSIBLE 0xf5820010 -+#define FSTV0910_P1_TSFIFO_LINENOK 0xf5820008 -+#define FSTV0910_P1_TSFIFO_MUXSTREAM 0xf5820004 -+#define FSTV0910_P1_SCRAMBDETECT 0xf5820002 -+#define FSTV0910_P1_ULDTV67_FALSELOCK 0xf5820001 -+ -+/*P1_TSBITRATE1*/ -+#define RSTV0910_P1_TSBITRATE1 0xf583 -+#define FSTV0910_P1_TSFIFO_BITRATE1 0xf58300ff -+ -+/*P1_TSBITRATE0*/ -+#define RSTV0910_P1_TSBITRATE0 0xf584 -+#define FSTV0910_P1_TSFIFO_BITRATE0 0xf58400ff -+ -+/*P1_ERRCTRL1*/ -+#define RSTV0910_P1_ERRCTRL1 0xf598 -+#define FSTV0910_P1_ERR_SOURCE1 0xf59800f0 -+#define FSTV0910_P1_NUM_EVENT1 0xf5980007 -+ -+/*P1_ERRCNT12*/ -+#define RSTV0910_P1_ERRCNT12 0xf599 -+#define FSTV0910_P1_ERRCNT1_OLDVALUE 0xf5990080 -+#define FSTV0910_P1_ERR_CNT12 0xf599007f -+ -+/*P1_ERRCNT11*/ -+#define RSTV0910_P1_ERRCNT11 0xf59a -+#define FSTV0910_P1_ERR_CNT11 0xf59a00ff -+ -+/*P1_ERRCNT10*/ -+#define RSTV0910_P1_ERRCNT10 0xf59b -+#define FSTV0910_P1_ERR_CNT10 0xf59b00ff -+ -+/*P1_ERRCTRL2*/ -+#define RSTV0910_P1_ERRCTRL2 0xf59c -+#define FSTV0910_P1_ERR_SOURCE2 0xf59c00f0 -+#define FSTV0910_P1_NUM_EVENT2 0xf59c0007 -+ -+/*P1_ERRCNT22*/ -+#define RSTV0910_P1_ERRCNT22 0xf59d -+#define FSTV0910_P1_ERRCNT2_OLDVALUE 0xf59d0080 -+#define FSTV0910_P1_ERR_CNT22 0xf59d007f -+ -+/*P1_ERRCNT21*/ -+#define RSTV0910_P1_ERRCNT21 0xf59e -+#define FSTV0910_P1_ERR_CNT21 0xf59e00ff -+ -+/*P1_ERRCNT20*/ -+#define RSTV0910_P1_ERRCNT20 0xf59f -+#define FSTV0910_P1_ERR_CNT20 0xf59f00ff -+ -+/*P1_FECSPY*/ -+#define RSTV0910_P1_FECSPY 0xf5a0 -+#define FSTV0910_P1_SPY_ENABLE 0xf5a00080 -+#define FSTV0910_P1_NO_SYNCBYTE 0xf5a00040 -+#define FSTV0910_P1_SERIAL_MODE 0xf5a00020 -+#define FSTV0910_P1_UNUSUAL_PACKET 0xf5a00010 -+#define FSTV0910_P1_BERMETER_DATAMODE 0xf5a0000c -+#define FSTV0910_P1_BERMETER_LMODE 0xf5a00002 -+#define FSTV0910_P1_BERMETER_RESET 0xf5a00001 -+ -+/*P1_FSPYCFG*/ -+#define RSTV0910_P1_FSPYCFG 0xf5a1 -+#define FSTV0910_P1_FECSPY_INPUT 0xf5a100c0 -+#define FSTV0910_P1_RST_ON_ERROR 0xf5a10020 -+#define FSTV0910_P1_ONE_SHOT 0xf5a10010 -+#define FSTV0910_P1_I2C_MODE 0xf5a1000c -+#define FSTV0910_P1_SPY_HYSTERESIS 0xf5a10003 -+ -+/*P1_FSPYDATA*/ -+#define RSTV0910_P1_FSPYDATA 0xf5a2 -+#define FSTV0910_P1_SPY_STUFFING 0xf5a20080 -+#define FSTV0910_P1_NOERROR_PKTJITTER 0xf5a20040 -+#define FSTV0910_P1_SPY_CNULLPKT 0xf5a20020 -+#define FSTV0910_P1_SPY_OUTDATA_MODE 0xf5a2001f -+ -+/*P1_FSPYOUT*/ -+#define RSTV0910_P1_FSPYOUT 0xf5a3 -+#define FSTV0910_P1_FSPY_DIRECT 0xf5a30080 -+#define FSTV0910_P1_SPY_OUTDATA_BUS 0xf5a30038 -+#define FSTV0910_P1_STUFF_MODE 0xf5a30007 -+ -+/*P1_FSTATUS*/ -+#define RSTV0910_P1_FSTATUS 0xf5a4 -+#define FSTV0910_P1_SPY_ENDSIM 0xf5a40080 -+#define FSTV0910_P1_VALID_SIM 0xf5a40040 -+#define FSTV0910_P1_FOUND_SIGNAL 0xf5a40020 -+#define FSTV0910_P1_DSS_SYNCBYTE 0xf5a40010 -+#define FSTV0910_P1_RESULT_STATE 0xf5a4000f -+ -+/*P1_FBERCPT4*/ -+#define RSTV0910_P1_FBERCPT4 0xf5a8 -+#define FSTV0910_P1_FBERMETER_CPT4 0xf5a800ff -+ -+/*P1_FBERCPT3*/ -+#define RSTV0910_P1_FBERCPT3 0xf5a9 -+#define FSTV0910_P1_FBERMETER_CPT3 0xf5a900ff -+ -+/*P1_FBERCPT2*/ -+#define RSTV0910_P1_FBERCPT2 0xf5aa -+#define FSTV0910_P1_FBERMETER_CPT2 0xf5aa00ff -+ -+/*P1_FBERCPT1*/ -+#define RSTV0910_P1_FBERCPT1 0xf5ab -+#define FSTV0910_P1_FBERMETER_CPT1 0xf5ab00ff -+ -+/*P1_FBERCPT0*/ -+#define RSTV0910_P1_FBERCPT0 0xf5ac -+#define FSTV0910_P1_FBERMETER_CPT0 0xf5ac00ff -+ -+/*P1_FBERERR2*/ -+#define RSTV0910_P1_FBERERR2 0xf5ad -+#define FSTV0910_P1_FBERMETER_ERR2 0xf5ad00ff -+ -+/*P1_FBERERR1*/ -+#define RSTV0910_P1_FBERERR1 0xf5ae -+#define FSTV0910_P1_FBERMETER_ERR1 0xf5ae00ff -+ -+/*P1_FBERERR0*/ -+#define RSTV0910_P1_FBERERR0 0xf5af -+#define FSTV0910_P1_FBERMETER_ERR0 0xf5af00ff -+ -+/*P1_FSPYBER*/ -+#define RSTV0910_P1_FSPYBER 0xf5b2 -+#define FSTV0910_P1_FSPYOBS_XORREAD 0xf5b20040 -+#define FSTV0910_P1_FSPYBER_OBSMODE 0xf5b20020 -+#define FSTV0910_P1_FSPYBER_SYNCBYTE 0xf5b20010 -+#define FSTV0910_P1_FSPYBER_UNSYNC 0xf5b20008 -+#define FSTV0910_P1_FSPYBER_CTIME 0xf5b20007 -+ -+/*P1_SFERROR*/ -+#define RSTV0910_P1_SFERROR 0xf5c1 -+#define FSTV0910_P1_SFEC_REGERR_VIT 0xf5c100ff -+ -+/*P1_SFECSTATUS*/ -+#define RSTV0910_P1_SFECSTATUS 0xf5c3 -+#define FSTV0910_P1_SFEC_ON 0xf5c30080 -+#define FSTV0910_P1_SFEC_OFF 0xf5c30040 -+#define FSTV0910_P1_LOCKEDSFEC 0xf5c30008 -+#define FSTV0910_P1_SFEC_DELOCK 0xf5c30004 -+#define FSTV0910_P1_SFEC_DEMODSEL 0xf5c30002 -+#define FSTV0910_P1_SFEC_OVFON 0xf5c30001 -+ -+/*P1_SFKDIV12*/ -+#define RSTV0910_P1_SFKDIV12 0xf5c4 -+#define FSTV0910_P1_SFECKDIV12_MAN 0xf5c40080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_12 0xf5c4007f -+ -+/*P1_SFKDIV23*/ -+#define RSTV0910_P1_SFKDIV23 0xf5c5 -+#define FSTV0910_P1_SFECKDIV23_MAN 0xf5c50080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_23 0xf5c5007f -+ -+/*P1_SFKDIV34*/ -+#define RSTV0910_P1_SFKDIV34 0xf5c6 -+#define FSTV0910_P1_SFECKDIV34_MAN 0xf5c60080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_34 0xf5c6007f -+ -+/*P1_SFKDIV56*/ -+#define RSTV0910_P1_SFKDIV56 0xf5c7 -+#define FSTV0910_P1_SFECKDIV56_MAN 0xf5c70080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_56 0xf5c7007f -+ -+/*P1_SFKDIV67*/ -+#define RSTV0910_P1_SFKDIV67 0xf5c8 -+#define FSTV0910_P1_SFECKDIV67_MAN 0xf5c80080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_67 0xf5c8007f -+ -+/*P1_SFKDIV78*/ -+#define RSTV0910_P1_SFKDIV78 0xf5c9 -+#define FSTV0910_P1_SFECKDIV78_MAN 0xf5c90080 -+#define FSTV0910_P1_SFEC_K_DIVIDER_78 0xf5c9007f -+ -+/*P1_SFSTATUS*/ -+#define RSTV0910_P1_SFSTATUS 0xf5cc -+#define FSTV0910_P1_SFEC_LINEOK 0xf5cc0080 -+#define FSTV0910_P1_SFEC_ERROR 0xf5cc0040 -+#define FSTV0910_P1_SFEC_DATA7 0xf5cc0020 -+#define FSTV0910_P1_SFEC_PKTDNBRFAIL 0xf5cc0010 -+#define FSTV0910_P1_TSSFEC_DEMODSEL 0xf5cc0008 -+#define FSTV0910_P1_SFEC_NOSYNC 0xf5cc0004 -+#define FSTV0910_P1_SFEC_UNREGULA 0xf5cc0002 -+#define FSTV0910_P1_SFEC_READY 0xf5cc0001 -+ -+/*P1_SFDLYSET2*/ -+#define RSTV0910_P1_SFDLYSET2 0xf5d0 -+#define FSTV0910_P1_SFEC_OFFSET 0xf5d000c0 -+#define FSTV0910_P1_RST_SFEC 0xf5d00008 -+#define FSTV0910_P1_DILDLINE_ERROR 0xf5d00004 -+#define FSTV0910_P1_SFEC_DISABLE 0xf5d00002 -+#define FSTV0910_P1_SFEC_UNREGUL 0xf5d00001 -+ -+/*P1_SFERRCTRL*/ -+#define RSTV0910_P1_SFERRCTRL 0xf5d8 -+#define FSTV0910_P1_SFEC_ERR_SOURCE 0xf5d800f0 -+#define FSTV0910_P1_SFEC_NUM_EVENT 0xf5d80007 -+ -+/*P1_SFERRCNT2*/ -+#define RSTV0910_P1_SFERRCNT2 0xf5d9 -+#define FSTV0910_P1_SFERRC_OLDVALUE 0xf5d90080 -+#define FSTV0910_P1_SFEC_ERR_CNT2 0xf5d9007f -+ -+/*P1_SFERRCNT1*/ -+#define RSTV0910_P1_SFERRCNT1 0xf5da -+#define FSTV0910_P1_SFEC_ERR_CNT1 0xf5da00ff -+ -+/*P1_SFERRCNT0*/ -+#define RSTV0910_P1_SFERRCNT0 0xf5db -+#define FSTV0910_P1_SFEC_ERR_CNT0 0xf5db00ff -+ -+/*TSGENERAL*/ -+#define RSTV0910_TSGENERAL 0xf630 -+#define FSTV0910_EN_LGNERROR 0xf6300080 -+#define FSTV0910_TSFIFO_DISTS2PAR 0xf6300040 -+#define FSTV0910_MUXSTREAM_COMPMOSE 0xf6300030 -+#define FSTV0910_MUXSTREAM_OUTMODE 0xf6300008 -+#define FSTV0910_TSFIFO_PERMPARAL 0xf6300006 -+#define FSTV0910_RST_REEDSOLO 0xf6300001 -+ -+/*P1_DISIRQCFG*/ -+#define RSTV0910_P1_DISIRQCFG 0xf700 -+#define FSTV0910_P1_ENRXEND 0xf7000040 -+#define FSTV0910_P1_ENRXFIFO8B 0xf7000020 -+#define FSTV0910_P1_ENTRFINISH 0xf7000010 -+#define FSTV0910_P1_ENTIMEOUT 0xf7000008 -+#define FSTV0910_P1_ENTXEND 0xf7000004 -+#define FSTV0910_P1_ENTXFIFO64B 0xf7000002 -+#define FSTV0910_P1_ENGAPBURST 0xf7000001 -+ -+/*P1_DISIRQSTAT*/ -+#define RSTV0910_P1_DISIRQSTAT 0xf701 -+#define FSTV0910_P1_IRQRXEND 0xf7010040 -+#define FSTV0910_P1_IRQRXFIFO8B 0xf7010020 -+#define FSTV0910_P1_IRQTRFINISH 0xf7010010 -+#define FSTV0910_P1_IRQTIMEOUT 0xf7010008 -+#define FSTV0910_P1_IRQTXEND 0xf7010004 -+#define FSTV0910_P1_IRQTXFIFO64B 0xf7010002 -+#define FSTV0910_P1_IRQGAPBURST 0xf7010001 -+ -+/*P1_DISTXCFG*/ -+#define RSTV0910_P1_DISTXCFG 0xf702 -+#define FSTV0910_P1_DISTX_RESET 0xf7020080 -+#define FSTV0910_P1_TIM_OFF 0xf7020040 -+#define FSTV0910_P1_TIM_CMD 0xf7020030 -+#define FSTV0910_P1_ENVELOP 0xf7020008 -+#define FSTV0910_P1_DIS_PRECHARGE 0xf7020004 -+#define FSTV0910_P1_DISEQC_MODE 0xf7020003 -+ -+/*P1_DISTXSTATUS*/ -+#define RSTV0910_P1_DISTXSTATUS 0xf703 -+#define FSTV0910_P1_TX_FIFO_FULL 0xf7030040 -+#define FSTV0910_P1_TX_IDLE 0xf7030020 -+#define FSTV0910_P1_GAP_BURST 0xf7030010 -+#define FSTV0910_P1_TX_FIFO64B 0xf7030008 -+#define FSTV0910_P1_TX_END 0xf7030004 -+#define FSTV0910_P1_TR_TIMEOUT 0xf7030002 -+#define FSTV0910_P1_TR_FINISH 0xf7030001 -+ -+/*P1_DISTXBYTES*/ -+#define RSTV0910_P1_DISTXBYTES 0xf704 -+#define FSTV0910_P1_TXFIFO_BYTES 0xf70400ff -+ -+/*P1_DISTXFIFO*/ -+#define RSTV0910_P1_DISTXFIFO 0xf705 -+#define FSTV0910_P1_DISEQC_TX_FIFO 0xf70500ff -+ -+/*P1_DISTXF22*/ -+#define RSTV0910_P1_DISTXF22 0xf706 -+#define FSTV0910_P1_F22TX 0xf70600ff -+ -+/*P1_DISTIMEOCFG*/ -+#define RSTV0910_P1_DISTIMEOCFG 0xf708 -+#define FSTV0910_P1_RXCHOICE 0xf7080006 -+#define FSTV0910_P1_TIMEOUT_OFF 0xf7080001 -+ -+/*P1_DISTIMEOUT*/ -+#define RSTV0910_P1_DISTIMEOUT 0xf709 -+#define FSTV0910_P1_TIMEOUT_COUNT 0xf70900ff -+ -+/*P1_DISRXCFG*/ -+#define RSTV0910_P1_DISRXCFG 0xf70a -+#define FSTV0910_P1_DISRX_RESET 0xf70a0080 -+#define FSTV0910_P1_EXTENVELOP 0xf70a0040 -+#define FSTV0910_P1_PINSELECT 0xf70a0038 -+#define FSTV0910_P1_IGNORE_SHORT22K 0xf70a0004 -+#define FSTV0910_P1_SIGNED_RXIN 0xf70a0002 -+#define FSTV0910_P1_DISRX_ON 0xf70a0001 -+ -+/*P1_DISRXSTAT1*/ -+#define RSTV0910_P1_DISRXSTAT1 0xf70b -+#define FSTV0910_P1_RXEND 0xf70b0080 -+#define FSTV0910_P1_RXACTIVE 0xf70b0040 -+#define FSTV0910_P1_RXDETECT 0xf70b0020 -+#define FSTV0910_P1_CONTTONE 0xf70b0010 -+#define FSTV0910_P1_8BFIFOREADY 0xf70b0008 -+#define FSTV0910_P1_FIFOEMPTY 0xf70b0004 -+ -+/*P1_DISRXSTAT0*/ -+#define RSTV0910_P1_DISRXSTAT0 0xf70c -+#define FSTV0910_P1_RXFAIL 0xf70c0080 -+#define FSTV0910_P1_FIFOPFAIL 0xf70c0040 -+#define FSTV0910_P1_RXNONBYTE 0xf70c0020 -+#define FSTV0910_P1_FIFOOVF 0xf70c0010 -+#define FSTV0910_P1_SHORT22K 0xf70c0008 -+#define FSTV0910_P1_RXMSGLOST 0xf70c0004 -+ -+/*P1_DISRXBYTES*/ -+#define RSTV0910_P1_DISRXBYTES 0xf70d -+#define FSTV0910_P1_RXFIFO_BYTES 0xf70d001f -+ -+/*P1_DISRXPARITY1*/ -+#define RSTV0910_P1_DISRXPARITY1 0xf70e -+#define FSTV0910_P1_DISRX_PARITY1 0xf70e00ff -+ -+/*P1_DISRXPARITY0*/ -+#define RSTV0910_P1_DISRXPARITY0 0xf70f -+#define FSTV0910_P1_DISRX_PARITY0 0xf70f00ff -+ -+/*P1_DISRXFIFO*/ -+#define RSTV0910_P1_DISRXFIFO 0xf710 -+#define FSTV0910_P1_DISEQC_RX_FIFO 0xf71000ff -+ -+/*P1_DISRXDC1*/ -+#define RSTV0910_P1_DISRXDC1 0xf711 -+#define FSTV0910_P1_DC_VALUE1 0xf7110103 -+ -+/*P1_DISRXDC0*/ -+#define RSTV0910_P1_DISRXDC0 0xf712 -+#define FSTV0910_P1_DC_VALUE0 0xf71200ff -+ -+/*P1_DISRXF221*/ -+#define RSTV0910_P1_DISRXF221 0xf714 -+#define FSTV0910_P1_F22RX1 0xf714000f -+ -+/*P1_DISRXF220*/ -+#define RSTV0910_P1_DISRXF220 0xf715 -+#define FSTV0910_P1_F22RX0 0xf71500ff -+ -+/*P1_DISRXF100*/ -+#define RSTV0910_P1_DISRXF100 0xf716 -+#define FSTV0910_P1_F100RX 0xf71600ff -+ -+/*P1_DISRXSHORT22K*/ -+#define RSTV0910_P1_DISRXSHORT22K 0xf71c -+#define FSTV0910_P1_SHORT22K_LENGTH 0xf71c001f -+ -+/*P1_ACRPRESC*/ -+#define RSTV0910_P1_ACRPRESC 0xf71e -+#define FSTV0910_P1_ACR_CODFRDY 0xf71e0008 -+#define FSTV0910_P1_ACR_PRESC 0xf71e0007 -+ -+/*P1_ACRDIV*/ -+#define RSTV0910_P1_ACRDIV 0xf71f -+#define FSTV0910_P1_ACR_DIV 0xf71f00ff -+ -+/*P2_DISIRQCFG*/ -+#define RSTV0910_P2_DISIRQCFG 0xf740 -+#define FSTV0910_P2_ENRXEND 0xf7400040 -+#define FSTV0910_P2_ENRXFIFO8B 0xf7400020 -+#define FSTV0910_P2_ENTRFINISH 0xf7400010 -+#define FSTV0910_P2_ENTIMEOUT 0xf7400008 -+#define FSTV0910_P2_ENTXEND 0xf7400004 -+#define FSTV0910_P2_ENTXFIFO64B 0xf7400002 -+#define FSTV0910_P2_ENGAPBURST 0xf7400001 -+ -+/*P2_DISIRQSTAT*/ -+#define RSTV0910_P2_DISIRQSTAT 0xf741 -+#define FSTV0910_P2_IRQRXEND 0xf7410040 -+#define FSTV0910_P2_IRQRXFIFO8B 0xf7410020 -+#define FSTV0910_P2_IRQTRFINISH 0xf7410010 -+#define FSTV0910_P2_IRQTIMEOUT 0xf7410008 -+#define FSTV0910_P2_IRQTXEND 0xf7410004 -+#define FSTV0910_P2_IRQTXFIFO64B 0xf7410002 -+#define FSTV0910_P2_IRQGAPBURST 0xf7410001 -+ -+/*P2_DISTXCFG*/ -+#define RSTV0910_P2_DISTXCFG 0xf742 -+#define FSTV0910_P2_DISTX_RESET 0xf7420080 -+#define FSTV0910_P2_TIM_OFF 0xf7420040 -+#define FSTV0910_P2_TIM_CMD 0xf7420030 -+#define FSTV0910_P2_ENVELOP 0xf7420008 -+#define FSTV0910_P2_DIS_PRECHARGE 0xf7420004 -+#define FSTV0910_P2_DISEQC_MODE 0xf7420003 -+ -+/*P2_DISTXSTATUS*/ -+#define RSTV0910_P2_DISTXSTATUS 0xf743 -+#define FSTV0910_P2_TX_FIFO_FULL 0xf7430040 -+#define FSTV0910_P2_TX_IDLE 0xf7430020 -+#define FSTV0910_P2_GAP_BURST 0xf7430010 -+#define FSTV0910_P2_TX_FIFO64B 0xf7430008 -+#define FSTV0910_P2_TX_END 0xf7430004 -+#define FSTV0910_P2_TR_TIMEOUT 0xf7430002 -+#define FSTV0910_P2_TR_FINISH 0xf7430001 -+ -+/*P2_DISTXBYTES*/ -+#define RSTV0910_P2_DISTXBYTES 0xf744 -+#define FSTV0910_P2_TXFIFO_BYTES 0xf74400ff -+ -+/*P2_DISTXFIFO*/ -+#define RSTV0910_P2_DISTXFIFO 0xf745 -+#define FSTV0910_P2_DISEQC_TX_FIFO 0xf74500ff -+ -+/*P2_DISTXF22*/ -+#define RSTV0910_P2_DISTXF22 0xf746 -+#define FSTV0910_P2_F22TX 0xf74600ff -+ -+/*P2_DISTIMEOCFG*/ -+#define RSTV0910_P2_DISTIMEOCFG 0xf748 -+#define FSTV0910_P2_RXCHOICE 0xf7480006 -+#define FSTV0910_P2_TIMEOUT_OFF 0xf7480001 -+ -+/*P2_DISTIMEOUT*/ -+#define RSTV0910_P2_DISTIMEOUT 0xf749 -+#define FSTV0910_P2_TIMEOUT_COUNT 0xf74900ff -+ -+/*P2_DISRXCFG*/ -+#define RSTV0910_P2_DISRXCFG 0xf74a -+#define FSTV0910_P2_DISRX_RESET 0xf74a0080 -+#define FSTV0910_P2_EXTENVELOP 0xf74a0040 -+#define FSTV0910_P2_PINSELECT 0xf74a0038 -+#define FSTV0910_P2_IGNORE_SHORT22K 0xf74a0004 -+#define FSTV0910_P2_SIGNED_RXIN 0xf74a0002 -+#define FSTV0910_P2_DISRX_ON 0xf74a0001 -+ -+/*P2_DISRXSTAT1*/ -+#define RSTV0910_P2_DISRXSTAT1 0xf74b -+#define FSTV0910_P2_RXEND 0xf74b0080 -+#define FSTV0910_P2_RXACTIVE 0xf74b0040 -+#define FSTV0910_P2_RXDETECT 0xf74b0020 -+#define FSTV0910_P2_CONTTONE 0xf74b0010 -+#define FSTV0910_P2_8BFIFOREADY 0xf74b0008 -+#define FSTV0910_P2_FIFOEMPTY 0xf74b0004 -+ -+/*P2_DISRXSTAT0*/ -+#define RSTV0910_P2_DISRXSTAT0 0xf74c -+#define FSTV0910_P2_RXFAIL 0xf74c0080 -+#define FSTV0910_P2_FIFOPFAIL 0xf74c0040 -+#define FSTV0910_P2_RXNONBYTE 0xf74c0020 -+#define FSTV0910_P2_FIFOOVF 0xf74c0010 -+#define FSTV0910_P2_SHORT22K 0xf74c0008 -+#define FSTV0910_P2_RXMSGLOST 0xf74c0004 -+ -+/*P2_DISRXBYTES*/ -+#define RSTV0910_P2_DISRXBYTES 0xf74d -+#define FSTV0910_P2_RXFIFO_BYTES 0xf74d001f -+ -+/*P2_DISRXPARITY1*/ -+#define RSTV0910_P2_DISRXPARITY1 0xf74e -+#define FSTV0910_P2_DISRX_PARITY1 0xf74e00ff -+ -+/*P2_DISRXPARITY0*/ -+#define RSTV0910_P2_DISRXPARITY0 0xf74f -+#define FSTV0910_P2_DISRX_PARITY0 0xf74f00ff -+ -+/*P2_DISRXFIFO*/ -+#define RSTV0910_P2_DISRXFIFO 0xf750 -+#define FSTV0910_P2_DISEQC_RX_FIFO 0xf75000ff -+ -+/*P2_DISRXDC1*/ -+#define RSTV0910_P2_DISRXDC1 0xf751 -+#define FSTV0910_P2_DC_VALUE1 0xf7510103 -+ -+/*P2_DISRXDC0*/ -+#define RSTV0910_P2_DISRXDC0 0xf752 -+#define FSTV0910_P2_DC_VALUE0 0xf75200ff -+ -+/*P2_DISRXF221*/ -+#define RSTV0910_P2_DISRXF221 0xf754 -+#define FSTV0910_P2_F22RX1 0xf754000f -+ -+/*P2_DISRXF220*/ -+#define RSTV0910_P2_DISRXF220 0xf755 -+#define FSTV0910_P2_F22RX0 0xf75500ff -+ -+/*P2_DISRXF100*/ -+#define RSTV0910_P2_DISRXF100 0xf756 -+#define FSTV0910_P2_F100RX 0xf75600ff -+ -+/*P2_DISRXSHORT22K*/ -+#define RSTV0910_P2_DISRXSHORT22K 0xf75c -+#define FSTV0910_P2_SHORT22K_LENGTH 0xf75c001f -+ -+/*P2_ACRPRESC*/ -+#define RSTV0910_P2_ACRPRESC 0xf75e -+#define FSTV0910_P2_ACR_CODFRDY 0xf75e0008 -+#define FSTV0910_P2_ACR_PRESC 0xf75e0007 -+ -+/*P2_ACRDIV*/ -+#define RSTV0910_P2_ACRDIV 0xf75f -+#define FSTV0910_P2_ACR_DIV 0xf75f00ff -+ -+/*P1_NBITER_NF4*/ -+#define RSTV0910_P1_NBITER_NF4 0xfa03 -+#define FSTV0910_P1_NBITER_NF_QPSK_1_2 0xfa0300ff -+ -+/*P1_NBITER_NF5*/ -+#define RSTV0910_P1_NBITER_NF5 0xfa04 -+#define FSTV0910_P1_NBITER_NF_QPSK_3_5 0xfa0400ff -+ -+/*P1_NBITER_NF6*/ -+#define RSTV0910_P1_NBITER_NF6 0xfa05 -+#define FSTV0910_P1_NBITER_NF_QPSK_2_3 0xfa0500ff -+ -+/*P1_NBITER_NF7*/ -+#define RSTV0910_P1_NBITER_NF7 0xfa06 -+#define FSTV0910_P1_NBITER_NF_QPSK_3_4 0xfa0600ff -+ -+/*P1_NBITER_NF8*/ -+#define RSTV0910_P1_NBITER_NF8 0xfa07 -+#define FSTV0910_P1_NBITER_NF_QPSK_4_5 0xfa0700ff -+ -+/*P1_NBITER_NF9*/ -+#define RSTV0910_P1_NBITER_NF9 0xfa08 -+#define FSTV0910_P1_NBITER_NF_QPSK_5_6 0xfa0800ff -+ -+/*P1_NBITER_NF10*/ -+#define RSTV0910_P1_NBITER_NF10 0xfa09 -+#define FSTV0910_P1_NBITER_NF_QPSK_8_9 0xfa0900ff -+ -+/*P1_NBITER_NF11*/ -+#define RSTV0910_P1_NBITER_NF11 0xfa0a -+#define FSTV0910_P1_NBITER_NF_QPSK_9_10 0xfa0a00ff -+ -+/*P1_NBITER_NF12*/ -+#define RSTV0910_P1_NBITER_NF12 0xfa0b -+#define FSTV0910_P1_NBITER_NF_8PSK_3_5 0xfa0b00ff -+ -+/*P1_NBITER_NF13*/ -+#define RSTV0910_P1_NBITER_NF13 0xfa0c -+#define FSTV0910_P1_NBITER_NF_8PSK_2_3 0xfa0c00ff -+ -+/*P1_NBITER_NF14*/ -+#define RSTV0910_P1_NBITER_NF14 0xfa0d -+#define FSTV0910_P1_NBITER_NF_8PSK_3_4 0xfa0d00ff -+ -+/*P1_NBITER_NF15*/ -+#define RSTV0910_P1_NBITER_NF15 0xfa0e -+#define FSTV0910_P1_NBITER_NF_8PSK_5_6 0xfa0e00ff -+ -+/*P1_NBITER_NF16*/ -+#define RSTV0910_P1_NBITER_NF16 0xfa0f -+#define FSTV0910_P1_NBITER_NF_8PSK_8_9 0xfa0f00ff -+ -+/*P1_NBITER_NF17*/ -+#define RSTV0910_P1_NBITER_NF17 0xfa10 -+#define FSTV0910_P1_NBITER_NF_8PSK_9_10 0xfa1000ff -+ -+/*GAINLLR_NF4*/ -+#define RSTV0910_GAINLLR_NF4 0xfa43 -+#define FSTV0910_GAINLLR_NF_QPSK_1_2 0xfa43007f -+ -+/*GAINLLR_NF5*/ -+#define RSTV0910_GAINLLR_NF5 0xfa44 -+#define FSTV0910_GAINLLR_NF_QPSK_3_5 0xfa44007f -+ -+/*GAINLLR_NF6*/ -+#define RSTV0910_GAINLLR_NF6 0xfa45 -+#define FSTV0910_GAINLLR_NF_QPSK_2_3 0xfa45007f -+ -+/*GAINLLR_NF7*/ -+#define RSTV0910_GAINLLR_NF7 0xfa46 -+#define FSTV0910_GAINLLR_NF_QPSK_3_4 0xfa46007f -+ -+/*GAINLLR_NF8*/ -+#define RSTV0910_GAINLLR_NF8 0xfa47 -+#define FSTV0910_GAINLLR_NF_QPSK_4_5 0xfa47007f -+ -+/*GAINLLR_NF9*/ -+#define RSTV0910_GAINLLR_NF9 0xfa48 -+#define FSTV0910_GAINLLR_NF_QPSK_5_6 0xfa48007f -+ -+/*GAINLLR_NF10*/ -+#define RSTV0910_GAINLLR_NF10 0xfa49 -+#define FSTV0910_GAINLLR_NF_QPSK_8_9 0xfa49007f -+ -+/*GAINLLR_NF11*/ -+#define RSTV0910_GAINLLR_NF11 0xfa4a -+#define FSTV0910_GAINLLR_NF_QPSK_9_10 0xfa4a007f -+ -+/*GAINLLR_NF12*/ -+#define RSTV0910_GAINLLR_NF12 0xfa4b -+#define FSTV0910_GAINLLR_NF_8PSK_3_5 0xfa4b007f -+ -+/*GAINLLR_NF13*/ -+#define RSTV0910_GAINLLR_NF13 0xfa4c -+#define FSTV0910_GAINLLR_NF_8PSK_2_3 0xfa4c007f -+ -+/*GAINLLR_NF14*/ -+#define RSTV0910_GAINLLR_NF14 0xfa4d -+#define FSTV0910_GAINLLR_NF_8PSK_3_4 0xfa4d007f -+ -+/*GAINLLR_NF15*/ -+#define RSTV0910_GAINLLR_NF15 0xfa4e -+#define FSTV0910_GAINLLR_NF_8PSK_5_6 0xfa4e007f -+ -+/*GAINLLR_NF16*/ -+#define RSTV0910_GAINLLR_NF16 0xfa4f -+#define FSTV0910_GAINLLR_NF_8PSK_8_9 0xfa4f007f -+ -+/*GAINLLR_NF17*/ -+#define RSTV0910_GAINLLR_NF17 0xfa50 -+#define FSTV0910_GAINLLR_NF_8PSK_9_10 0xfa50007f -+ -+/*CFGEXT*/ -+#define RSTV0910_CFGEXT 0xfa80 -+#define FSTV0910_BYPFIFOBCH 0xfa800080 -+#define FSTV0910_BYPBCH 0xfa800040 -+#define FSTV0910_BYPLDPC 0xfa800020 -+#define FSTV0910_BYPFIFOBCHF 0xfa800010 -+#define FSTV0910_INVLLRSIGN 0xfa800008 -+#define FSTV0910_SHORTMULT 0xfa800004 -+#define FSTV0910_ENSTOPDEC 0xfa800002 -+ -+/*GENCFG*/ -+#define RSTV0910_GENCFG 0xfa86 -+#define FSTV0910_LEG_ITER 0xfa860040 -+#define FSTV0910_NOSHFRD1 0xfa860020 -+#define FSTV0910_BROADCAST 0xfa860010 -+#define FSTV0910_NOSHFRD2 0xfa860008 -+#define FSTV0910_BCHERRFLAG 0xfa860004 -+#define FSTV0910_CROSSINPUT 0xfa860002 -+#define FSTV0910_DDEMOD 0xfa860001 -+ -+/*LDPCERR1*/ -+#define RSTV0910_LDPCERR1 0xfa96 -+#define FSTV0910_LDPC_ERRORS1 0xfa9600ff -+ -+/*LDPCERR0*/ -+#define RSTV0910_LDPCERR0 0xfa97 -+#define FSTV0910_LDPC_ERRORS0 0xfa9700ff -+ -+/*BCHERR*/ -+#define RSTV0910_BCHERR 0xfa98 -+#define FSTV0910_ERRORFLAG 0xfa980010 -+#define FSTV0910_BCH_ERRORS_COUNTER 0xfa98000f -+ -+/*P1_MAXEXTRAITER*/ -+#define RSTV0910_P1_MAXEXTRAITER 0xfab1 -+#define FSTV0910_P1_MAX_EXTRA_ITER 0xfab100ff -+ -+/*P2_MAXEXTRAITER*/ -+#define RSTV0910_P2_MAXEXTRAITER 0xfab6 -+#define FSTV0910_P2_MAX_EXTRA_ITER 0xfab600ff -+ -+/*P1_STATUSITER*/ -+#define RSTV0910_P1_STATUSITER 0xfabc -+#define FSTV0910_P1_STATUS_ITER 0xfabc00ff -+ -+/*P1_STATUSMAXITER*/ -+#define RSTV0910_P1_STATUSMAXITER 0xfabd -+#define FSTV0910_P1_STATUS_MAX_ITER 0xfabd00ff -+ -+/*P2_STATUSITER*/ -+#define RSTV0910_P2_STATUSITER 0xfabe -+#define FSTV0910_P2_STATUS_ITER 0xfabe00ff -+ -+/*P2_STATUSMAXITER*/ -+#define RSTV0910_P2_STATUSMAXITER 0xfabf -+#define FSTV0910_P2_STATUS_MAX_ITER 0xfabf00ff -+ -+/*P2_NBITER_NF4*/ -+#define RSTV0910_P2_NBITER_NF4 0xfac3 -+#define FSTV0910_P2_NBITER_NF_QPSK_1_2 0xfac300ff -+ -+/*P2_NBITER_NF5*/ -+#define RSTV0910_P2_NBITER_NF5 0xfac4 -+#define FSTV0910_P2_NBITER_NF_QPSK_3_5 0xfac400ff -+ -+/*P2_NBITER_NF6*/ -+#define RSTV0910_P2_NBITER_NF6 0xfac5 -+#define FSTV0910_P2_NBITER_NF_QPSK_2_3 0xfac500ff -+ -+/*P2_NBITER_NF7*/ -+#define RSTV0910_P2_NBITER_NF7 0xfac6 -+#define FSTV0910_P2_NBITER_NF_QPSK_3_4 0xfac600ff -+ -+/*P2_NBITER_NF8*/ -+#define RSTV0910_P2_NBITER_NF8 0xfac7 -+#define FSTV0910_P2_NBITER_NF_QPSK_4_5 0xfac700ff -+ -+/*P2_NBITER_NF9*/ -+#define RSTV0910_P2_NBITER_NF9 0xfac8 -+#define FSTV0910_P2_NBITER_NF_QPSK_5_6 0xfac800ff -+ -+/*P2_NBITER_NF10*/ -+#define RSTV0910_P2_NBITER_NF10 0xfac9 -+#define FSTV0910_P2_NBITER_NF_QPSK_8_9 0xfac900ff -+ -+/*P2_NBITER_NF11*/ -+#define RSTV0910_P2_NBITER_NF11 0xfaca -+#define FSTV0910_P2_NBITER_NF_QPSK_9_10 0xfaca00ff -+ -+/*P2_NBITER_NF12*/ -+#define RSTV0910_P2_NBITER_NF12 0xfacb -+#define FSTV0910_P2_NBITER_NF_8PSK_3_5 0xfacb00ff -+ -+/*P2_NBITER_NF13*/ -+#define RSTV0910_P2_NBITER_NF13 0xfacc -+#define FSTV0910_P2_NBITER_NF_8PSK_2_3 0xfacc00ff -+ -+/*P2_NBITER_NF14*/ -+#define RSTV0910_P2_NBITER_NF14 0xfacd -+#define FSTV0910_P2_NBITER_NF_8PSK_3_4 0xfacd00ff -+ -+/*P2_NBITER_NF15*/ -+#define RSTV0910_P2_NBITER_NF15 0xface -+#define FSTV0910_P2_NBITER_NF_8PSK_5_6 0xface00ff -+ -+/*P2_NBITER_NF16*/ -+#define RSTV0910_P2_NBITER_NF16 0xfacf -+#define FSTV0910_P2_NBITER_NF_8PSK_8_9 0xfacf00ff -+ -+/*P2_NBITER_NF17*/ -+#define RSTV0910_P2_NBITER_NF17 0xfad0 -+#define FSTV0910_P2_NBITER_NF_8PSK_9_10 0xfad000ff -+ -+/*TSTRES0*/ -+#define RSTV0910_TSTRES0 0xff11 -+#define FSTV0910_FRESFEC 0xff110080 -+#define FSTV0910_FRESTS 0xff110040 -+#define FSTV0910_FRESVIT1 0xff110020 -+#define FSTV0910_FRESVIT2 0xff110010 -+#define FSTV0910_FRESSYM1 0xff110008 -+#define FSTV0910_FRESSYM2 0xff110004 -+#define FSTV0910_FRESMAS 0xff110002 -+#define FSTV0910_FRESINT 0xff110001 -+ -+/*P2_TCTL4*/ -+#define RSTV0910_P2_TCTL4 0xff28 -+#define FSTV0910_P2_CFR2TOCFR1_DVBS1 0xff2800c0 -+#define FSTV0910_P2_TSTINV_PHERR 0xff280020 -+#define FSTV0910_P2_EN_PLHCALC 0xff280010 -+#define FSTV0910_P2_TETA3L_RSTTETA3D 0xff280008 -+#define FSTV0910_P2_DIS_FORCEBETA2 0xff280004 -+#define FSTV0910_P2_CAR3_NOTRACEBACK 0xff280002 -+#define FSTV0910_P2_CAR3_NOFORWARD 0xff280001 -+ -+/*P1_TCTL4*/ -+#define RSTV0910_P1_TCTL4 0xff48 -+#define FSTV0910_P1_CFR2TOCFR1_DVBS1 0xff4800c0 -+#define FSTV0910_P1_TSTINV_PHERR 0xff480020 -+#define FSTV0910_P1_EN_PLHCALC 0xff480010 -+#define FSTV0910_P1_TETA3L_RSTTETA3D 0xff480008 -+#define FSTV0910_P1_DIS_FORCEBETA2 0xff480004 -+#define FSTV0910_P1_CAR3_NOTRACEBACK 0xff480002 -+#define FSTV0910_P1_CAR3_NOFORWARD 0xff480001 -+ -+#define STV0910_NBREGS 735 -+#define STV0910_NBFIELDS 1776 -diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c -new file mode 100644 -index 0000000..fbd6365 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv6111.c -@@ -0,0 +1,450 @@ -+/* -+ * Driver for the ST STV6111 tuner -+ * -+ * Copyright (C) 2014 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+ -+static inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+ -+struct stv { -+ struct i2c_adapter *i2c; -+ u8 adr; -+ -+ u8 reg[11]; -+ u32 ref_freq; -+}; -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_err("stv6111: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("stv6111: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int write_regs(struct stv *state, int reg, int len) -+{ -+ u8 d[12]; -+ -+ memcpy(&d[1], &state->reg[reg], len); -+ d[0] = reg; -+ return i2c_write(state->i2c, state->adr, d, len + 1); -+} -+ -+#if 0 -+static int write_reg(struct stv *state, u8 reg, u8 val) -+{ -+ u8 d[2] = {reg, val}; -+ -+ return i2c_write(state->i2c, state->adr, d, 2); -+} -+#endif -+ -+static int read_reg(struct stv *state, u8 reg, u8 *val) -+{ -+ return i2c_read(state->i2c, state->adr, ®, 1, val, 1); -+} -+ -+static int read_regs(struct stv *state, u8 reg, u8 *val, int len) -+{ -+ return i2c_read(state->i2c, state->adr, ®, 1, val, len); -+} -+ -+static void dump_regs(struct stv *state) -+{ -+ u8 d[11], *c = &state->reg[0]; -+ -+ read_regs(state, 0, d, 11); -+ pr_info("stv6111_regs = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], -+ d[8], d[9], d[10]); -+ pr_info("reg[] = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], -+ c[8], c[9], c[10]); -+} -+ -+static int wait_for_call_done(struct stv *state, u8 mask) -+{ -+ int status = 0; -+ u32 LockRetryCount = 10; -+ -+ while (LockRetryCount > 0) { -+ u8 Status; -+ -+ status = read_reg(state, 9, &Status); -+ if (status < 0) -+ return status; -+ -+ if ((Status & mask) == 0) -+ break; -+ usleep_range(4000, 6000); -+ LockRetryCount -= 1; -+ -+ status = -1; -+ } -+ return status; -+} -+ -+static void init_state(struct stv *state) -+{ -+ u32 clkdiv = 0; -+ u32 agcmode = 0; -+ u32 agcref = 2; -+ u32 agcset = 0xffffffff; -+ u32 bbmode = 0xffffffff; -+ -+ state->reg[0] = 0x08; -+ state->reg[1] = 0x41; -+ state->reg[2] = 0x8f; -+ state->reg[3] = 0x00; -+ state->reg[4] = 0xce; -+ state->reg[5] = 0x54; -+ state->reg[6] = 0x55; -+ state->reg[7] = 0x45; -+ state->reg[8] = 0x46; -+ state->reg[9] = 0xbd; -+ state->reg[10] = 0x11; -+ -+ state->ref_freq = 16000; -+ -+ -+ if (clkdiv <= 3) -+ state->reg[0x00] |= (clkdiv & 0x03); -+ if (agcmode <= 3) { -+ state->reg[0x03] |= (agcmode << 5); -+ if (agcmode == 0x01) -+ state->reg[0x01] |= 0x30; -+ } -+ if (bbmode <= 3) -+ state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4); -+ if (agcref <= 7) -+ state->reg[0x03] |= agcref; -+ if (agcset <= 31) -+ state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40; -+} -+ -+static int attach_init(struct stv *state) -+{ -+ if (write_regs(state, 0, 11)) -+ return -1; -+ pr_info("attach_init OK\n"); -+ dump_regs(state); -+ return 0; -+} -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ /* struct tda_state *state = fe->tuner_priv; */ -+ -+ pr_info("tuner sleep\n"); -+ return 0; -+} -+ -+static int init(struct dvb_frontend *fe) -+{ -+ /* struct tda_state *state = fe->tuner_priv; */ -+ pr_info("init\n"); -+ return 0; -+} -+ -+static int release(struct dvb_frontend *fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ return 0; -+} -+ -+static int set_bandwidth(struct dvb_frontend *fe, u32 CutOffFrequency) -+{ -+ struct stv *state = fe->tuner_priv; -+ u32 index = (CutOffFrequency + 999999) / 1000000; -+ -+ if (index < 6) -+ index = 6; -+ if (index > 50) -+ index = 50; -+ if ((state->reg[0x08] & ~0xFC) == ((index-6) << 2)) -+ return 0; -+ -+ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index-6) << 2); -+ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x08; -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ write_regs(state, 0x08, 2); -+ wait_for_call_done(state, 0x08); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ return 0; -+} -+ -+static int set_lof(struct stv *state, u32 LocalFrequency, u32 CutOffFrequency) -+{ -+ u32 index = (CutOffFrequency + 999999) / 1000000; -+ u32 Frequency = (LocalFrequency + 500) / 1000; -+ u32 p = 1, psel = 0, fvco, div, frac; -+ u8 Icp, tmp; -+ -+ pr_info("F = %u, COF = %u\n", Frequency, CutOffFrequency); -+ if (index < 6) -+ index = 6; -+ if (index > 50) -+ index = 50; -+ -+ if (Frequency <= 1300000) { -+ p = 4; -+ psel = 1; -+ } else { -+ p = 2; -+ psel = 0; -+ } -+ fvco = Frequency * p; -+ div = fvco / state->ref_freq; -+ frac = fvco % state->ref_freq; -+ frac = MulDiv32(frac, 0x40000, state->ref_freq); -+ -+ Icp = 0; -+ if (fvco < 2700000) -+ Icp = 0; -+ else if (fvco < 2950000) -+ Icp = 1; -+ else if (fvco < 3300000) -+ Icp = 2; -+ else if (fvco < 3700000) -+ Icp = 3; -+ else if (fvco < 4200000) -+ Icp = 5; -+ else if (fvco < 4800000) -+ Icp = 6; -+ else -+ Icp = 7; -+ -+ state->reg[0x02] |= 0x80; /* LNA IIP3 Mode */ -+ -+ state->reg[0x03] = (state->reg[0x03] & ~0x80) | (psel << 7); -+ state->reg[0x04] = (div & 0xFF); -+ state->reg[0x05] = (((div >> 8) & 0x01) | ((frac & 0x7F) << 1)) & 0xff; -+ state->reg[0x06] = ((frac >> 7) & 0xFF); -+ state->reg[0x07] = (state->reg[0x07] & ~0x07) | ((frac >> 15) & 0x07); -+ state->reg[0x07] = (state->reg[0x07] & ~0xE0) | (Icp << 5); -+ -+ state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2); -+ /* Start cal vco,CF */ -+ state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x0C; -+ write_regs(state, 2, 8); -+ -+ wait_for_call_done(state, 0x0C); -+ -+ usleep_range(10000, 12000); -+ -+ read_reg(state, 0x03, &tmp); -+ if (tmp & 0x10) { -+ state->reg[0x02] &= ~0x80; /* LNA NF Mode */ -+ write_regs(state, 2, 1); -+ } -+ read_reg(state, 0x08, &tmp); -+ -+ dump_regs(state); -+ return 0; -+} -+ -+static int set_params(struct dvb_frontend *fe) -+{ -+ struct stv *state = fe->tuner_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ int status; -+ u32 freq, symb, cutoff; -+ -+ if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2) -+ return -EINVAL; -+ -+ freq = p->frequency * 1000; -+ symb = p->symbol_rate; -+ cutoff = 5000000 + MulDiv32(p->symbol_rate, 135, 200); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ set_lof(state, freq, cutoff); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ return status; -+} -+ -+static int get_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ *frequency = 0; -+ return 0; -+} -+ -+static u32 AGC_Gain[] = { -+ 000, /* 0.0 */ -+ 000, /* 0.1 */ -+ 1000, /* 0.2 */ -+ 2000, /* 0.3 */ -+ 3000, /* 0.4 */ -+ 4000, /* 0.5 */ -+ 5000, /* 0.6 */ -+ 6000, /* 0.7 */ -+ 7000, /* 0.8 */ -+ 14000, /* 0.9 */ -+ 20000, /* 1.0 */ -+ 27000, /* 1.1 */ -+ 32000, /* 1.2 */ -+ 37000, /* 1.3 */ -+ 42000, /* 1.4 */ -+ 47000, /* 1.5 */ -+ 50000, /* 1.6 */ -+ 53000, /* 1.7 */ -+ 56000, /* 1.8 */ -+ 58000, /* 1.9 */ -+ 60000, /* 2.0 */ -+ 62000, /* 2.1 */ -+ 63000, /* 2.2 */ -+ 64000, /* 2.3 */ -+ 64500, /* 2.4 */ -+ 65000, /* 2.5 */ -+ 65500, /* 2.6 */ -+ 66000, /* 2.7 */ -+ 66500, /* 2.8 */ -+ 67000, /* 2.9 */ -+}; -+ -+static int get_rf_strength(struct dvb_frontend *fe, u16 *st) -+{ -+ *st = 0; -+#if 0 -+ struct stv *state = fe->tuner_priv; -+ s32 Gain; -+ u32 Index = RFAgc / 100; -+ if (Index >= (sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1)) -+ Gain = AGC_Gain[sizeof(AGC_Gain) / sizeof(AGC_Gain[0]) - 1]; -+ else -+ Gain = AGC_Gain[Index] + -+ ((AGC_Gain[Index+1] - AGC_Gain[Index]) * -+ (RFAgc % 100)) / 100; -+ *st = Gain; -+#endif -+ return 0; -+} -+ -+static int get_if(struct dvb_frontend *fe, u32 *frequency) -+{ -+ *frequency = 0; -+ return 0; -+} -+ -+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -+{ -+ return 0; -+} -+ -+static struct dvb_tuner_ops tuner_ops = { -+ .info = { -+ .name = "STV6111", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_step = 0 -+ }, -+ .init = init, -+ .sleep = sleep, -+ .set_params = set_params, -+ .release = release, -+ .get_frequency = get_frequency, -+ .get_if_frequency = get_if, -+ .get_bandwidth = get_bandwidth, -+ .get_rf_strength = get_rf_strength, -+ .set_bandwidth = set_bandwidth, -+}; -+ -+struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr) -+{ -+ struct stv *state; -+ int stat; -+ -+ state = kzalloc(sizeof(struct stv), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ state->adr = adr; -+ state->i2c = i2c; -+ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); -+ init_state(state); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ stat = attach_init(state); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ if (stat < 0) { -+ kfree(state); -+ return 0; -+ } -+ fe->tuner_priv = state; -+ return fe; -+} -+EXPORT_SYMBOL_GPL(stv6111_attach); -+ -+MODULE_DESCRIPTION("STV6111 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Local variables: -+ * c-basic-offset: 8 -+ * End: -+ */ -diff --git a/drivers/media/dvb-frontends/stv6111.h b/drivers/media/dvb-frontends/stv6111.h -new file mode 100644 -index 0000000..31d200c ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv6111.h -@@ -0,0 +1,5 @@ -+#ifndef _STV6111_H_ -+#define _STV6111_H_ -+struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr); -+#endif -diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c -new file mode 100644 -index 0000000..7d99fd5 ---- /dev/null -+++ b/drivers/media/dvb-frontends/tda18212dd.c -@@ -0,0 +1,974 @@ -+/* -+ * tda18212: Driver for the TDA18212 tuner -+ * -+ * Copyright (C) 2011-2013 Digital Devices GmbH -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+ -+#ifndef CHK_ERROR -+#define CHK_ERROR(s) if ((status = s) < 0) break -+#endif -+ -+#define MASTER_PSM_AGC1 0 -+#define MASTER_AGC1_6_15dB 1 -+ -+#define SLAVE_PSM_AGC1 1 -+#define SLAVE_AGC1_6_15dB 0 -+ -+/* 0 = 2 Vpp ... 2 = 1 Vpp, 7 = 0.5 Vpp */ -+#define IF_LEVEL_DVBC 2 -+#define IF_LEVEL_DVBT 2 -+ -+enum { -+ ID_1 = 0x00, -+ ID_2 = 0x01, -+ ID_3 = 0x02, -+ THERMO_1, -+ THERMO_2, -+ POWER_STATE_1, -+ POWER_STATE_2, -+ INPUT_POWER_LEVEL, -+ IRQ_STATUS, -+ IRQ_ENABLE, -+ IRQ_CLEAR, -+ IRQ_SET, -+ AGC1_1, -+ AGC2_1, -+ AGCK_1, -+ RF_AGC_1, -+ IR_MIXER_1 = 0x10, -+ AGC5_1, -+ IF_AGC, -+ IF_1, -+ REFERENCE, -+ IF_FREQUENCY_1, -+ RF_FREQUENCY_1, -+ RF_FREQUENCY_2, -+ RF_FREQUENCY_3, -+ MSM_1, -+ MSM_2, -+ PSM_1, -+ DCC_1, -+ FLO_MAX, -+ IR_CAL_1, -+ IR_CAL_2, -+ IR_CAL_3 = 0x20, -+ IR_CAL_4, -+ VSYNC_MGT, -+ IR_MIXER_2, -+ AGC1_2, -+ AGC5_2, -+ RF_CAL_1, -+ RF_CAL_2, -+ RF_CAL_3, -+ RF_CAL_4, -+ RF_CAL_5, -+ RF_CAL_6, -+ RF_FILTER_1, -+ RF_FILTER_2, -+ RF_FILTER_3, -+ RF_BAND_PASS_FILTER, -+ CP_CURRENT = 0x30, -+ AGC_DET_OUT = 0x31, -+ RF_AGC_GAIN_1 = 0x32, -+ RF_AGC_GAIN_2 = 0x33, -+ IF_AGC_GAIN = 0x34, -+ POWER_1 = 0x35, -+ POWER_2 = 0x36, -+ MISC_1, -+ RFCAL_LOG_1, -+ RFCAL_LOG_2, -+ RFCAL_LOG_3, -+ RFCAL_LOG_4, -+ RFCAL_LOG_5, -+ RFCAL_LOG_6, -+ RFCAL_LOG_7, -+ RFCAL_LOG_8, -+ RFCAL_LOG_9 = 0x40, -+ RFCAL_LOG_10 = 0x41, -+ RFCAL_LOG_11 = 0x42, -+ RFCAL_LOG_12 = 0x43, -+ REG_MAX, -+}; -+ -+enum HF_Standard { -+ HF_None = 0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio, -+ HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ, -+ HF_DVBT, HF_ATSC, HF_DVBC_6MHZ, HF_DVBC_7MHZ, -+ HF_DVBC_8MHZ, HF_DVBC -+}; -+ -+struct SStandardParams { -+ s32 m_IFFrequency; -+ u32 m_BandWidth; -+ u8 m_IF_1; /* FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3 */ -+ u8 m_IR_MIXER_2; /* 03 :6 HI_Pass:1 DC_Notch:1 */ -+ u8 m_AGC1_1; /* 0F :4 AGC1_Top:4 */ -+ u8 m_AGC2_1; /* 0F :4 AGC2_Top:4 */ -+ /*EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 */ -+ u8 m_RF_AGC_1_Low; -+ /*EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 */ -+ u8 m_RF_AGC_1_High; -+ u8 m_IR_MIXER_1; /* 0F :4 IR_mixer_Top:4 */ -+ u8 m_AGC5_1; /* 1F :3 AGC5_Ana AGC5_Top:4 */ -+ u8 m_AGCK_1; /* 0F :4 AGCK_Step:2 AGCK_Mode:2 */ -+ u8 m_PSM_1; /* 20 :2 PSM_StoB:1 :5 */ -+ bool m_AGC1_Freeze; -+ bool m_LTO_STO_immune; -+}; -+ -+#if 0 -+static struct SStandardParams -+m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = { -+ { 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_6MHZ */ -+ { 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_7MHZ */ -+ { 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_8MHZ */ -+ { 0000000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, /* HF_DVBT (Unused) */ -+ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, -+ 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, /* HF_ATSC */ -+ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_6MHZ */ -+ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, -+ /* HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) */ -+ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_8MHZ */ -+}; -+#else -+static struct SStandardParams -+m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = { -+ { 4000000, 6000000, 0x41, 0x03, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_6MHZ */ -+ { 4500000, 7000000, 0x42, 0x03, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_7MHZ */ -+ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x2B, -+ 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, /* HF_DVBT_8MHZ */ -+ /* ------------------------------ */ -+ { 0000000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, /* HF_DVBT (Unused)*/ -+ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, -+ 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, /* HF_ATSC */ -+ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_6MHZ */ -+ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, -+ /* HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) */ -+ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, -+ 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, /* HF_DVBC_8MHZ */ -+}; -+#endif -+ -+struct tda_state { -+ struct i2c_adapter *i2c; -+ u8 adr; -+ -+ enum HF_Standard m_Standard; -+ u32 m_Frequency; -+ u32 IF; -+ -+ bool m_isMaster; -+ bool m_bPowerMeasurement; -+ bool m_bLTEnable; -+ bool m_bEnableFreeze; -+ -+ u16 m_ID; -+ -+ s32 m_SettlingTime; -+ -+ u8 m_IFLevelDVBC; -+ u8 m_IFLevelDVBT; -+ u8 Regs[REG_MAX]; -+ u8 m_LastPowerLevel; -+}; -+ -+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = data, .len = len} }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ pr_err("tda18212dd: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ pr_err("tda18212: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int write_regs(struct tda_state *state, -+ u8 SubAddr, u8 *Regs, u16 nRegs) -+{ -+ u8 data[REG_MAX + 1]; -+ -+ data[0] = SubAddr; -+ memcpy(data + 1, Regs, nRegs); -+ return i2c_write(state->i2c, state->adr, data, nRegs + 1); -+} -+ -+static int write_reg(struct tda_state *state, u8 SubAddr, u8 Reg) -+{ -+ u8 msg[2] = {SubAddr, Reg}; -+ -+ return i2c_write(state->i2c, state->adr, msg, 2); -+} -+ -+static int Read(struct tda_state *state, u8 *Regs) -+{ -+ return i2c_readn(state->i2c, state->adr, Regs, REG_MAX); -+} -+ -+static int update_regs(struct tda_state *state, u8 RegFrom, u8 RegTo) -+{ -+ return write_regs(state, RegFrom, -+ &state->Regs[RegFrom], RegTo-RegFrom + 1); -+} -+ -+static int update_reg(struct tda_state *state, u8 Reg) -+{ -+ return write_reg(state, Reg, state->Regs[Reg]); -+} -+ -+ -+static int read_regs(struct tda_state *state, -+ u8 SubAddr, u8 *Regs, u16 nRegs) -+{ -+ return i2c_read(state->i2c, state->adr, -+ &SubAddr, 1, Regs, nRegs); -+} -+ -+static int read_reg(struct tda_state *state, -+ u8 SubAddr, u8 *Reg) -+{ -+ return i2c_read(state->i2c, state->adr, -+ &SubAddr, 1, Reg, 1); -+} -+ -+static int read_reg1(struct tda_state *state, u8 Reg) -+{ -+ return read_reg(state, Reg, &state->Regs[Reg]); -+} -+ -+static void init_state(struct tda_state *state) -+{ -+ u32 ulIFLevelDVBC = IF_LEVEL_DVBC; -+ u32 ulIFLevelDVBT = IF_LEVEL_DVBT; -+ u32 ulPowerMeasurement = 1; -+ u32 ulLTEnable = 1; -+ u32 ulEnableFreeze = 0; -+ -+ state->m_Frequency = 0; -+ state->m_isMaster = true; -+ state->m_ID = 0; -+ state->m_LastPowerLevel = 0xFF; -+ state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07); -+ state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07); -+ state->m_bPowerMeasurement = (ulPowerMeasurement != 0); -+ state->m_bLTEnable = (ulLTEnable != 0); -+ state->m_bEnableFreeze = (ulEnableFreeze != 0); -+} -+ -+static int StartCalibration(struct tda_state *state) -+{ -+ int status = 0; -+ do { -+ state->Regs[POWER_2] &= ~0x02; /* RSSI CK = 31.25 kHz */ -+ CHK_ERROR(update_reg(state, POWER_2)); -+ -+ /* AGC1 Do Step = 2 */ -+ state->Regs[AGC1_2] = (state->Regs[AGC1_2] & ~0x60) | 0x40; -+ CHK_ERROR(update_reg(state, AGC1_2)); /* AGC */ -+ -+ /* AGC2 Do Step = 1 */ -+ state->Regs[RF_FILTER_3] = -+ (state->Regs[RF_FILTER_3] & ~0xC0) | 0x40; -+ CHK_ERROR(update_reg(state, RF_FILTER_3)); -+ -+ /* AGCs Assym Up Step = 3 // Datasheet sets all bits to 1! */ -+ state->Regs[AGCK_1] |= 0xC0; -+ CHK_ERROR(update_reg(state, AGCK_1)); -+ -+ /* AGCs Assym Do Step = 2 */ -+ state->Regs[AGC5_1] = (state->Regs[AGC5_1] & ~0x60) | 0x40; -+ CHK_ERROR(update_reg(state, AGC5_1)); -+ -+ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ state->Regs[MSM_1] = 0x3B; /* Set Calibration */ -+ state->Regs[MSM_2] = 0x01; /* Start MSM */ -+ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); -+ state->Regs[MSM_2] = 0x00; -+ } while (0); -+ return status; -+} -+ -+static int FinishCalibration(struct tda_state *state) -+{ -+ int status = 0; -+ u8 RFCal_Log[12]; -+ -+ do { -+ u8 IRQ = 0; -+ int Timeout = 150; /* 1.5 s */ -+ while (true) { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if ((IRQ & 0x80) != 0) -+ break; -+ Timeout -= 1; -+ if (Timeout == 0) { -+ status = -1; -+ break; -+ } -+ usleep_range(10000, 12000); -+ } -+ CHK_ERROR(status); -+ -+ state->Regs[FLO_MAX] = 0x0A; -+ CHK_ERROR(update_reg(state, FLO_MAX)); -+ -+ state->Regs[AGC1_1] &= ~0xC0; -+ if (state->m_bLTEnable) -+ state->Regs[AGC1_1] |= 0x80; /* LTEnable */ -+ -+ state->Regs[AGC1_1] |= (state->m_isMaster ? -+ MASTER_AGC1_6_15dB : -+ SLAVE_AGC1_6_15dB) << 6; -+ CHK_ERROR(update_reg(state, AGC1_1)); -+ -+ state->Regs[PSM_1] &= ~0xC0; -+ state->Regs[PSM_1] |= (state->m_isMaster ? -+ MASTER_PSM_AGC1 : SLAVE_PSM_AGC1) << 6; -+ CHK_ERROR(update_reg(state, PSM_1)); -+ -+ state->Regs[REFERENCE] |= 0x03; /* XTOUT = 3 */ -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ CHK_ERROR(read_regs(state, RFCAL_LOG_1, -+ RFCal_Log, sizeof(RFCal_Log))); -+ } while (0); -+ return status; -+} -+ -+static int PowerOn(struct tda_state *state) -+{ -+ state->Regs[POWER_STATE_2] &= ~0x0F; -+ update_reg(state, POWER_STATE_2); -+ /* Digital clock source = Sigma Delta */ -+ state->Regs[REFERENCE] |= 0x40; -+ update_reg(state, REFERENCE); -+ return 0; -+} -+ -+static int Standby(struct tda_state *state) -+{ -+ int status = 0; -+ -+ do { -+ /* Digital clock source = Quarz */ -+ state->Regs[REFERENCE] &= ~0x40; -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ state->Regs[POWER_STATE_2] &= ~0x0F; -+ state->Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E; -+ CHK_ERROR(update_reg(state, POWER_STATE_2)); -+ } while (0); -+ return status; -+} -+ -+static int attach_init(struct tda_state *state) -+{ -+ int stat = 0; -+ u8 Id[2]; -+ u8 PowerState = 0x00; -+ -+ state->m_Standard = HF_None; -+ -+ /* first read after cold reset sometimes fails on some cards, -+ try twice */ -+ stat = read_regs(state, ID_1, Id, sizeof(Id)); -+ stat = read_regs(state, ID_1, Id, sizeof(Id)); -+ if (stat < 0) -+ return -1; -+ -+ state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1]; -+ state->m_isMaster = ((Id[0] & 0x80) != 0); -+ if (!state->m_isMaster) -+ state->m_bLTEnable = false; -+ -+ pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID, -+ state->m_isMaster ? "master" : "slave"); -+ -+ if (state->m_ID != 18212) -+ return -1; -+ -+ stat = read_reg(state, POWER_STATE_1 , &PowerState); -+ if (stat < 0) -+ return stat; -+ -+ pr_info("tda18212dd: PowerState %02x\n", PowerState); -+ -+ if (state->m_isMaster) { -+ if (PowerState & 0x02) { -+ /* msleep for XTAL Calibration -+ (on a PC this should be long done) */ -+ u8 IRQStatus = 0; -+ int Timeout = 10; -+ -+ while (Timeout > 0) { -+ read_reg(state, IRQ_STATUS, &IRQStatus); -+ if (IRQStatus & 0x20) -+ break; -+ Timeout -= 1; -+ usleep_range(10000, 12000); -+ } -+ if ((IRQStatus & 0x20) == 0) -+ stat = -ETIMEDOUT; -+ } -+ } else { -+ write_reg(state, FLO_MAX, 0x00); -+ write_reg(state, CP_CURRENT, 0x68); -+ } -+ Read(state, state->Regs); -+ -+ PowerOn(state); -+ StartCalibration(state); -+ FinishCalibration(state); -+ Standby(state); -+ -+ { -+ u8 RFCal_Log[12]; -+ -+ read_regs(state, RFCAL_LOG_1, RFCal_Log, sizeof(RFCal_Log)); -+ pr_info("RFCal Log: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ RFCal_Log[0], RFCal_Log[1], -+ RFCal_Log[2], RFCal_Log[3], -+ RFCal_Log[4], RFCal_Log[5], -+ RFCal_Log[6], RFCal_Log[7], -+ RFCal_Log[8], RFCal_Log[9], -+ RFCal_Log[10], RFCal_Log[11]); -+ } -+ return stat; -+} -+ -+static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) -+{ -+ int status = 0; -+ -+ do { -+ u8 IRQ = 0; -+ int Timeout = 70; /* 700 ms */ -+ -+ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ state->Regs[MSM_1] = 0x80; /* power measurement */ -+ state->Regs[MSM_2] = 0x01; /* Start MSM */ -+ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); -+ state->Regs[MSM_2] = 0x00; -+ -+ while (true) { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if ((IRQ & 0x80) != 0) -+ break; -+ Timeout -= 1; -+ if (Timeout == 0) { -+ status = -1; -+ break; -+ } -+ usleep_range(10000, 12000); -+ } -+ CHK_ERROR(status); -+ -+ CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL)); -+ *pPowerLevel = state->Regs[INPUT_POWER_LEVEL] & 0x7F; -+ -+ if (*pPowerLevel > 110) -+ *pPowerLevel = 110; -+ } while (0); -+ /* pr_info("PL %d\n", *pPowerLevel); */ -+ return status; -+} -+ -+static int SetFrequency(struct tda_state *state, u32 Frequency, -+ enum HF_Standard Standard) -+{ -+ int status = 0; -+ struct SStandardParams *StandardParams; -+ u32 f = Frequency / 1000; -+ u8 IRQ = 0; -+ int Timeout = 25; /* 250 ms */ -+ u32 fRatio = Frequency / 16000000; -+ u32 fDelta = Frequency - fRatio * 16000000; -+ -+ if (Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ) -+ return -EINVAL; -+ StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ]; -+ -+ if (StandardParams->m_IFFrequency == 0) -+ return -EINVAL; -+ state->m_Standard = HF_None; -+ state->m_Frequency = 0; -+ -+ do { -+ /* IF Level */ -+ state->Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? -+ state->m_IFLevelDVBC : state->m_IFLevelDVBT; -+ CHK_ERROR(update_reg(state, IF_AGC)); -+ -+ /* Standard setup */ -+ state->Regs[IF_1] = StandardParams->m_IF_1; -+ CHK_ERROR(update_reg(state, IF_1)); -+ -+ state->Regs[IR_MIXER_2] = (state->Regs[IR_MIXER_2] & ~0x03) | -+ StandardParams->m_IR_MIXER_2; -+ CHK_ERROR(update_reg(state, IR_MIXER_2)); -+ -+ state->Regs[AGC1_1] = (state->Regs[AGC1_1] & ~0x0F) | -+ StandardParams->m_AGC1_1; -+ CHK_ERROR(update_reg(state, AGC1_1)); -+ -+ state->Regs[AGC2_1] = (state->Regs[AGC2_1] & ~0x0F) | -+ StandardParams->m_AGC2_1; -+ CHK_ERROR(update_reg(state, AGC2_1)); -+ -+ state->Regs[RF_AGC_1] &= ~0xEF; -+ if (Frequency < 291000000) -+ state->Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low; -+ else -+ state->Regs[RF_AGC_1] |= -+ StandardParams->m_RF_AGC_1_High; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ -+ state->Regs[IR_MIXER_1] = -+ (state->Regs[IR_MIXER_1] & ~0x0F) | -+ StandardParams->m_IR_MIXER_1; -+ CHK_ERROR(update_reg(state, IR_MIXER_1)); -+ -+ state->Regs[AGC5_1] = (state->Regs[AGC5_1] & ~0x1F) | -+ StandardParams->m_AGC5_1; -+ CHK_ERROR(update_reg(state, AGC5_1)); -+ -+ state->Regs[AGCK_1] = (state->Regs[AGCK_1] & ~0x0F) | -+ StandardParams->m_AGCK_1; -+ CHK_ERROR(update_reg(state, AGCK_1)); -+ -+ state->Regs[PSM_1] = (state->Regs[PSM_1] & ~0x20) | -+ StandardParams->m_PSM_1; -+ CHK_ERROR(update_reg(state, PSM_1)); -+ -+ state->Regs[IF_FREQUENCY_1] = (StandardParams->m_IFFrequency / -+ 50000); -+ CHK_ERROR(update_reg(state, IF_FREQUENCY_1)); -+ -+ if (state->m_isMaster && StandardParams->m_LTO_STO_immune) { -+ u8 tmp; -+ u8 RF_Filter_Gain; -+ -+ CHK_ERROR(read_reg(state, RF_AGC_GAIN_1, &tmp)); -+ RF_Filter_Gain = (tmp & 0x30) >> 4; -+ -+ state->Regs[RF_FILTER_1] = -+ (state->Regs[RF_FILTER_1] & ~0x0C) | -+ (RF_Filter_Gain << 2); -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ -+ state->Regs[RF_FILTER_1] |= 0x10; /* Force */ -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ -+ while (RF_Filter_Gain != 0) { -+ RF_Filter_Gain -= 1; -+ state->Regs[RF_FILTER_1] = -+ (state->Regs[RF_FILTER_1] & ~0x0C) | -+ (RF_Filter_Gain << 2); -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ usleep_range(10000, 12000); -+ } -+ CHK_ERROR(status); -+ -+ state->Regs[RF_AGC_1] |= 0x08; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ } -+ -+ state->Regs[IRQ_CLEAR] |= 0x80; /* Reset IRQ */ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ CHK_ERROR(PowerOn(state)); -+ -+ state->Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF); -+ state->Regs[RF_FREQUENCY_2] = ((f >> 8) & 0xFF); -+ state->Regs[RF_FREQUENCY_3] = (f & 0xFF); -+ CHK_ERROR(update_regs(state, RF_FREQUENCY_1, RF_FREQUENCY_3)); -+ -+ state->Regs[MSM_1] = 0x41; /* Tune */ -+ state->Regs[MSM_2] = 0x01; /* Start MSM */ -+ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); -+ state->Regs[MSM_2] = 0x00; -+ -+ while (true) { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if ((IRQ & 0x80) != 0) -+ break; -+ Timeout -= 1; -+ if (Timeout == 0) { -+ status = -1; -+ break; -+ } -+ usleep_range(10000, 12000); -+ } -+ CHK_ERROR(status); -+ -+ if (state->m_isMaster && StandardParams->m_LTO_STO_immune) { -+ state->Regs[RF_AGC_1] &= ~0x08; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ -+ msleep(50); -+ -+ state->Regs[RF_FILTER_1] &= ~0x10; /* remove force */ -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ } -+ -+ /* Spur reduction */ -+ -+ if (Frequency < 72000000) -+ state->Regs[REFERENCE] |= 0x40; /* Set digital clock */ -+ else if (Frequency < 104000000) -+ state->Regs[REFERENCE] &= ~0x40; /*Clear digital clock*/ -+ else if (Frequency < 120000000) -+ state->Regs[REFERENCE] |= 0x40; /* Set digital clock */ -+ else { -+ if (fDelta <= 8000000) { -+ /* Clear or set digital clock */ -+ if (fRatio & 1) -+ state->Regs[REFERENCE] &= ~0x40; -+ else -+ state->Regs[REFERENCE] |= 0x40; -+ } else { -+ /* Set or clear digital clock */ -+ if (fRatio & 1) -+ state->Regs[REFERENCE] |= 0x40; -+ else -+ state->Regs[REFERENCE] &= ~0x40; -+ } -+ -+ } -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ if (StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze) { -+ u8 tmp; -+ int AGC1GainMin = 0; -+ int nSteps = 10; -+ int Step = 0; -+ -+ CHK_ERROR(read_reg(state, AGC1_2, &tmp)); -+ if ((tmp & 0x80) == 0) { -+ state->Regs[AGC1_2] |= 0x80; /* Loop off */ -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ state->Regs[AGC1_2] |= 0x10; /* Force gain */ -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ /* Adapt */ -+ if (state->Regs[AGC1_1] & 0x40) { /* AGC1_6_15dB set */ -+ AGC1GainMin = 6; -+ nSteps = 4; -+ } -+ while (Step < nSteps) { -+ int Down = 0; -+ int Up = 0, i; -+ u8 AGC1_Gain; -+ -+ Step = Step + 1; -+ -+ for (i = 0; i < 40; i += 1) { -+ CHK_ERROR(read_reg(state, AGC_DET_OUT, -+ &tmp)); -+ Up += (tmp & 0x02) ? 1 : -4; -+ Down += (tmp & 0x01) ? 14 : -1; -+ usleep_range(1000, 2000); -+ } -+ CHK_ERROR(status); -+ AGC1_Gain = (state->Regs[AGC1_2] & 0x0F); -+ if (Up >= 15 && AGC1_Gain != 9) { -+ state->Regs[AGC1_2] = -+ (state->Regs[AGC1_2] & ~0x0F) | -+ (AGC1_Gain + 1); -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } else if (Down >= 10 && -+ AGC1_Gain != AGC1GainMin) { -+ state->Regs[AGC1_2] = -+ (state->Regs[AGC1_2] & ~0x0F) | -+ (AGC1_Gain - 1); -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } else -+ Step = nSteps; -+ } -+ } else { -+ state->Regs[AGC1_2] &= ~0x10; /* unforce gain */ -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ state->Regs[AGC1_2] &= ~0x80; /* Loop on */ -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ -+ state->m_Standard = Standard; -+ state->m_Frequency = Frequency; -+ -+ if (state->m_bPowerMeasurement) -+ PowerMeasurement(state, &state->m_LastPowerLevel); -+ } while (0); -+ -+ return status; -+} -+ -+static int sleep(struct dvb_frontend *fe) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ Standby(state); -+ return 0; -+} -+ -+static int init(struct dvb_frontend *fe) -+{ -+ /* struct tda_state *state = fe->tuner_priv; */ -+ return 0; -+} -+ -+static int release(struct dvb_frontend *fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ return 0; -+} -+ -+#ifndef USE_API3 -+static int set_params(struct dvb_frontend *fe) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ int status = 0; -+ int Standard; -+ u32 bw; -+ -+ bw = (p->bandwidth_hz + 999999) / 1000000; -+ state->m_Frequency = p->frequency; -+ /*pr_info("tuner bw=%u freq=%u\n", bw, state->m_Frequency);*/ -+ if (p->delivery_system == SYS_DVBT || -+ p->delivery_system == SYS_DVBT2 || -+ p->delivery_system == SYS_ISDBT) { -+ switch (bw) { -+ case 6: -+ Standard = HF_DVBT_6MHZ; -+ break; -+ case 7: -+ Standard = HF_DVBT_7MHZ; -+ break; -+ default: -+ case 8: -+ Standard = HF_DVBT_8MHZ; -+ break; -+ } -+ } else if (p->delivery_system == SYS_DVBC_ANNEX_A) { -+ switch (bw) { -+ case 6: -+ Standard = HF_DVBC_6MHZ; -+ break; -+ case 7: -+ Standard = HF_DVBC_7MHZ; -+ break; -+ default: -+ case 8: -+ Standard = HF_DVBC_8MHZ; -+ break; -+ } -+ } else -+ return -EINVAL; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ SetFrequency(state, state->m_Frequency, Standard); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ return status; -+} -+#else -+static int set_params(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *params) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ int status = 0; -+ int Standard; -+ -+ state->m_Frequency = params->frequency; -+ -+ if (fe->ops.info.type == FE_OFDM) -+ switch (params->u.ofdm.bandwidth) { -+ case BANDWIDTH_6_MHZ: -+ Standard = HF_DVBT_6MHZ; -+ break; -+ case BANDWIDTH_7_MHZ: -+ Standard = HF_DVBT_7MHZ; -+ break; -+ default: -+ case BANDWIDTH_8_MHZ: -+ Standard = HF_DVBT_8MHZ; -+ break; -+ } -+ else if (fe->ops.info.type == FE_QAM) { -+ Standard = HF_DVBC_8MHZ; -+ } else -+ return -EINVAL; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ SetFrequency(state, state->m_Frequency, Standard); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ return status; -+} -+#endif -+ -+static int get_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ *frequency = state->IF; -+ return 0; -+} -+ -+static int get_rf_strength(struct dvb_frontend *fe, u16 *st) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ *st = state->m_LastPowerLevel; -+ return 0; -+} -+ -+static int get_if(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ state->IF = 0; -+ if (state->m_Standard < HF_DVBT_6MHZ || -+ state->m_Standard > HF_DVBC_8MHZ) -+ return 0; -+ state->IF = m_StandardTable[state->m_Standard - -+ HF_DVBT_6MHZ].m_IFFrequency; -+ *frequency = state->IF; -+ return 0; -+} -+ -+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -+{ -+ /* struct tda_state *state = fe->tuner_priv; */ -+ /* *bandwidth = priv->bandwidth; */ -+ return 0; -+} -+ -+ -+static struct dvb_tuner_ops tuner_ops = { -+ .info = { -+ .name = "NXP TDA18212", -+ .frequency_min = 47125000, -+ .frequency_max = 865000000, -+ .frequency_step = 62500 -+ }, -+ .init = init, -+ .sleep = sleep, -+ .set_params = set_params, -+ .release = release, -+ .get_frequency = get_frequency, -+ .get_if_frequency = get_if, -+ .get_bandwidth = get_bandwidth, -+ .get_rf_strength = get_rf_strength, -+}; -+ -+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr) -+{ -+ struct tda_state *state; -+ int stat; -+ -+ state = kzalloc(sizeof(struct tda_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ state->adr = adr; -+ state->i2c = i2c; -+ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); -+ init_state(state); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ stat = attach_init(state); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ if (stat < 0) { -+ kfree(state); -+ return 0; -+ } -+ fe->tuner_priv = state; -+ return fe; -+} -+EXPORT_SYMBOL_GPL(tda18212dd_attach); -+ -+MODULE_DESCRIPTION("TDA18212 driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Local variables: -+ * c-basic-offset: 8 -+ * End: -+ */ -diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h -new file mode 100644 -index 0000000..687fab4a ---- /dev/null -+++ b/drivers/media/dvb-frontends/tda18212dd.h -@@ -0,0 +1,5 @@ -+#ifndef _TDA18212DD_H_ -+#define _TDA18212DD_H_ -+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr); -+#endif -diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c -index de0a1c1..ad7c72e 100644 ---- a/drivers/media/dvb-frontends/tda18271c2dd.c -+++ b/drivers/media/dvb-frontends/tda18271c2dd.c -@@ -32,10 +32,6 @@ - #include - - #include "dvb_frontend.h" --#include "tda18271c2dd.h" -- --/* Max transfer size done by I2C transfer functions */ --#define MAX_XFER_SIZE 64 - - struct SStandardParam { - s32 m_IFFrequency; -@@ -142,18 +138,11 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) - static int WriteRegs(struct tda_state *state, - u8 SubAddr, u8 *Regs, u16 nRegs) - { -- u8 data[MAX_XFER_SIZE]; -- -- if (1 + nRegs > sizeof(data)) { -- printk(KERN_WARNING -- "%s: i2c wr: len=%d is too big!\n", -- KBUILD_MODNAME, nRegs); -- return -EINVAL; -- } -+ u8 data[nRegs+1]; - - data[0] = SubAddr; - memcpy(data + 1, Regs, nRegs); -- return i2c_write(state->i2c, state->adr, data, nRegs + 1); -+ return i2c_write(state->i2c, state->adr, data, nRegs+1); - } - - static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg) -@@ -1030,7 +1019,7 @@ static int ChannelConfiguration(struct tda_state *state, - state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; - - if ((Standard == HF_FM_Radio) && state->m_bFMInput) -- state->m_Regs[EP4] |= 0x80; -+ state->m_Regs[EP4] |= 80; - - state->m_Regs[MPD] &= ~0x80; - if (Standard > HF_AnalogMax) -diff --git a/drivers/media/dvb-frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h -index dd84f7b..1389c74 100644 ---- a/drivers/media/dvb-frontends/tda18271c2dd.h -+++ b/drivers/media/dvb-frontends/tda18271c2dd.h -@@ -1,9 +1,7 @@ - #ifndef _TDA18271C2DD_H_ - #define _TDA18271C2DD_H_ -- --#include -- --#if IS_ENABLED(CONFIG_DVB_TDA18271C2DD) -+#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \ -+ && defined(MODULE)) - struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, u8 adr); - #else -diff --git a/drivers/media/dvb-frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h -index f3bca5c..b87661b 100644 ---- a/drivers/media/dvb-frontends/tda18271c2dd_maps.h -+++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h -@@ -5,7 +5,7 @@ enum HF_S { - HF_DVBC_8MHZ, HF_DVBC - }; - --static struct SStandardParam m_StandardTable[] = { -+struct SStandardParam m_StandardTable[] = { - { 0, 0, 0x00, 0x00 }, /* HF_None */ - { 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */ - { 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */ -@@ -27,7 +27,7 @@ static struct SStandardParam m_StandardTable[] = { - { 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */ - }; - --static struct SMap m_BP_Filter_Map[] = { -+struct SMap m_BP_Filter_Map[] = { - { 62000000, 0x00 }, - { 84000000, 0x01 }, - { 100000000, 0x02 }, -@@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = { - { 865000000, 489500000, 697500000, 842000000}, - }; - --static u8 m_Thermometer_Map_1[16] = { -+u8 m_Thermometer_Map_1[16] = { - 60, 62, 66, 64, - 74, 72, 68, 70, - 90, 88, 84, 86, - 76, 78, 82, 80, - }; - --static u8 m_Thermometer_Map_2[16] = { -+u8 m_Thermometer_Map_2[16] = { - 92, 94, 98, 96, - 106, 104, 100, 102, - 122, 120, 116, 118, -diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig -index 44e5dc1..d283008 100644 ---- a/drivers/media/pci/ddbridge/Kconfig -+++ b/drivers/media/pci/ddbridge/Kconfig -@@ -1,18 +1,23 @@ - config DVB_DDBRIDGE - tristate "Digital Devices bridge support" - depends on DVB_CORE && PCI && I2C -+ select DVB_CXD2099 - select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT - select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT - select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT - ---help--- - Support for cards with the Digital Devices PCI express bridge: - - Octopus PCIe Bridge - - Octopus mini PCIe Bridge - - Octopus LE -- - DuoFlex S2 Octopus -- - DuoFlex CT Octopus -- - cineS2(v6) -+ - DuoFlex S2 -+ - DuoFlex CT -+ - cineS2(v6.x) -+ - cineCT(v6.x, v7) - - Say Y if you own such a card and want to use it. -diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile -index 7446c8b..2610161 100644 ---- a/drivers/media/pci/ddbridge/Makefile -+++ b/drivers/media/pci/ddbridge/Makefile -@@ -2,8 +2,6 @@ - # Makefile for the ddbridge device driver - # - --ddbridge-objs := ddbridge-core.o -- - obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o - - ccflags-y += -Idrivers/media/dvb-core/ -diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c -index 9e3492e..c2fc010 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-core.c -+++ b/drivers/media/pci/ddbridge/ddbridge-core.c -@@ -1,7 +1,8 @@ - /* -- * ddbridge.c: Digital Devices PCIe bridge driver -+ * ddbridge-core.c: Digital Devices bridge core functions - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2013 Digital Devices GmbH -+ * Ralph Metzler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -21,268 +22,245 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include "ddbridge.h" -- --#include "ddbridge-regs.h" -- --#include "tda18271c2dd.h" --#include "stv6110x.h" --#include "stv090x.h" --#include "lnbh24.h" --#include "drxk.h" -+DEFINE_MUTEX(redirect_lock); -+ -+static int ci_bitrate = 72000; -+module_param(ci_bitrate, int, 0444); -+MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI."); -+ -+static int ts_loop = -1; -+module_param(ts_loop, int, 0444); -+MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop"); -+ -+static int vlan; -+module_param(vlan, int, 0444); -+MODULE_PARM_DESC(vlan, "VLAN and QoS IDs enabled"); -+ -+static int tt; -+module_param(tt, int, 0444); -+MODULE_PARM_DESC(tt, ""); -+ -+#define DDB_MAX_ADAPTER 32 -+static struct ddb *ddbs[DDB_MAX_ADAPTER]; - - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - --/* MSI had problems with lost interrupts, fixed but needs testing */ --#undef CONFIG_PCI_MSI -+#include "ddbridge-mod.c" -+#include "ddbridge-i2c.c" -+#include "ddbridge-ns.c" - --/******************************************************************************/ - --static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) - { -- struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1 } }; -- return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; --} -+ u32 i, base; -+ u64 mem; - --static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) --{ -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = ®, .len = 1 }, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1 } }; -- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+ if (!dma) -+ return; -+ base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100; -+ for (i = 0; i < dma->num; i++) { -+ mem = dma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); -+ } -+ dma->bufreg = (dma->div << 16) | -+ ((dma->num & 0x1f) << 11) | -+ ((dma->size >> 7) & 0x7ff); - } - --static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -- u16 reg, u8 *val) -+static void ddb_set_dma_tables(struct ddb *dev) - { -- u8 msg[2] = {reg>>8, reg&0xff}; -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = msg, .len = 2}, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1} }; -- return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+ u32 i; -+ -+ for (i = 0; i < dev->info->port_num * 2; i++) -+ ddb_set_dma_table(dev, dev->input[i].dma); -+ for (i = 0; i < dev->info->port_num; i++) -+ ddb_set_dma_table(dev, dev->output[i].dma); - } - --static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void ddb_redirect_dma(struct ddb *dev, -+ struct ddb_dma *sdma, -+ struct ddb_dma *ddma) - { -- struct ddb *dev = i2c->dev; -- int stat; -- u32 val; -+ u32 i, base; -+ u64 mem; - -- i2c->done = 0; -- ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); -- stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); -- if (stat <= 0) { -- printk(KERN_ERR "I2C timeout\n"); -- { /* MSI debugging*/ -- u32 istat = ddbreadl(INTERRUPT_STATUS); -- printk(KERN_ERR "IRS %08x\n", istat); -- ddbwritel(istat, INTERRUPT_ACK); -- } -- return -EIO; -+ sdma->bufreg = ddma->bufreg; -+ base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; -+ for (i = 0; i < ddma->num; i++) { -+ mem = ddma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); - } -- val = ddbreadl(i2c->regs+I2C_COMMAND); -- if (val & 0x70000) -- return -EIO; -- return 0; - } - --static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, -- struct i2c_msg msg[], int num) -+static int ddb_unredirect(struct ddb_port *port) - { -- struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); -- struct ddb *dev = i2c->dev; -- u8 addr = 0; -- -- if (num) -- addr = msg[0].addr; -+ struct ddb_input *oredi, *iredi = 0; -+ struct ddb_output *iredo = 0; - -- if (num == 2 && msg[1].flags & I2C_M_RD && -- !(msg[0].flags & I2C_M_RD)) { -- memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, -- msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len|(msg[1].len << 16), -- i2c->regs+I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 1)) { -- memcpy_fromio(msg[1].buf, -- dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, -- msg[1].len); -- return num; -- } -- } -- -- if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -- ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 2)) -- return num; -+ /*pr_info("unredirect %d.%d\n", port->dev->nr, port->nr);*/ -+ mutex_lock(&redirect_lock); -+ if (port->output->dma->running) { -+ mutex_unlock(&redirect_lock); -+ return -EBUSY; - } -- if (num == 1 && (msg[0].flags & I2C_M_RD)) { -- ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); -- if (!ddb_i2c_cmd(i2c, addr, 3)) { -- ddbcpyfrom(msg[0].buf, -- I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); -- return num; -+ oredi = port->output->redi; -+ if (!oredi) -+ goto done; -+ if (port->input[0]) { -+ iredi = port->input[0]->redi; -+ iredo = port->input[0]->redo; -+ -+ if (iredo) { -+ iredo->port->output->redi = oredi; -+ if (iredo->port->input[0]) { -+ iredo->port->input[0]->redi = iredi; -+ ddb_redirect_dma(oredi->port->dev, -+ oredi->dma, iredo->dma); -+ } -+ port->input[0]->redo = 0; -+ ddb_set_dma_table(port->dev, port->input[0]->dma); - } -+ oredi->redi = iredi; -+ port->input[0]->redi = 0; - } -- return -EIO; --} -+ oredi->redo = 0; -+ port->output->redi = 0; - -+ ddb_set_dma_table(oredi->port->dev, oredi->dma); -+done: -+ mutex_unlock(&redirect_lock); -+ return 0; -+} - --static u32 ddb_i2c_functionality(struct i2c_adapter *adap) -+static int ddb_redirect(u32 i, u32 p) - { -- return I2C_FUNC_SMBUS_EMUL; --} -+ struct ddb *idev = ddbs[(i >> 4) & 0x1f]; -+ struct ddb_input *input, *input2; -+ struct ddb *pdev = ddbs[(p >> 4) & 0x1f]; -+ struct ddb_port *port; - --static struct i2c_algorithm ddb_i2c_algo = { -- .master_xfer = ddb_i2c_master_xfer, -- .functionality = ddb_i2c_functionality, --}; -+ if (!idev->has_dma || !pdev->has_dma) -+ return -EINVAL; -+ if (!idev || !pdev) -+ return -EINVAL; - --static void ddb_i2c_release(struct ddb *dev) --{ -- int i; -- struct ddb_i2c *i2c; -- struct i2c_adapter *adap; -+ port = &pdev->port[p & 0x0f]; -+ if (!port->output) -+ return -EINVAL; -+ if (ddb_unredirect(port)) -+ return -EBUSY; - -- for (i = 0; i < dev->info->port_num; i++) { -- i2c = &dev->i2c[i]; -- adap = &i2c->adap; -- i2c_del_adapter(adap); -- } --} -+ if (i == 8) -+ return 0; - --static int ddb_i2c_init(struct ddb *dev) --{ -- int i, j, stat = 0; -- struct ddb_i2c *i2c; -- struct i2c_adapter *adap; -+ input = &idev->input[i & 7]; -+ if (!input) -+ return -EINVAL; - -- for (i = 0; i < dev->info->port_num; i++) { -- i2c = &dev->i2c[i]; -- i2c->dev = dev; -- i2c->nr = i; -- i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); -- i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); -- i2c->regs = 0x80 + i * 0x20; -- ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING); -- ddbwritel((i2c->rbuf << 16) | i2c->wbuf, -- i2c->regs + I2C_TASKADDRESS); -- init_waitqueue_head(&i2c->wq); -- -- adap = &i2c->adap; -- i2c_set_adapdata(adap, i2c); --#ifdef I2C_ADAP_CLASS_TV_DIGITAL -- adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; --#else --#ifdef I2C_CLASS_TV_ANALOG -- adap->class = I2C_CLASS_TV_ANALOG; --#endif --#endif -- strcpy(adap->name, "ddbridge"); -- adap->algo = &ddb_i2c_algo; -- adap->algo_data = (void *)i2c; -- adap->dev.parent = &dev->pdev->dev; -- stat = i2c_add_adapter(adap); -- if (stat) -- break; -+ mutex_lock(&redirect_lock); -+ if (port->output->dma->running || input->dma->running) { -+ mutex_unlock(&redirect_lock); -+ return -EBUSY; - } -- if (stat) -- for (j = 0; j < i; j++) { -- i2c = &dev->i2c[j]; -- adap = &i2c->adap; -- i2c_del_adapter(adap); -- } -- return stat; --} -+ input2 = port->input[0]; -+ if (input2) { -+ if (input->redi) { -+ input2->redi = input->redi; -+ input->redi = 0; -+ } else -+ input2->redi = input; -+ } -+ input->redo = port->output; -+ port->output->redi = input; - -+ ddb_redirect_dma(input->port->dev, input->dma, port->output->dma); -+ mutex_unlock(&redirect_lock); -+ return 0; -+} - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - --#if 0 --static void set_table(struct ddb *dev, u32 off, -- dma_addr_t *pbuf, u32 num) -+#ifdef DDB_ALT_DMA -+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { -- u32 i, base; -- u64 mem; -+ int i; - -- base = DMA_BASE_ADDRESS_TABLE + off; -- for (i = 0; i < num; i++) { -- mem = pbuf[i]; -- ddbwritel(mem & 0xffffffff, base + i * 8); -- ddbwritel(mem >> 32, base + i * 8 + 4); -+ if (!dma) -+ return; -+ for (i = 0; i < dma->num; i++) { -+ if (dma->vbuf[i]) { -+ dma_unmap_single(&pdev->dev, dma->pbuf[i], -+ dma->size, -+ dir ? DMA_TO_DEVICE : -+ DMA_FROM_DEVICE); -+ kfree(dma->vbuf[i]); -+ dma->vbuf[i] = 0; -+ } - } - } --#endif - --static void ddb_address_table(struct ddb *dev) -+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { -- u32 i, j, base; -- u64 mem; -- dma_addr_t *pbuf; -+ int i; - -- for (i = 0; i < dev->info->port_num * 2; i++) { -- base = DMA_BASE_ADDRESS_TABLE + i * 0x100; -- pbuf = dev->input[i].pbuf; -- for (j = 0; j < dev->input[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -- } -- } -- for (i = 0; i < dev->info->port_num; i++) { -- base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100; -- pbuf = dev->output[i].pbuf; -- for (j = 0; j < dev->output[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -+ if (!dma) -+ return 0; -+ for (i = 0; i < dma->num; i++) { -+ dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT); -+ if (!dma->vbuf[i]) -+ return -ENOMEM; -+ dma->pbuf[i] = dma_map_single(&pdev->dev, dma->vbuf[i], -+ dma->size, -+ dir ? DMA_TO_DEVICE : -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(&pdev->dev, dma->pbuf[i])) { -+ kfree(dma->vbuf[i]); -+ return -ENOMEM; - } - } -+ return 0; - } -+#else - --static void io_free(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { - int i; - -- for (i = 0; i < num; i++) { -- if (vbuf[i]) { -- pci_free_consistent(pdev, size, vbuf[i], pbuf[i]); -- vbuf[i] = NULL; -+ if (!dma) -+ return; -+ for (i = 0; i < dma->num; i++) { -+ if (dma->vbuf[i]) { -+ pci_free_consistent(pdev, dma->size, -+ dma->vbuf[i], dma->pbuf[i]); -+ dma->vbuf[i] = 0; - } - } - } - --static int io_alloc(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) - { - int i; - -- for (i = 0; i < num; i++) { -- vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]); -- if (!vbuf[i]) -+ if (!dma) -+ return 0; -+ for (i = 0; i < dma->num; i++) { -+ dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size, -+ &dma->pbuf[i]); -+ if (!dma->vbuf[i]) - return -ENOMEM; - } - return 0; - } -+#endif - - static int ddb_buffers_alloc(struct ddb *dev) - { -@@ -293,34 +271,24 @@ static int ddb_buffers_alloc(struct ddb *dev) - port = &dev->port[i]; - switch (port->class) { - case DDB_PORT_TUNER: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -+ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0) - return -1; -- if (io_alloc(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num) < 0) -+ if (dma_alloc(dev->pdev, port->input[1]->dma, 0) < 0) - return -1; - break; - case DDB_PORT_CI: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -+ case DDB_PORT_LOOP: -+ if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0) - return -1; -- if (io_alloc(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num) < 0) -+ case DDB_PORT_MOD: -+ if (dma_alloc(dev->pdev, port->output->dma, 1) < 0) - return -1; - break; - default: - break; - } - } -- ddb_address_table(dev); -+ ddb_set_dma_tables(dev); - return 0; - } - -@@ -331,287 +299,839 @@ static void ddb_buffers_free(struct ddb *dev) - - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; -- io_free(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num); -- io_free(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num); -- io_free(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num); -+ -+ if (port->input[0]) -+ dma_free(dev->pdev, port->input[0]->dma, 0); -+ if (port->input[1]) -+ dma_free(dev->pdev, port->input[1]->dma, 0); -+ if (port->output) -+ dma_free(dev->pdev, port->output->dma, 1); - } - } - --static void ddb_input_start(struct ddb_input *input) -+static void ddb_output_start(struct ddb_output *output) - { -- struct ddb *dev = input->port->dev; -+ struct ddb *dev = output->port->dev; -+ u32 con2; - -- spin_lock_irq(&input->lock); -- input->cbuf = 0; -- input->coff = 0; -+ con2 = ((output->port->obr << 13) + 71999) / 72000; -+ con2 = (con2 << 16) | output->port->gap; - -- /* reset */ -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(2, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -+ if (output->dma) { -+ spin_lock_irq(&output->dma->lock); -+ output->dma->cbuf = 0; -+ output->dma->coff = 0; -+ output->dma->stat = 0; -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); -+ } -+ if (output->port->class == DDB_PORT_MOD) -+ ddbridge_mod_output_start(output); -+ else { -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, con2, TS_OUTPUT_CONTROL2(output->nr)); -+ } -+ if (output->dma) { -+ ddbwritel(dev, output->dma->bufreg, -+ DMA_BUFFER_SIZE(output->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); -+ ddbwritel(dev, 1, DMA_BASE_READ); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); -+ } -+ if (output->port->class != DDB_PORT_MOD) { -+ if (output->port->input[0]->port->class == DDB_PORT_LOOP) -+ /*ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0x45, -+ TS_OUTPUT_CONTROL(output->nr));*/ -+ ddbwritel(dev, (1 << 13) | 0x15, -+ TS_OUTPUT_CONTROL(output->nr)); -+ else -+ ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr)); -+ } -+ if (output->dma) { -+ output->dma->running = 1; -+ spin_unlock_irq(&output->dma->lock); -+ } -+} - -- ddbwritel((1 << 16) | -- (input->dma_buf_num << 11) | -- (input->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(input->nr)); -- ddbwritel(0, DMA_BUFFER_ACK(input->nr)); -+static void ddb_output_stop(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; - -- ddbwritel(1, DMA_BASE_WRITE); -- ddbwritel(3, DMA_BUFFER_CONTROL(input->nr)); -- ddbwritel(9, TS_INPUT_CONTROL(input->nr)); -- input->running = 1; -- spin_unlock_irq(&input->lock); -+ if (output->dma) -+ spin_lock_irq(&output->dma->lock); -+ if (output->port->class == DDB_PORT_MOD) -+ ddbridge_mod_output_stop(output); -+ else -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ if (output->dma) { -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); -+ output->dma->running = 0; -+ spin_unlock_irq(&output->dma->lock); -+ } - } - - static void ddb_input_stop(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; - -- spin_lock_irq(&input->lock); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(input->nr)); -- input->running = 0; -- spin_unlock_irq(&input->lock); -+ if (input->dma) -+ spin_lock_irq(&input->dma->lock); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); -+ if (input->dma) { -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); -+ input->dma->running = 0; -+ spin_unlock_irq(&input->dma->lock); -+ } -+ /*pr_info("input_stop %d.%d\n", dev->nr, input->nr);*/ - } - --static void ddb_output_start(struct ddb_output *output) -+static void ddb_input_start(struct ddb_input *input) - { -- struct ddb *dev = output->port->dev; -+ struct ddb *dev = input->port->dev; - -- spin_lock_irq(&output->lock); -- output->cbuf = 0; -- output->coff = 0; -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel((1 << 16) | -- (output->dma_buf_num << 11) | -- (output->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(output->nr + 8)); -- ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8)); -- -- ddbwritel(1, DMA_BASE_READ); -- ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8)); -- /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */ -- ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr)); -- output->running = 1; -- spin_unlock_irq(&output->lock); -+ if (input->dma) { -+ spin_lock_irq(&input->dma->lock); -+ input->dma->cbuf = 0; -+ input->dma->coff = 0; -+ input->dma->stat = 0; -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); -+ } -+ ddbwritel(dev, 0, TS_INPUT_CONTROL2(input->nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); -+ -+ if (input->dma) { -+ ddbwritel(dev, input->dma->bufreg, -+ DMA_BUFFER_SIZE(input->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); -+ ddbwritel(dev, 1, DMA_BASE_WRITE); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); -+ } -+ if (dev->info->type == DDB_OCTONET) -+ ddbwritel(dev, 0x01, TS_INPUT_CONTROL(input->nr)); -+ else -+ ddbwritel(dev, 0x09, TS_INPUT_CONTROL(input->nr)); -+ if (input->dma) { -+ input->dma->running = 1; -+ spin_unlock_irq(&input->dma->lock); -+ } -+ /*pr_info("input_start %d.%d\n", dev->nr, input->nr);*/ - } - --static void ddb_output_stop(struct ddb_output *output) -+ -+static int ddb_dvb_input_start(struct ddb_input *input) - { -- struct ddb *dev = output->port->dev; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (!dvb->users) -+ ddb_input_start(input); -+ -+ return ++dvb->users; -+} -+ -+static int ddb_dvb_input_stop(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- spin_lock_irq(&output->lock); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8)); -- output->running = 0; -- spin_unlock_irq(&output->lock); -+ if (--dvb->users) -+ return dvb->users; -+ -+ ddb_input_stop(input); -+ return 0; -+} -+ -+static void ddb_input_start_all(struct ddb_input *input) -+{ -+ struct ddb_input *i = input; -+ struct ddb_output *o; -+ -+ mutex_lock(&redirect_lock); -+ while (i && (o = i->redo)) { -+ ddb_output_start(o); -+ i = o->port->input[0]; -+ if (i) -+ ddb_input_start(i); -+ } -+ ddb_input_start(input); -+ mutex_unlock(&redirect_lock); -+} -+ -+static void ddb_input_stop_all(struct ddb_input *input) -+{ -+ struct ddb_input *i = input; -+ struct ddb_output *o; -+ -+ mutex_lock(&redirect_lock); -+ ddb_input_stop(input); -+ while (i && (o = i->redo)) { -+ ddb_output_stop(o); -+ i = o->port->input[0]; -+ if (i) -+ ddb_input_stop(i); -+ } -+ mutex_unlock(&redirect_lock); - } - - static u32 ddb_output_free(struct ddb_output *output) - { -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - s32 diff; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - -- if (output->cbuf != idx) { -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -- (output->dma_buf_size - output->coff <= 188)) -+ if (output->dma->cbuf != idx) { -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && -+ (output->dma->size - output->dma->coff <= 188)) - return 0; - return 188; - } -- diff = off - output->coff; -+ diff = off - output->dma->coff; - if (diff <= 0 || diff > 188) - return 188; - return 0; - } - -+#if 0 -+static u32 ddb_dma_free(struct ddb_dma *dma) -+{ -+ u32 idx, off, stat = dma->stat; -+ s32 p1, p2, diff; -+ -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ -+ p1 = idx * dma->size + off; -+ p2 = dma->cbuf * dma->size + dma->coff; -+ -+ diff = p1 - p2; -+ if (diff <= 0) -+ diff += dma->num * dma->size; -+ return diff; -+} -+#endif -+ - static ssize_t ddb_output_write(struct ddb_output *output, -- const __user u8 *buf, size_t count) -+ const u8 *buf, size_t count) - { - struct ddb *dev = output->port->dev; -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - u32 left = count, len; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - while (left) { -- len = output->dma_buf_size - output->coff; -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -+ len = output->dma->size - output->dma->coff; -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && - (off == 0)) { - if (len <= 188) - break; - len -= 188; - } -- if (output->cbuf == idx) { -- if (off > output->coff) { --#if 1 -- len = off - output->coff; -+ if (output->dma->cbuf == idx) { -+ if (off > output->dma->coff) { -+ len = off - output->dma->coff; - len -= (len % 188); - if (len <= 188) -- --#endif - break; - len -= 188; - } - } - if (len > left) - len = left; -- if (copy_from_user(output->vbuf[output->cbuf] + output->coff, -+ if (copy_from_user(output->dma->vbuf[output->dma->cbuf] + -+ output->dma->coff, - buf, len)) - return -EIO; -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_device(dev->dev, -+ output->dma->pbuf[ -+ output->dma->cbuf], -+ output->dma->size, DMA_TO_DEVICE); -+#endif - left -= len; - buf += len; -- output->coff += len; -- if (output->coff == output->dma_buf_size) { -- output->coff = 0; -- output->cbuf = ((output->cbuf + 1) % output->dma_buf_num); -+ output->dma->coff += len; -+ if (output->dma->coff == output->dma->size) { -+ output->dma->coff = 0; -+ output->dma->cbuf = ((output->dma->cbuf + 1) % -+ output->dma->num); - } -- ddbwritel((output->cbuf << 11) | (output->coff >> 7), -- DMA_BUFFER_ACK(output->nr + 8)); -+ ddbwritel(dev, -+ (output->dma->cbuf << 11) | -+ (output->dma->coff >> 7), -+ DMA_BUFFER_ACK(output->dma->nr)); - } - return count - left; - } - -+#if 0 -+static u32 ddb_input_free_bytes(struct ddb_input *input) -+{ -+ struct ddb *dev = input->port->dev; -+ u32 idx, off, stat = input->dma->stat; -+ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); -+ -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ -+ if (ctrl & 4) -+ return 0; -+ if (input->dma->cbuf != idx) -+ return 1; -+ return 0; -+} -+ -+ -+ -+static s32 ddb_output_used_bufs(struct ddb_output *output) -+{ -+ u32 idx, off, stat, ctrl; -+ s32 diff; -+ -+ spin_lock_irq(&output->dma->lock); -+ stat = output->dma->stat; -+ ctrl = output->dma->ctrl; -+ spin_unlock_irq(&output->dma->lock); -+ -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ -+ if (ctrl & 4) -+ return 0; -+ diff = output->dma->cbuf - idx; -+ if (diff == 0 && off < output->dma->coff) -+ return 0; -+ if (diff <= 0) -+ diff += output->dma->num; -+ return diff; -+} -+ -+static s32 ddb_input_free_bufs(struct ddb_input *input) -+{ -+ u32 idx, off, stat, ctrl; -+ s32 free; -+ -+ spin_lock_irq(&input->dma->lock); -+ ctrl = input->dma->ctrl; -+ stat = input->dma->stat; -+ spin_unlock_irq(&input->dma->lock); -+ if (ctrl & 4) -+ return 0; -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ free = input->dma->cbuf - idx; -+ if (free == 0 && off < input->dma->coff) -+ return 0; -+ if (free <= 0) -+ free += input->dma->num; -+ return free - 1; -+} -+ -+static u32 ddb_output_ok(struct ddb_output *output) -+{ -+ struct ddb_input *input = output->port->input[0]; -+ s32 diff; -+ -+ diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output); -+ if (diff > 0) -+ return 1; -+ return 0; -+} -+#endif -+ - static u32 ddb_input_avail(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; -- u32 idx, off, stat = input->stat; -- u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr)); -+ u32 idx, off, stat = input->dma->stat; -+ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - if (ctrl & 4) { -- printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); -- ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); -+ pr_err("IA %d %d %08x\n", idx, off, ctrl); -+ ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); - return 0; - } -- if (input->cbuf != idx) -+ if (input->dma->cbuf != idx) - return 188; - return 0; - } - --static ssize_t ddb_input_read(struct ddb_input *input, __user u8 *buf, size_t count) -+static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) - { - struct ddb *dev = input->port->dev; - u32 left = count; -- u32 idx, free, stat = input->stat; -+ u32 idx, off, free, stat = input->dma->stat; - int ret; - - idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; - - while (left) { -- if (input->cbuf == idx) -+ if (input->dma->cbuf == idx) - return count - left; -- free = input->dma_buf_size - input->coff; -+ free = input->dma->size - input->dma->coff; - if (free > left) - free = left; -- ret = copy_to_user(buf, input->vbuf[input->cbuf] + -- input->coff, free); -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_cpu(dev->dev, -+ input->dma->pbuf[input->dma->cbuf], -+ input->dma->size, DMA_FROM_DEVICE); -+#endif -+ ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + -+ input->dma->coff, free); - if (ret) - return -EFAULT; -- input->coff += free; -- if (input->coff == input->dma_buf_size) { -- input->coff = 0; -- input->cbuf = (input->cbuf+1) % input->dma_buf_num; -+ input->dma->coff += free; -+ if (input->dma->coff == input->dma->size) { -+ input->dma->coff = 0; -+ input->dma->cbuf = (input->dma->cbuf + 1) % -+ input->dma->num; - } - left -= free; -- ddbwritel((input->cbuf << 11) | (input->coff >> 7), -- DMA_BUFFER_ACK(input->nr)); -+ ddbwritel(dev, -+ (input->dma->cbuf << 11) | (input->dma->coff >> 7), -+ DMA_BUFFER_ACK(input->dma->nr)); - } - return count; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - --#if 0 --static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) -+static ssize_t ts_write(struct file *file, const char *buf, -+ size_t count, loff_t *ppos) - { -- int i; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb *dev = output->port->dev; -+ size_t left = count; -+ int stat; - -- for (i = 0; i < dev->info->port_num * 2; i++) { -- if (dev->input[i].fe == fe) -- return &dev->input[i]; -+ if (!dev->has_dma) -+ return -EINVAL; -+ while (left) { -+ if (ddb_output_free(output) < 188) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible( -+ output->dma->wq, -+ ddb_output_free(output) >= 188) < 0) -+ break; -+ } -+ stat = ddb_output_write(output, buf, left); -+ if (stat < 0) -+ return stat; -+ buf += stat; -+ left -= stat; - } -- return NULL; -+ return (left == count) ? -EAGAIN : (count - left); - } --#endif - --static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+static ssize_t ts_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) - { -- struct ddb_input *input = fe->sec_priv; -- struct ddb_port *port = input->port; -- int status; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ struct ddb *dev = output->port->dev; -+ size_t left = count; -+ int stat; - -- if (enable) { -- mutex_lock(&port->i2c_gate_lock); -- status = input->gate_ctrl(fe, 1); -- } else { -- status = input->gate_ctrl(fe, 0); -- mutex_unlock(&port->i2c_gate_lock); -+ if (!dev->has_dma) -+ return -EINVAL; -+ while (left) { -+ if (ddb_input_avail(input) < 188) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible( -+ input->dma->wq, -+ ddb_input_avail(input) >= 188) < 0) -+ break; -+ } -+ stat = ddb_input_read(input, buf, left); -+ if (stat < 0) -+ return stat; -+ left -= stat; -+ buf += stat; - } -- return status; -+ return (count && (left == count)) ? -EAGAIN : (count - left); - } - --static int demod_attach_drxk(struct ddb_input *input) -+static unsigned int ts_poll(struct file *file, poll_table *wait) - { -- struct i2c_adapter *i2c = &input->port->i2c->adap; -- struct dvb_frontend *fe; -- struct drxk_config config; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; - -- memset(&config, 0, sizeof(config)); -- config.microcode_name = "drxk_a3.mc"; -- config.qam_demod_parameter_count = 4; -- config.adr = 0x29 + (input->nr & 1); -+ unsigned int mask = 0; - -- fe = input->fe = dvb_attach(drxk_attach, &config, i2c); -- if (!input->fe) { -- printk(KERN_ERR "No DRXK found!\n"); -- return -ENODEV; -- } -- fe->sec_priv = input; -- input->gate_ctrl = fe->ops.i2c_gate_ctrl; -- fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -- return 0; -+ poll_wait(file, &input->dma->wq, wait); -+ poll_wait(file, &output->dma->wq, wait); -+ if (ddb_input_avail(input) >= 188) -+ mask |= POLLIN | POLLRDNORM; -+ if (ddb_output_free(output) >= 188) -+ mask |= POLLOUT | POLLWRNORM; -+ return mask; - } - --static int tuner_attach_tda18271(struct ddb_input *input) -+static int ts_release(struct inode *inode, struct file *file) - { -- struct i2c_adapter *i2c = &input->port->i2c->adap; -- struct dvb_frontend *fe; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -+ if (!input) -+ return -EINVAL; -+ ddb_input_stop(input); -+ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ ddb_output_stop(output); -+ } -+ return dvb_generic_release(inode, file); -+} -+ -+static int ts_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) { -+ if (!input) -+ return -EINVAL; -+ if (input->redo || input->redi) -+ return -EBUSY; -+ } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ } -+ err = dvb_generic_open(inode, file); -+ if (err < 0) -+ return err; -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ ddb_input_start(input); -+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ ddb_output_start(output); -+ return err; -+} -+ -+static int mod_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ ddb_output_stop(output); -+ } -+ return dvb_generic_release(inode, file); -+} -+ -+static int mod_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { -+ if (!output) -+ return -EINVAL; -+ } -+ err = dvb_generic_open(inode, file); -+ if (err < 0) -+ return err; -+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) -+ ddb_output_start(output); -+ return err; -+} -+static const struct file_operations ci_fops = { -+ .owner = THIS_MODULE, -+ .read = ts_read, -+ .write = ts_write, -+ .open = ts_open, -+ .release = ts_release, -+ .poll = ts_poll, -+ .mmap = 0, -+}; -+ -+static struct dvb_device dvbdev_ci = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 2, -+ .fops = &ci_fops, -+}; -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static long mod_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl); -+} -+ -+static const struct file_operations mod_fops = { -+ .owner = THIS_MODULE, -+ .read = ts_read, -+ .write = ts_write, -+ .open = mod_open, -+ .release = mod_release, -+ .poll = ts_poll, -+ .mmap = 0, -+ .unlocked_ioctl = mod_ioctl, -+}; -+ -+static struct dvb_device dvbdev_mod = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 2, -+ .fops = &mod_fops, -+}; -+ -+ -+#if 0 -+static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) -+{ -+ int i; -+ -+ for (i = 0; i < dev->info->port_num * 2; i++) { -+ if (dev->input[i].fe == fe) -+ return &dev->input[i]; -+ } -+ return NULL; -+} -+#endif -+ -+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int status; -+ -+ if (enable) { -+ mutex_lock(&port->i2c_gate_lock); -+ status = dvb->i2c_gate_ctrl(fe, 1); -+ } else { -+ status = dvb->i2c_gate_ctrl(fe, 0); -+ mutex_unlock(&port->i2c_gate_lock); -+ } -+ return status; -+} -+ -+#if IS_ENABLED(CONFIG_DVB_DRXK) -+static int demod_attach_drxk(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ struct drxk_config config; -+ -+ memset(&config, 0, sizeof(config)); -+ config.adr = 0x29 + (input->nr & 1); -+ config.microcode_name = "drxk_a3.mc"; -+ -+ fe = dvb->fe = dvb_attach(drxk_attach, &config, i2c); -+ if (!fe) { -+ pr_err("No DRXK found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+#endif -+ -+#if 0 -+struct stv0367_config stv0367_0 = { -+ .demod_address = 0x1f, -+ .xtal = 27000000, -+ .if_khz = 5000, -+ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, -+ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, -+ .clk_pol = STV0367_RISINGEDGE_CLOCK, -+}; -+ -+struct stv0367_config stv0367_1 = { -+ .demod_address = 0x1e, -+ .xtal = 27000000, -+ .if_khz = 5000, -+ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, -+ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, -+ .clk_pol = STV0367_RISINGEDGE_CLOCK, -+}; -+ -+ -+static int demod_attach_stv0367(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ fe = dvb->fe = dvb_attach(stv0367ter_attach, -+ (input->nr & 1) ? &stv0367_1 : &stv0367_0, -+ i2c); -+ if (!dvb->fe) { -+ pr_err("No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+#endif -+ -+struct cxd2843_cfg cxd2843_0 = { -+ .adr = 0x6c, -+}; -+ -+struct cxd2843_cfg cxd2843_1 = { -+ .adr = 0x6d, -+}; -+ -+struct cxd2843_cfg cxd2843p_0 = { -+ .adr = 0x6c, -+ .parallel = 1, -+}; - -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 1); -- fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); -+struct cxd2843_cfg cxd2843p_1 = { -+ .adr = 0x6d, -+ .parallel = 1, -+}; -+ -+static int demod_attach_cxd2843(struct ddb_input *input, int par) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ if (par) -+ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, -+ (input->nr & 1) ? -+ &cxd2843p_1 : &cxd2843p_0); -+ else -+ fe = dvb->fe = dvb_attach(cxd2843_attach, i2c, -+ (input->nr & 1) ? -+ &cxd2843_1 : &cxd2843_0); -+ if (!dvb->fe) { -+ pr_err("No cxd2837/38/43 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+struct stv0367_cfg stv0367dd_0 = { -+ .adr = 0x1f, -+ .xtal = 27000000, -+}; -+ -+struct stv0367_cfg stv0367dd_1 = { -+ .adr = 0x1e, -+ .xtal = 27000000, -+}; -+ -+static int demod_attach_stv0367dd(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ fe = dvb->fe = dvb_attach(stv0367_attach, i2c, -+ (input->nr & 1) ? -+ &stv0367dd_1 : &stv0367dd_0, -+ &dvb->fe2); -+ if (!dvb->fe) { -+ pr_err("No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int tuner_attach_tda18271(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ if (dvb->fe->ops.i2c_gate_ctrl) -+ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1); -+ fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60); -+ if (dvb->fe->ops.i2c_gate_ctrl) -+ dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0); - if (!fe) { -- printk(KERN_ERR "No TDA18271 found!\n"); -+ pr_err("No TDA18271 found!\n"); - return -ENODEV; - } -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 0); - return 0; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+static int tuner_attach_tda18212dd(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ -+ fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c, -+ (input->nr & 1) ? 0x63 : 0x60); -+ if (!fe) { -+ pr_err("No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+ -+#ifdef CONFIG_DVB_TDA18212 -+struct tda18212_config tda18212_0 = { -+ .i2c_address = 0x60, -+}; -+ -+struct tda18212_config tda18212_1 = { -+ .i2c_address = 0x63, -+}; -+ -+static int tuner_attach_tda18212(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; -+ struct tda18212_config *cfg; -+ -+ cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0; -+ fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg); -+ if (!fe) { -+ pr_err("No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+#endif -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - - static struct stv090x_config stv0900 = { - .device = STV0900, -@@ -624,6 +1144,9 @@ static struct stv090x_config stv0900 = { - .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - -+ .ts1_tei = 1, -+ .ts2_tei = 1, -+ - .repeater_level = STV090x_RPTLEVEL_16, - - .adc1_range = STV090x_ADC_1Vpp, -@@ -643,6 +1166,9 @@ static struct stv090x_config stv0900_aa = { - .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - -+ .ts1_tei = 1, -+ .ts2_tei = 1, -+ - .repeater_level = STV090x_RPTLEVEL_16, - - .adc1_range = STV090x_ADC_1Vpp, -@@ -667,18 +1193,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) - { - struct i2c_adapter *i2c = &input->port->i2c->adap; - struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- input->fe = dvb_attach(stv090x_attach, feconf, i2c, -- (input->nr & 1) ? STV090x_DEMODULATOR_1 -- : STV090x_DEMODULATOR_0); -- if (!input->fe) { -- printk(KERN_ERR "No STV0900 found!\n"); -+ dvb->fe = dvb_attach(stv090x_attach, feconf, i2c, -+ (input->nr & 1) ? STV090x_DEMODULATOR_1 -+ : STV090x_DEMODULATOR_0); -+ if (!dvb->fe) { -+ pr_err("No STV0900 found!\n"); - return -ENODEV; - } -- if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, -+ if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0, - 0, (input->nr & 1) ? - (0x09 - type) : (0x0b - type))) { -- printk(KERN_ERR "No LNBH24 found!\n"); -+ pr_err("No LNBH24 found!\n"); - return -ENODEV; - } - return 0; -@@ -687,18 +1214,19 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) - static int tuner_attach_stv6110(struct ddb_input *input, int type) - { - struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; - struct stv6110x_config *tunerconf = (input->nr & 1) ? - &stv6110b : &stv6110a; - struct stv6110x_devctl *ctl; - -- ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); -+ ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c); - if (!ctl) { -- printk(KERN_ERR "No STV6110X found!\n"); -+ pr_err("No STV6110X found!\n"); - return -ENODEV; - } -- printk(KERN_INFO "attach tuner input %d adr %02x\n", -- input->nr, tunerconf->addr); -+ pr_info("attach tuner input %d adr %02x\n", -+ input->nr, tunerconf->addr); - - feconf->tuner_init = ctl->tuner_init; - feconf->tuner_sleep = ctl->tuner_sleep; -@@ -715,329 +1243,919 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) - return 0; - } - --static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, -- int (*start_feed)(struct dvb_demux_feed *), -- int (*stop_feed)(struct dvb_demux_feed *), -- void *priv) -+static struct stv0910_cfg stv0910 = { -+ .adr = 0x68, -+ .parallel = 1, -+ .rptlvl = 4, -+ .clk = 30000000, -+}; -+ -+static int demod_attach_stv0910(struct ddb_input *input, int type) - { -- dvbdemux->priv = priv; -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; - -- dvbdemux->filternum = 256; -- dvbdemux->feednum = 256; -- dvbdemux->start_feed = start_feed; -- dvbdemux->stop_feed = stop_feed; -- dvbdemux->write_to_decoder = NULL; -- dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | -- DMX_SECTION_FILTERING | -- DMX_MEMORY_BASED_FILTERING); -- return dvb_dmx_init(dvbdemux); -+ dvb->fe = dvb_attach(stv0910_attach, i2c, &stv0910, (input->nr & 1)); -+ if (!dvb->fe) { -+ pr_err("No STV0910 found!\n"); -+ return -ENODEV; -+ } -+ if (!dvb_attach(lnbh25_attach, dvb->fe, i2c, -+ (input->nr & 1) ? 0x09 : 0x08)) { -+ pr_err("No LNBH25 found!\n"); -+ return -ENODEV; -+ } -+ return 0; - } - --static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, -- struct dvb_demux *dvbdemux, -- struct dmx_frontend *hw_frontend, -- struct dmx_frontend *mem_frontend, -- struct dvb_adapter *dvb_adapter) -+static int tuner_attach_stv6111(struct ddb_input *input) - { -- int ret; -- -- dmxdev->filternum = 256; -- dmxdev->demux = &dvbdemux->dmx; -- dmxdev->capabilities = 0; -- ret = dvb_dmxdev_init(dmxdev, dvb_adapter); -- if (ret < 0) -- return ret; -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_frontend *fe; - -- hw_frontend->source = DMX_FRONTEND_0; -- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); -- mem_frontend->source = DMX_MEMORY_FE; -- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); -- return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); -+ fe = dvb_attach(stv6111_attach, dvb->fe, i2c, -+ (input->nr & 1) ? 0x63 : 0x60); -+ if (!fe) { -+ pr_err("No STV6111 found!\n"); -+ return -ENODEV; -+ } -+ return 0; - } - --static int start_feed(struct dvb_demux_feed *dvbdmxfeed) -+static int lnb_command(struct ddb *dev, u32 lnb, u32 cmd) - { -- struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -- struct ddb_input *input = dvbdmx->priv; -+ u32 c, v = 0; - -- if (!input->users) -- ddb_input_start(input); -- -- return ++input->users; -+ v = LNB_TONE & (dev->lnb_tone << (15 - lnb)); -+ pr_info("lnb_control[%u] = %08x\n", lnb, cmd | v); -+ ddbwritel(dev, cmd | v, LNB_CONTROL(lnb)); -+ for (c = 0; c < 10; c++) { -+ v = ddbreadl(dev, LNB_CONTROL(lnb)); -+ pr_info("ctrl = %08x\n", v); -+ if ((v & LNB_BUSY) == 0) -+ break; -+ msleep(20); -+ } -+ return 0; - } - --static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) -+static int dd_send_master_cmd(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *cmd) - { -- struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -- struct ddb_input *input = dvbdmx->priv; -- -- if (--input->users) -- return input->users; -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int i; - -- ddb_input_stop(input); -+ mutex_lock(&dev->lnb_lock); -+ ddbwritel(dev, 0, LNB_BUF_LEVEL(dvb->input)); -+ for (i = 0; i < cmd->msg_len; i++) -+ ddbwritel(dev, cmd->msg[i], LNB_BUF_WRITE(dvb->input)); -+ lnb_command(dev, dvb->input, LNB_CMD_DISEQC); -+ mutex_unlock(&dev->lnb_lock); - return 0; - } - -- --static void dvb_input_detach(struct ddb_input *input) -+static int dd_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) - { -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -- -- switch (input->attached) { -- case 5: -- if (input->fe2) -- dvb_unregister_frontend(input->fe2); -- if (input->fe) { -- dvb_unregister_frontend(input->fe); -- dvb_frontend_detach(input->fe); -- input->fe = NULL; -- } -- case 4: -- dvb_net_release(&input->dvbnet); -- -- case 3: -- dvbdemux->dmx.close(&dvbdemux->dmx); -- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->hw_frontend); -- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->mem_frontend); -- dvb_dmxdev_release(&input->dmxdev); -+ struct ddb_input *input = fe->sec_priv; -+ struct ddb_port *port = input->port; -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int s = 0; - -- case 2: -- dvb_dmx_release(&input->demux); -+ mutex_lock(&dev->lnb_lock); -+ switch (tone) { -+ case SEC_TONE_OFF: -+ dev->lnb_tone &= ~(1ULL << dvb->input); -+ break; -+ case SEC_TONE_ON: -+ dev->lnb_tone |= (1ULL << dvb->input); -+ break; -+ default: -+ s = -EINVAL; -+ break; -+ }; -+ if (!s) -+ s = lnb_command(dev, dvb->input, LNB_CMD_NOP); -+ mutex_unlock(&dev->lnb_lock); -+ return 0; -+} - -- case 1: -- dvb_unregister_adapter(adap); -- } -- input->attached = 0; -+static int dd_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) -+{ -+ -+ return 0; - } - --static int dvb_input_attach(struct ddb_input *input) -+static int dd_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) - { -- int ret; -+ struct ddb_input *input = fe->sec_priv; - struct ddb_port *port = input->port; -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -- -- ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -- &input->port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) { -- printk(KERN_ERR "ddbridge: Could not register adapter." -- "Check if you enabled enough adapters in dvb-core!\n"); -+ struct ddb *dev = port->dev; -+ struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; -+ int s = 0; -+ -+ mutex_lock(&dev->lnb_lock); -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ lnb_command(dev, dvb->input, LNB_CMD_OFF); -+ break; -+ case SEC_VOLTAGE_13: -+ lnb_command(dev, dvb->input, LNB_CMD_LOW); -+ break; -+ case SEC_VOLTAGE_18: -+ lnb_command(dev, dvb->input, LNB_CMD_HIGH); -+ break; -+ default: -+ s = -EINVAL; -+ break; -+ }; -+ mutex_unlock(&dev->lnb_lock); -+ return s; -+} -+ -+static int dd_set_input(struct dvb_frontend *fe) -+{ -+ -+ return 0; -+} -+ -+static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, -+ int (*start_feed)(struct dvb_demux_feed *), -+ int (*stop_feed)(struct dvb_demux_feed *), -+ void *priv) -+{ -+ dvbdemux->priv = priv; -+ -+ dvbdemux->filternum = 256; -+ dvbdemux->feednum = 256; -+ dvbdemux->start_feed = start_feed; -+ dvbdemux->stop_feed = stop_feed; -+ dvbdemux->write_to_decoder = NULL; -+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | -+ DMX_SECTION_FILTERING | -+ DMX_MEMORY_BASED_FILTERING); -+ return dvb_dmx_init(dvbdemux); -+} -+ -+static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, -+ struct dvb_demux *dvbdemux, -+ struct dmx_frontend *hw_frontend, -+ struct dmx_frontend *mem_frontend, -+ struct dvb_adapter *dvb_adapter) -+{ -+ int ret; -+ -+ dmxdev->filternum = 256; -+ dmxdev->demux = &dvbdemux->dmx; -+ dmxdev->capabilities = 0; -+ ret = dvb_dmxdev_init(dmxdev, dvb_adapter); -+ if (ret < 0) - return ret; -+ -+ hw_frontend->source = DMX_FRONTEND_0; -+ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); -+ mem_frontend->source = DMX_MEMORY_FE; -+ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); -+ return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); -+} -+ -+#if 0 -+static int start_input(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (!dvb->users) -+ ddb_input_start_all(input); -+ -+ return ++dvb->users; -+} -+ -+static int stop_input(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (--dvb->users) -+ return dvb->users; -+ -+ ddb_input_stop_all(input); -+ return 0; -+} -+#endif -+ -+static int start_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct ddb_input *input = dvbdmx->priv; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (!dvb->users) -+ ddb_input_start_all(input); -+ -+ return ++dvb->users; -+} -+ -+static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct ddb_input *input = dvbdmx->priv; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ -+ if (--dvb->users) -+ return dvb->users; -+ -+ ddb_input_stop_all(input); -+ return 0; -+} -+ -+static void dvb_input_detach(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_demux *dvbdemux = &dvb->demux; -+ -+ switch (dvb->attached) { -+ case 0x31: -+ if (dvb->fe2) -+ dvb_unregister_frontend(dvb->fe2); -+ if (dvb->fe) -+ dvb_unregister_frontend(dvb->fe); -+ /* fallthrough */ -+ case 0x30: -+ dvb_frontend_detach(dvb->fe); -+ dvb->fe = dvb->fe2 = NULL; -+ /* fallthrough */ -+ case 0x21: -+ if (input->port->dev->ns_num) -+ dvb_netstream_release(&dvb->dvbns); -+ /* fallthrough */ -+ case 0x20: -+ dvb_net_release(&dvb->dvbnet); -+ /* fallthrough */ -+ case 0x11: -+ dvbdemux->dmx.close(&dvbdemux->dmx); -+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -+ &dvb->hw_frontend); -+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -+ &dvb->mem_frontend); -+ dvb_dmxdev_release(&dvb->dmxdev); -+ /* fallthrough */ -+ case 0x10: -+ dvb_dmx_release(&dvb->demux); -+ /* fallthrough */ -+ case 0x01: -+ break; -+ } -+ dvb->attached = 0x00; -+} -+ -+static int dvb_register_adapters(struct ddb *dev) -+{ -+ int i, ret = 0; -+ struct ddb_port *port; -+ struct dvb_adapter *adap; -+ -+ if (adapter_alloc == 3 || dev->info->type == DDB_MOD) { -+ port = &dev->port[0]; -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ port->dvb[0].adap = adap; -+ port->dvb[1].adap = adap; -+ } -+ return 0; -+ } -+ -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ switch (port->class) { -+ case DDB_PORT_TUNER: -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ -+ if (adapter_alloc > 0) { -+ port->dvb[1].adap = port->dvb[0].adap; -+ break; -+ } -+ adap = port->dvb[1].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[1].adap_registered = 1; -+ break; -+ -+ case DDB_PORT_CI: -+ case DDB_PORT_LOOP: -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ break; -+ default: -+ if (adapter_alloc < 2) -+ break; -+ adap = port->dvb[0].adap; -+ ret = dvb_register_adapter(adap, "DDBridge", -+ THIS_MODULE, -+ port->dev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->dvb[0].adap_registered = 1; -+ break; -+ } -+ } -+ return ret; -+} -+ -+static void dvb_unregister_adapters(struct ddb *dev) -+{ -+ int i; -+ struct ddb_port *port; -+ struct ddb_dvb *dvb; -+ -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ -+ dvb = &port->dvb[0]; -+ if (dvb->adap_registered) -+ dvb_unregister_adapter(dvb->adap); -+ dvb->adap_registered = 0; -+ -+ dvb = &port->dvb[1]; -+ if (dvb->adap_registered) -+ dvb_unregister_adapter(dvb->adap); -+ dvb->adap_registered = 0; - } -- input->attached = 1; -+} -+ -+static int dvb_input_attach(struct ddb_input *input) -+{ -+ int ret = 0; -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct ddb_port *port = input->port; -+ struct dvb_adapter *adap = dvb->adap; -+ struct dvb_demux *dvbdemux = &dvb->demux; -+ -+ dvb->attached = 0x01; - - ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", - start_feed, - stop_feed, input); - if (ret < 0) - return ret; -- input->attached = 2; -+ dvb->attached = 0x10; - -- ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux, -- &input->hw_frontend, -- &input->mem_frontend, adap); -+ ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev, -+ &dvb->demux, -+ &dvb->hw_frontend, -+ &dvb->mem_frontend, adap); - if (ret < 0) - return ret; -- input->attached = 3; -+ dvb->attached = 0x11; - -- ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux); -+ ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux); - if (ret < 0) - return ret; -- input->attached = 4; -+ dvb->attached = 0x20; - -- input->fe = NULL; -+ if (input->port->dev->ns_num) { -+ ret = netstream_init(input); -+ if (ret < 0) -+ return ret; -+ dvb->attached = 0x21; -+ } -+ dvb->fe = dvb->fe2 = 0; - switch (port->type) { - case DDB_TUNER_DVBS_ST: - if (demod_attach_stv0900(input, 0) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 0) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } -+ break; -+ case DDB_TUNER_DVBS_STV0910: -+ case DDB_TUNER_DVBS_STV0910_P: -+ if (demod_attach_stv0910(input, 0) < 0) -+ return -ENODEV; -+ if (tuner_attach_stv6111(input) < 0) -+ return -ENODEV; - break; - case DDB_TUNER_DVBS_ST_AA: - if (demod_attach_stv0900(input, 1) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 1) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } - break; -+#if IS_ENABLED(CONFIG_DVB_DRXK) - case DDB_TUNER_DVBCT_TR: - if (demod_attach_drxk(input) < 0) - return -ENODEV; - if (tuner_attach_tda18271(input) < 0) - return -ENODEV; -- if (dvb_register_frontend(adap, input->fe) < 0) -+ break; -+#endif -+ case DDB_TUNER_DVBCT_ST: -+ if (demod_attach_stv0367dd(input) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212dd(input) < 0) -+ return -ENODEV; -+ break; -+ case DDB_TUNER_DVBCT2_SONY: -+ case DDB_TUNER_DVBC2T2_SONY: -+ case DDB_TUNER_ISDBT_SONY: -+ if (demod_attach_cxd2843(input, 0) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212dd(input) < 0) -+ return -ENODEV; -+ break; -+ case DDB_TUNER_DVBCT2_SONY_P: -+ case DDB_TUNER_DVBC2T2_SONY_P: -+ case DDB_TUNER_ISDBT_SONY_P: -+ if (demod_attach_cxd2843(input, 1) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212dd(input) < 0) - return -ENODEV; -- if (input->fe2) { -- if (dvb_register_frontend(adap, input->fe2) < 0) -- return -ENODEV; -- input->fe2->tuner_priv = input->fe->tuner_priv; -- memcpy(&input->fe2->ops.tuner_ops, -- &input->fe->ops.tuner_ops, -- sizeof(struct dvb_tuner_ops)); -- } - break; -+ default: -+ return 0; - } -- input->attached = 5; -+ dvb->attached = 0x30; -+ if (dvb->fe) { -+ if (dvb_register_frontend(adap, dvb->fe) < 0) -+ return -ENODEV; -+ } -+ if (dvb->fe2) { -+ if (dvb_register_frontend(adap, dvb->fe2) < 0) -+ return -ENODEV; -+ dvb->fe2->tuner_priv = dvb->fe->tuner_priv; -+ memcpy(&dvb->fe2->ops.tuner_ops, -+ &dvb->fe->ops.tuner_ops, -+ sizeof(struct dvb_tuner_ops)); -+ } -+ dvb->attached = 0x31; - return 0; - } - --/****************************************************************************/ --/****************************************************************************/ - --static ssize_t ts_write(struct file *file, const __user char *buf, -- size_t count, loff_t *ppos) -+static int port_has_encti(struct ddb_port *port) - { -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- size_t left = count; -- int stat; -+ u8 val; -+ int ret = i2c_read_reg(&port->i2c->adap, 0x20, 0, &val); - -- while (left) { -- if (ddb_output_free(output) < 188) { -- if (file->f_flags & O_NONBLOCK) -- break; -- if (wait_event_interruptible( -- output->wq, ddb_output_free(output) >= 188) < 0) -- break; -- } -- stat = ddb_output_write(output, buf, left); -- if (stat < 0) -- break; -- buf += stat; -- left -= stat; -- } -- return (left == count) ? -EAGAIN : (count - left); -+ if (!ret) -+ pr_info("[0x20]=0x%02x\n", val); -+ return ret ? 0 : 1; - } - --static ssize_t ts_read(struct file *file, __user char *buf, -- size_t count, loff_t *ppos) -+static int port_has_cxd(struct ddb_port *port, u8 *type) - { -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- struct ddb_input *input = output->port->input[0]; -- int left, read; -+ u8 val; -+ u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; -+ struct i2c_msg msgs[2] = {{ .addr = 0x40, .flags = 0, -+ .buf = probe, .len = 4 }, -+ { .addr = 0x40, .flags = I2C_M_RD, -+ .buf = data, .len = 4 } }; -+ val = i2c_transfer(&port->i2c->adap, msgs, 2); -+ if (val != 2) -+ return 0; - -- count -= count % 188; -- left = count; -- while (left) { -- if (ddb_input_avail(input) < 188) { -- if (file->f_flags & O_NONBLOCK) -- break; -- if (wait_event_interruptible( -- input->wq, ddb_input_avail(input) >= 188) < 0) -- break; -- } -- read = ddb_input_read(input, buf, left); -- if (read < 0) -- return read; -- left -= read; -- buf += read; -- } -- return (left == count) ? -EAGAIN : (count - left); -+ if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43) -+ *type = 2; -+ else -+ *type = 1; -+ return 1; - } - --static unsigned int ts_poll(struct file *file, poll_table *wait) -+static int port_has_xo2(struct ddb_port *port, u8 *id) - { -- /* -- struct dvb_device *dvbdev = file->private_data; -- struct ddb_output *output = dvbdev->priv; -- struct ddb_input *input = output->port->input[0]; -- */ -- unsigned int mask = 0; -+ u8 val; -+ u8 probe[1] = { 0x00 }, data[4]; -+ struct i2c_msg msgs[2] = {{ .addr = 0x10, .flags = 0, -+ .buf = probe, .len = 1 }, -+ { .addr = 0x10, .flags = I2C_M_RD, -+ .buf = data, .len = 4 } }; -+ val = i2c_transfer(&port->i2c->adap, msgs, 2); -+ if (val != 2) -+ return 0; -+ -+ if (data[0] != 'D' || data[1] != 'F') -+ return 0; -+ -+ *id = data[2]; -+ return 1; -+} -+ -+static int port_has_stv0900(struct ddb_port *port) -+{ -+ u8 val; -+ if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_stv0900_aa(struct ddb_port *port, u8 *id) -+{ -+ if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, id) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_drxks(struct ddb_port *port) -+{ -+ u8 val; -+ if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) -+ return 0; -+ if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) -+ return 0; -+ return 1; -+} -+ -+static int port_has_stv0367(struct ddb_port *port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ return 1; -+} - - #if 0 -- if (data_avail_to_read) -- mask |= POLLIN | POLLRDNORM; -- if (data_avail_to_write) -- mask |= POLLOUT | POLLWRNORM; -+static int init_xo2_old(struct ddb_port *port) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ u8 val; -+ int res; -+ -+ res = i2c_read_reg(i2c, 0x10, 0x04, &val); -+ if (res < 0) -+ return res; -+ -+ if (val != 0x02) { -+ pr_info("Port %d: invalid XO2\n", port->nr); -+ return -1; -+ } -+ i2c_write_reg(i2c, 0x10, 0xc0, 0x00); /* Disable XO2 I2C master */ -+ -+ i2c_read_reg(i2c, 0x10, 0x08, &val); -+ if (val != 0) { -+ i2c_write_reg(i2c, 0x10, 0x08, 0x00); -+ msleep(100); -+ } -+ /* Enable tuner power, disable pll, reset demods */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x04); -+ usleep_range(2000, 3000); -+ /* Release demod resets */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x07); -+ usleep_range(2000, 3000); -+ /* Start XO2 PLL */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x87); - -- poll_wait(file, &read_queue, wait); -- poll_wait(file, &write_queue, wait); -+ return 0; -+} - #endif -- return mask; -+ -+static int init_xo2(struct ddb_port *port) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ u8 val, data[2]; -+ int res; -+ -+ res = i2c_read_regs(i2c, 0x10, 0x04, data, 2); -+ if (res < 0) -+ return res; -+ -+ if (data[0] != 0x01) { -+ pr_info("Port %d: invalid XO2\n", port->nr); -+ return -1; -+ } -+ -+ i2c_read_reg(i2c, 0x10, 0x08, &val); -+ if (val != 0) { -+ i2c_write_reg(i2c, 0x10, 0x08, 0x00); -+ msleep(100); -+ } -+ /* Enable tuner power, disable pll, reset demods */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x04); -+ usleep_range(2000, 3000); -+ /* Release demod resets */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x07); -+ usleep_range(2000, 3000); -+ /* Start XO2 PLL */ -+ i2c_write_reg(i2c, 0x10, 0x08, 0x87); -+ -+ return 0; - } - --static const struct file_operations ci_fops = { -- .owner = THIS_MODULE, -- .read = ts_read, -- .write = ts_write, -- .open = dvb_generic_open, -- .release = dvb_generic_release, -- .poll = ts_poll, -+static int port_has_cxd28xx(struct ddb_port *port, u8 *id) -+{ -+ struct i2c_adapter *i2c = &port->i2c->adap; -+ int status; -+ -+ status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0); -+ if (status) -+ return 0; -+ status = i2c_read_reg(i2c, 0x6e, 0xfd, id); -+ if (status) -+ return 0; -+ return 1; -+} -+ -+static char *xo2names[] = { -+ "DUAL DVB-S2", "DUAL DVB-C/T/T2", -+ "DUAL DVB-ISDBT", "DUAL DVB-C/C2/T/T2", -+ "DUAL ATSC", "DUAL DVB-C/C2/T/T2", -+ "", "" - }; - --static struct dvb_device dvbdev_ci = { -- .readers = -1, -- .writers = -1, -- .users = -1, -- .fops = &ci_fops, --}; -+static void ddb_port_probe(struct ddb_port *port) -+{ -+ struct ddb *dev = port->dev; -+ u8 id; -+ -+ port->name = "NO MODULE"; -+ port->class = DDB_PORT_NONE; -+ -+ if (dev->info->type == DDB_MOD) { -+ port->name = "MOD"; -+ port->class = DDB_PORT_MOD; -+ return; -+ } -+ -+ if (dev->info->type == DDB_OCTOPUS_MAX) { -+ port->name = "DUAL DVB-S2 MX"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_MXL5XX; -+ if (port->i2c) -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ return; -+ } -+ -+ if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) { -+ port->name = "CI internal"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_INTERNAL; -+ } else if (port_has_cxd(port, &id)) { -+ if (id == 1) { -+ port->name = "CI"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_EXTERNAL_SONY; -+ ddbwritel(dev, I2C_SPEED_400, -+ port->i2c->regs + I2C_TIMING); -+ } else { -+ pr_info(KERN_INFO "Port %d: Uninitialized DuoFlex\n", -+ port->nr); -+ return; -+ } -+ } else if (port_has_xo2(port, &id)) { -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ id >>= 2; -+ if (id > 5) { -+ port->name = "unknown XO2 DuoFlex"; -+ } else { -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_XO2 + id; -+ port->name = xo2names[id]; -+ init_xo2(port); -+ } -+ } else if (port_has_cxd28xx(port, &id)) { -+ switch (id) { -+ case 0xa4: -+ port->name = "DUAL DVB-CT2 CXD2843"; -+ port->type = DDB_TUNER_DVBC2T2_SONY_P; -+ break; -+ case 0xb1: -+ port->name = "DUAL DVB-CT2 CXD2837"; -+ port->type = DDB_TUNER_DVBCT2_SONY_P; -+ break; -+ case 0xb0: -+ port->name = "DUAL ISDB-T CXD2838"; -+ port->type = DDB_TUNER_ISDBT_SONY_P; -+ break; -+ default: -+ return; -+ } -+ port->class = DDB_PORT_TUNER; -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0900(port)) { -+ port->name = "DUAL DVB-S2"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBS_ST; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0900_aa(port, &id)) { -+ port->name = "DUAL DVB-S2"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBS_ST_AA; -+ if (id == 0x51) -+ port->type = DDB_TUNER_DVBS_STV0910_P; -+ else -+ port->type = DDB_TUNER_DVBS_ST_AA; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_drxks(port)) { -+ port->name = "DUAL DVB-C/T"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBCT_TR; -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0367(port)) { -+ port->name = "DUAL DVB-C/T"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBCT_ST; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_encti(port)) { -+ port->name = "ENCTI"; -+ port->class = DDB_PORT_LOOP; -+ } else if (port->nr == ts_loop) { -+ port->name = "TS LOOP"; -+ port->class = DDB_PORT_LOOP; -+ } -+} -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static int wait_ci_ready(struct ddb_ci *ci) -+{ -+ u32 count = 10; -+ -+ ndelay(500); -+ do { -+ if (ddbreadl(ci->port->dev, -+ CI_CONTROL(ci->nr)) & CI_READY) -+ break; -+ usleep_range(1, 2); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0; -+} -+ -+static int read_attribute_mem(struct dvb_ca_en50221 *ca, -+ int slot, int address) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1); -+ -+ if (address > CI_BUFFER_SIZE) -+ return -1; -+ ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, -+ CI_DO_READ_ATTRIBUTES(ci->nr)); -+ wait_ci_ready(ci); -+ val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); -+ return val; -+} -+ -+static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, -+ int address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_ATTRIBUTE_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int read_cam_control(struct dvb_ca_en50221 *ca, -+ int slot, u8 address) -+{ -+ u32 count = 100; -+ struct ddb_ci *ci = ca->data; -+ u32 res; -+ -+ ddbwritel(ci->port->dev, CI_READ_CMD | address, -+ CI_DO_IO_RW(ci->nr)); -+ ndelay(500); -+ do { -+ res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); -+ if (res & CI_READY) -+ break; -+ usleep_range(1, 2); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0xff & res; -+} -+ -+static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, -+ u8 address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_IO_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int slot_reset(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ msleep(100); -+ ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ udelay(20); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} - --/****************************************************************************/ --/****************************************************************************/ --/****************************************************************************/ -+static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; - --static void input_tasklet(unsigned long data) -+ ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); -+ msleep(300); -+ return 0; -+} -+ -+static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) - { -- struct ddb_input *input = (struct ddb_input *) data; -- struct ddb *dev = input->port->dev; -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); - -- spin_lock(&input->lock); -- if (!input->running) { -- spin_unlock(&input->lock); -- return; -- } -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -+ ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} - -- if (input->port->class == DDB_PORT_TUNER) { -- if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) -- printk(KERN_ERR "Overflow input %d\n", input->nr); -- while (input->cbuf != ((input->stat >> 11) & 0x1f) -- || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { -- dvb_dmx_swfilter_packets(&input->demux, -- input->vbuf[input->cbuf], -- input->dma_buf_size / 188); -+static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); -+ int stat = 0; - -- input->cbuf = (input->cbuf + 1) % input->dma_buf_num; -- ddbwritel((input->cbuf << 11), -- DMA_BUFFER_ACK(input->nr)); -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -- } -- } -- if (input->port->class == DDB_PORT_CI) -- wake_up(&input->wq); -- spin_unlock(&input->lock); -+ if (val & CI_CAM_DETECT) -+ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; -+ if (val & CI_CAM_READY) -+ stat |= DVB_CA_EN50221_POLL_CAM_READY; -+ return stat; - } - --static void output_tasklet(unsigned long data) -+static struct dvb_ca_en50221 en_templ = { -+ .read_attribute_mem = read_attribute_mem, -+ .write_attribute_mem = write_attribute_mem, -+ .read_cam_control = read_cam_control, -+ .write_cam_control = write_cam_control, -+ .slot_reset = slot_reset, -+ .slot_shutdown = slot_shutdown, -+ .slot_ts_enable = slot_ts_enable, -+ .poll_slot_status = poll_slot_status, -+}; -+ -+static void ci_attach(struct ddb_port *port) - { -- struct ddb_output *output = (struct ddb_output *) data; -- struct ddb *dev = output->port->dev; -+ struct ddb_ci *ci = 0; - -- spin_lock(&output->lock); -- if (!output->running) { -- spin_unlock(&output->lock); -+ ci = kzalloc(sizeof(*ci), GFP_KERNEL); -+ if (!ci) - return; -- } -- output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8)); -- wake_up(&output->wq); -- spin_unlock(&output->lock); -+ memcpy(&ci->en, &en_templ, sizeof(en_templ)); -+ ci->en.data = ci; -+ port->en = &ci->en; -+ ci->port = port; -+ ci->nr = port->nr - 2; - } - -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ - --static struct cxd2099_cfg cxd_cfg = { -- .bitrate = 62000, -+struct cxd2099_cfg cxd_cfg = { -+ .bitrate = 72000, - .adr = 0x40, - .polarity = 1, - .clock_mode = 1, -@@ -1045,28 +2163,21 @@ static struct cxd2099_cfg cxd_cfg = { - - static int ddb_ci_attach(struct ddb_port *port) - { -- int ret; -- -- ret = dvb_register_adapter(&port->output->adap, -- "DDBridge", -- THIS_MODULE, -- &port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) -- return ret; -- port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -- if (!port->en) { -- dvb_unregister_adapter(&port->output->adap); -- return -ENODEV; -+ if (port->type == DDB_CI_EXTERNAL_SONY) { -+ cxd_cfg.bitrate = ci_bitrate; -+ port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->dvb[0].adap, -+ port->en, 0, 1); - } -- ddb_input_start(port->input[0]); -- ddb_output_start(port->output); -- dvb_ca_en50221_init(&port->output->adap, -- port->en, 0, 1); -- ret = dvb_register_device(&port->output->adap, &port->output->dev, -- &dvbdev_ci, (void *) port->output, -- DVB_DEVICE_SEC); -- return ret; -+ if (port->type == DDB_CI_INTERNAL) { -+ ci_attach(port); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); -+ } -+ return 0; - } - - static int ddb_port_attach(struct ddb_port *port) -@@ -1079,15 +2190,32 @@ static int ddb_port_attach(struct ddb_port *port) - if (ret < 0) - break; - ret = dvb_input_attach(port->input[1]); -+ if (ret < 0) -+ break; -+ port->input[0]->redi = port->input[0]; -+ port->input[1]->redi = port->input[1]; - break; - case DDB_PORT_CI: - ret = ddb_ci_attach(port); -+ if (ret < 0) -+ break; -+ case DDB_PORT_LOOP: -+ ret = dvb_register_device(port->dvb[0].adap, -+ &port->dvb[0].dev, -+ &dvbdev_ci, (void *) port->output, -+ DVB_DEVICE_CI); -+ break; -+ case DDB_PORT_MOD: -+ ret = dvb_register_device(port->dvb[0].adap, -+ &port->dvb[0].dev, -+ &dvbdev_mod, (void *) port->output, -+ DVB_DEVICE_MOD); - break; - default: - break; - } - if (ret < 0) -- printk(KERN_ERR "port_attach on port %d failed\n", port->nr); -+ pr_err("port_attach on port %d failed\n", port->nr); - return ret; - } - -@@ -1096,6 +2224,21 @@ static int ddb_ports_attach(struct ddb *dev) - int i, ret = 0; - struct ddb_port *port; - -+ if (dev->ids.devid == 0x0301dd01) -+ dev->ns_num = 15; -+ else -+ dev->ns_num = dev->info->ns_num; -+ for (i = 0; i < dev->ns_num; i++) -+ dev->ns[i].nr = i; -+ pr_info("%d netstream channels\n", dev->ns_num); -+ -+ if (dev->info->port_num) { -+ ret = dvb_register_adapters(dev); -+ if (ret < 0) { -+ pr_err("Registering adapters failed. Check DVB_MAX_ADAPTERS in config.\n"); -+ return ret; -+ } -+ } - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; - ret = ddb_port_attach(port); -@@ -1112,124 +2255,259 @@ static void ddb_ports_detach(struct ddb *dev) - - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; -+ - switch (port->class) { - case DDB_PORT_TUNER: - dvb_input_detach(port->input[0]); - dvb_input_detach(port->input[1]); - break; - case DDB_PORT_CI: -- dvb_unregister_device(port->output->dev); -+ case DDB_PORT_LOOP: -+ if (port->dvb[0].dev) -+ dvb_unregister_device(port->dvb[0].dev); - if (port->en) { -- ddb_input_stop(port->input[0]); -- ddb_output_stop(port->output); - dvb_ca_en50221_release(port->en); - kfree(port->en); -- port->en = NULL; -- dvb_unregister_adapter(&port->output->adap); -+ port->en = 0; - } - break; -+ case DDB_PORT_MOD: -+ if (port->dvb[0].dev) -+ dvb_unregister_device(port->dvb[0].dev); -+ break; - } - } -+ dvb_unregister_adapters(dev); - } - --/****************************************************************************/ --/****************************************************************************/ - --static int port_has_ci(struct ddb_port *port) -+/* Copy input DMA pointers to output DMA and ACK. */ -+ -+static void input_write_output(struct ddb_input *input, -+ struct ddb_output *output) - { -- u8 val; -- return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1; -+ ddbwritel(output->port->dev, -+ input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); -+ output->dma->cbuf = (input->dma->stat >> 11) & 0x1f; -+ output->dma->coff = (input->dma->stat & 0x7ff) << 7; - } - --static int port_has_stv0900(struct ddb_port *port) -+static void output_ack_input(struct ddb_output *output, -+ struct ddb_input *input) - { -- u8 val; -- if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0) -- return 0; -- return 1; -+ ddbwritel(input->port->dev, -+ output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); - } - --static int port_has_stv0900_aa(struct ddb_port *port) -+static void input_write_dvb(struct ddb_input *input, -+ struct ddb_input *input2) - { -- u8 val; -- if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0) -- return 0; -- return 1; -+ struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1]; -+ struct ddb_dma *dma, *dma2; -+ struct ddb *dev = input->port->dev; -+ int noack = 0; -+ -+ dma = dma2 = input->dma; -+ /* if there also is an output connected, do not ACK. -+ input_write_output will ACK. */ -+ if (input->redo) { -+ dma2 = input->redo->dma; -+ noack = 1; -+ } -+ while (dma->cbuf != ((dma->stat >> 11) & 0x1f) -+ || (4 & dma->ctrl)) { -+ if (4 & dma->ctrl) { -+ /*pr_err("Overflow dma %d\n", dma->nr);*/ -+ if (noack) -+ noack = 0; -+ } -+#ifdef DDB_ALT_DMA -+ dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], -+ dma2->size, DMA_FROM_DEVICE); -+#endif -+ dvb_dmx_swfilter_packets(&dvb->demux, -+ dma2->vbuf[dma->cbuf], -+ dma2->size / 188); -+ dma->cbuf = (dma->cbuf + 1) % dma2->num; -+ if (!noack) -+ ddbwritel(dev, (dma->cbuf << 11), -+ DMA_BUFFER_ACK(dma->nr)); -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ } - } - --static int port_has_drxks(struct ddb_port *port) -+#ifdef DDB_USE_WORK -+static void input_work(struct work_struct *work) - { -- u8 val; -- if (i2c_read(&port->i2c->adap, 0x29, &val) < 0) -- return 0; -- if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0) -- return 0; -- return 1; -+ struct ddb_dma *dma = container_of(work, struct ddb_dma, work); -+ struct ddb_input *input = (struct ddb_input *) dma->io; -+#else -+static void input_tasklet(unsigned long data) -+{ -+ struct ddb_input *input = (struct ddb_input *) data; -+ struct ddb_dma *dma = input->dma; -+#endif -+ struct ddb *dev = input->port->dev; -+ -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); -+ return; -+ } -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ -+#if 0 -+ if (4 & dma->ctrl) -+ pr_err("Overflow dma %d\n", dma->nr); -+#endif -+ if (input->redi) -+ input_write_dvb(input, input->redi); -+ if (input->redo) -+ input_write_output(input, input->redo); -+ wake_up(&dma->wq); -+ spin_unlock(&dma->lock); - } - --static void ddb_port_probe(struct ddb_port *port) -+static void input_handler(unsigned long data) - { -- struct ddb *dev = port->dev; -- char *modname = "NO MODULE"; -+ struct ddb_input *input = (struct ddb_input *) data; -+ struct ddb_dma *dma = input->dma; - -- port->class = DDB_PORT_NONE; - -- if (port_has_ci(port)) { -- modname = "CI"; -- port->class = DDB_PORT_CI; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -- } else if (port_has_stv0900(port)) { -- modname = "DUAL DVB-S2"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBS_ST; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -- } else if (port_has_stv0900_aa(port)) { -- modname = "DUAL DVB-S2"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBS_ST_AA; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -- } else if (port_has_drxks(port)) { -- modname = "DUAL DVB-C/T"; -- port->class = DDB_PORT_TUNER; -- port->type = DDB_TUNER_DVBCT_TR; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ /* If there is no input connected, input_tasklet() will -+ just copy pointers and ACK. So, there is no need to go -+ through the tasklet scheduler. */ -+#ifdef DDB_USE_WORK -+ if (input->redi) -+ queue_work(ddb_wq, &dma->work); -+ else -+ input_work(&dma->work); -+#else -+ if (input->redi) -+ tasklet_schedule(&dma->tasklet); -+ else -+ input_tasklet(data); -+#endif -+} -+ -+/* hmm, don't really need this anymore. -+ The output IRQ just copies some pointers, acks and wakes. */ -+ -+#ifdef DDB_USE_WORK -+static void output_work(struct work_struct *work) -+{ -+} -+#else -+static void output_tasklet(unsigned long data) -+{ -+} -+#endif -+ -+static void output_handler(unsigned long data) -+{ -+ struct ddb_output *output = (struct ddb_output *) data; -+ struct ddb_dma *dma = output->dma; -+ struct ddb *dev = output->port->dev; -+ -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); -+ return; -+ } -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ if (output->redi) -+ output_ack_input(output, output->redi); -+ wake_up(&dma->wq); -+ spin_unlock(&dma->lock); -+} -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+ -+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out) -+{ -+#ifndef DDB_USE_WORK -+ unsigned long priv = (unsigned long) io; -+#endif -+ -+ dma->io = io; -+ dma->nr = nr; -+ spin_lock_init(&dma->lock); -+ init_waitqueue_head(&dma->wq); -+ if (out) { -+#ifdef DDB_USE_WORK -+ INIT_WORK(&dma->work, output_work); -+#else -+ tasklet_init(&dma->tasklet, output_tasklet, priv); -+#endif -+ dma->num = OUTPUT_DMA_BUFS; -+ dma->size = OUTPUT_DMA_SIZE; -+ dma->div = OUTPUT_DMA_IRQ_DIV; -+ } else { -+#ifdef DDB_USE_WORK -+ INIT_WORK(&dma->work, input_work); -+#else -+ tasklet_init(&dma->tasklet, input_tasklet, priv); -+#endif -+ dma->num = INPUT_DMA_BUFS; -+ dma->size = INPUT_DMA_SIZE; -+ dma->div = INPUT_DMA_IRQ_DIV; - } -- printk(KERN_INFO "Port %d (TAB %d): %s\n", -- port->nr, port->nr+1, modname); - } - --static void ddb_input_init(struct ddb_port *port, int nr) -+static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int dma_nr) - { - struct ddb *dev = port->dev; - struct ddb_input *input = &dev->input[nr]; - -+ if (dev->has_dma) { -+ dev->handler[dma_nr + 8] = input_handler; -+ dev->handler_data[dma_nr + 8] = (unsigned long) input; -+ } -+ port->input[pnr] = input; - input->nr = nr; - input->port = port; -- input->dma_buf_num = INPUT_DMA_BUFS; -- input->dma_buf_size = INPUT_DMA_SIZE; -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(2, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, DMA_BUFFER_ACK(nr)); -- tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input); -- spin_lock_init(&input->lock); -- init_waitqueue_head(&input->wq); -+ if (dev->has_dma) { -+ input->dma = &dev->dma[dma_nr]; -+ ddb_dma_init(input->dma, dma_nr, (void *) input, 0); -+ } -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ if (dev->has_dma) -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); - } - --static void ddb_output_init(struct ddb_port *port, int nr) -+static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr) - { - struct ddb *dev = port->dev; - struct ddb_output *output = &dev->output[nr]; -+ -+ if (dev->has_dma) { -+ dev->handler[dma_nr + 8] = output_handler; -+ dev->handler_data[dma_nr + 8] = (unsigned long) output; -+ } -+ port->output = output; - output->nr = nr; - output->port = port; -- output->dma_buf_num = OUTPUT_DMA_BUFS; -- output->dma_buf_size = OUTPUT_DMA_SIZE; -- -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output); -- init_waitqueue_head(&output->wq); -+ if (dev->has_dma) { -+ output->dma = &dev->dma[dma_nr]; -+ ddb_dma_init(output->dma, dma_nr, (void *) output, 1); -+ } -+ if (output->port->class == DDB_PORT_MOD) { -+ /*ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));*/ -+ } else { -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); -+ } -+ if (dev->has_dma) -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); - } - - static void ddb_ports_init(struct ddb *dev) -@@ -1237,20 +2515,53 @@ static void ddb_ports_init(struct ddb *dev) - int i; - struct ddb_port *port; - -+ if (dev->info->board_control) { -+ ddbwritel(dev, 0, BOARD_CONTROL); -+ msleep(100); -+ ddbwritel(dev, 4, BOARD_CONTROL); -+ usleep_range(2000, 3000); -+ ddbwritel(dev, 4 | dev->info->board_control, BOARD_CONTROL); -+ usleep_range(2000, 3000); -+ } -+ - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; - port->dev = dev; - port->nr = i; -- port->i2c = &dev->i2c[i]; -- port->input[0] = &dev->input[2 * i]; -- port->input[1] = &dev->input[2 * i + 1]; -- port->output = &dev->output[i]; -- -+ if (dev->info->i2c_num > i) -+ port->i2c = &dev->i2c[i]; -+ port->gap = 4; -+ port->obr = ci_bitrate; - mutex_init(&port->i2c_gate_lock); - ddb_port_probe(port); -- ddb_input_init(port, 2 * i); -- ddb_input_init(port, 2 * i + 1); -- ddb_output_init(port, i); -+ pr_info("Port %d (TAB %d): %s\n", -+ port->nr, port->nr + 1, port->name); -+ -+ port->dvb[0].adap = &dev->adap[2 * i]; -+ port->dvb[1].adap = &dev->adap[2 * i + 1]; -+ -+ if ((dev->info->type == DDB_OCTOPUS_CI) || -+ (dev->info->type == DDB_OCTONET) || -+ (dev->info->type == DDB_OCTOPUS)) { -+ if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) { -+ ddb_input_init(port, 2 + i, 0, 2 + i); -+ ddb_input_init(port, 4 + i, 1, 4 + i); -+ } else { -+ ddb_input_init(port, 2 * i, 0, 2 * i); -+ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1); -+ } -+ ddb_output_init(port, i, i + 8); -+ } -+ if (dev->info->type == DDB_OCTOPUS_MAX) { -+ ddb_input_init(port, 2 * i, 0, 2 * i); -+ ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1); -+ } -+ if (dev->info->type == DDB_MOD) { -+ ddb_output_init(port, i, i); -+ dev->handler[i + 18] = ddbridge_mod_rate_handler; -+ dev->handler_data[i + 18] = -+ (unsigned long) &dev->output[i]; -+ } - } - } - -@@ -1259,12 +2570,25 @@ static void ddb_ports_release(struct ddb *dev) - int i; - struct ddb_port *port; - -+ if (!dev->has_dma) -+ return; - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; -- port->dev = dev; -- tasklet_kill(&port->input[0]->tasklet); -- tasklet_kill(&port->input[1]->tasklet); -- tasklet_kill(&port->output->tasklet); -+#ifdef DDB_USE_WORK -+ if (port->input[0]) -+ cancel_work_sync(&port->input[0]->dma->work); -+ if (port->input[1]) -+ cancel_work_sync(&port->input[1]->dma->work); -+ if (port->output) -+ cancel_work_sync(&port->output->dma->work); -+#else -+ if (port->input[0]) -+ tasklet_kill(&port->input[0]->dma->tasklet); -+ if (port->input[1]) -+ tasklet_kill(&port->input[1]->dma->tasklet); -+ if (port->output) -+ tasklet_kill(&port->output->dma->tasklet); -+#endif - } - } - -@@ -1272,90 +2596,306 @@ static void ddb_ports_release(struct ddb *dev) - /****************************************************************************/ - /****************************************************************************/ - --static void irq_handle_i2c(struct ddb *dev, int n) -+#define IRQ_HANDLE(_nr) \ -+ do { if ((s & (1UL << _nr)) && dev->handler[_nr]) \ -+ dev->handler[_nr](dev->handler_data[_nr]); } \ -+ while (0) -+ -+static void irq_handle_msg(struct ddb *dev, u32 s) -+{ -+ dev->i2c_irq++; -+ IRQ_HANDLE(0); -+ IRQ_HANDLE(1); -+ IRQ_HANDLE(2); -+ IRQ_HANDLE(3); -+} -+ -+static void irq_handle_io(struct ddb *dev, u32 s) -+{ -+ dev->ts_irq++; -+ IRQ_HANDLE(8); -+ IRQ_HANDLE(9); -+ IRQ_HANDLE(10); -+ IRQ_HANDLE(11); -+ IRQ_HANDLE(12); -+ IRQ_HANDLE(13); -+ IRQ_HANDLE(14); -+ IRQ_HANDLE(15); -+ IRQ_HANDLE(16); -+ IRQ_HANDLE(17); -+ IRQ_HANDLE(18); -+ IRQ_HANDLE(19); -+ if (dev->info->type != DDB_MOD) -+ return; -+ IRQ_HANDLE(20); -+ IRQ_HANDLE(21); -+ IRQ_HANDLE(22); -+ IRQ_HANDLE(23); -+ IRQ_HANDLE(24); -+ IRQ_HANDLE(25); -+ IRQ_HANDLE(26); -+ IRQ_HANDLE(27); -+} -+ -+static irqreturn_t irq_handler0(int irq, void *dev_id) - { -- struct ddb_i2c *i2c = &dev->i2c[n]; -+ struct ddb *dev = (struct ddb *) dev_id; -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ -+ do { -+ if (s & 0x80000000) -+ return IRQ_NONE; -+ if (!(s & 0xfff00)) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ irq_handle_io(dev, s); -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t irq_handler1(int irq, void *dev_id) -+{ -+ struct ddb *dev = (struct ddb *) dev_id; -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ -+ do { -+ if (s & 0x80000000) -+ return IRQ_NONE; -+ if (!(s & 0x0000f)) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ irq_handle_msg(dev, s); -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); - -- i2c->done = 1; -- wake_up(&i2c->wq); -+ return IRQ_HANDLED; - } - - static irqreturn_t irq_handler(int irq, void *dev_id) - { - struct ddb *dev = (struct ddb *) dev_id; -- u32 s = ddbreadl(INTERRUPT_STATUS); -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); -+ int ret = IRQ_HANDLED; - - if (!s) - return IRQ_NONE; -- - do { -- ddbwritel(s, INTERRUPT_ACK); -- -- if (s & 0x00000001) -- irq_handle_i2c(dev, 0); -- if (s & 0x00000002) -- irq_handle_i2c(dev, 1); -- if (s & 0x00000004) -- irq_handle_i2c(dev, 2); -- if (s & 0x00000008) -- irq_handle_i2c(dev, 3); -- -- if (s & 0x00000100) -- tasklet_schedule(&dev->input[0].tasklet); -- if (s & 0x00000200) -- tasklet_schedule(&dev->input[1].tasklet); -- if (s & 0x00000400) -- tasklet_schedule(&dev->input[2].tasklet); -- if (s & 0x00000800) -- tasklet_schedule(&dev->input[3].tasklet); -- if (s & 0x00001000) -- tasklet_schedule(&dev->input[4].tasklet); -- if (s & 0x00002000) -- tasklet_schedule(&dev->input[5].tasklet); -- if (s & 0x00004000) -- tasklet_schedule(&dev->input[6].tasklet); -- if (s & 0x00008000) -- tasklet_schedule(&dev->input[7].tasklet); -- -- if (s & 0x00010000) -- tasklet_schedule(&dev->output[0].tasklet); -- if (s & 0x00020000) -- tasklet_schedule(&dev->output[1].tasklet); -- if (s & 0x00040000) -- tasklet_schedule(&dev->output[2].tasklet); -- if (s & 0x00080000) -- tasklet_schedule(&dev->output[3].tasklet); -- -- /* if (s & 0x000f0000) printk(KERN_DEBUG "%08x\n", istat); */ -- } while ((s = ddbreadl(INTERRUPT_STATUS))); -+ if (s & 0x80000000) -+ return IRQ_NONE; -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ -+ if (s & 0x0000000f) -+ irq_handle_msg(dev, s); -+ if (s & 0x0fffff00) { -+ irq_handle_io(dev, s); -+#ifdef DDB_TEST_THREADED -+ ret = IRQ_WAKE_THREAD; -+#endif -+ } -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); -+ -+ return ret; -+} -+ -+#ifdef DDB_TEST_THREADED -+static irqreturn_t irq_thread(int irq, void *dev_id) -+{ -+ /* struct ddb *dev = (struct ddb *) dev_id; */ -+ -+ /*pr_info("%s\n", __func__);*/ - - return IRQ_HANDLED; - } -+#endif -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+#ifdef DVB_NSD -+ -+static ssize_t nsd_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ return 0; -+} - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+static unsigned int nsd_poll(struct file *file, poll_table *wait) -+{ -+ return 0; -+} -+ -+static int nsd_release(struct inode *inode, struct file *file) -+{ -+ return dvb_generic_release(inode, file); -+} -+ -+static int nsd_open(struct inode *inode, struct file *file) -+{ -+ return dvb_generic_open(inode, file); -+} -+ -+static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb *dev = dvbdev->priv; -+ -+ /* unsigned long arg = (unsigned long) parg; */ -+ int ret = 0; -+ -+ switch (cmd) { -+ case NSD_START_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ u32 ctrl = ((ts->input & 7) << 8) | -+ ((ts->filter_mask & 3) << 2); -+ u32 to; -+ -+ if (ddbreadl(dev, TS_CAPTURE_CONTROL) & 1) { -+ pr_info("ts capture busy\n"); -+ return -EBUSY; -+ } -+ ddb_dvb_input_start(&dev->input[ts->input & 7]); -+ -+ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); -+ ddbwritel(dev, ts->pid, TS_CAPTURE_PID); -+ ddbwritel(dev, (ts->section_id << 16) | -+ (ts->table << 8) | ts->section, -+ TS_CAPTURE_TABLESECTION); -+ /* 1024 ms default timeout if timeout set to 0 */ -+ if (ts->timeout) -+ to = ts->timeout; -+ else -+ to = 1024; -+ /* 21 packets default if num set to 0 */ -+ if (ts->num) -+ to |= ((u32) ts->num << 16); -+ else -+ to |= (21 << 16); -+ ddbwritel(dev, to, TS_CAPTURE_TIMEOUT); -+ if (ts->mode) -+ ctrl |= 2; -+ ddbwritel(dev, ctrl | 1, TS_CAPTURE_CONTROL); -+ break; -+ } -+ case NSD_POLL_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ -+ if (ctrl & 1) -+ return -EBUSY; -+ if (ctrl & (1 << 14)) { -+ /*pr_info("ts capture timeout\n");*/ -+ return -EAGAIN; -+ } -+ ddbcpyfrom(dev, dev->tsbuf, TS_CAPTURE_MEMORY, -+ TS_CAPTURE_LEN); -+ ts->len = ddbreadl(dev, TS_CAPTURE_RECEIVED) & 0x1fff; -+ if (copy_to_user(ts->ts, dev->tsbuf, ts->len)) -+ return -EIO; -+ break; -+ } -+ case NSD_CANCEL_GET_TS: -+ { -+ u32 ctrl = 0; -+ pr_info("cancel ts capture: 0x%x\n", ctrl); -+ ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL); -+ ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ /*pr_info("control register is 0x%x\n", ctrl);*/ -+ break; -+ } -+ case NSD_STOP_GET_TS: -+ { -+ struct dvb_nsd_ts *ts = parg; -+ u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL); -+ -+ if (ctrl & 1) { -+ pr_info("cannot stop ts capture, while it was neither finished not canceled\n"); -+ return -EBUSY; -+ } -+ /*pr_info("ts capture stopped\n");*/ -+ ddb_dvb_input_stop(&dev->input[ts->input & 7]); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static long nsd_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy(file, cmd, arg, nsd_do_ioctl); -+} -+ -+static const struct file_operations nsd_fops = { -+ .owner = THIS_MODULE, -+ .read = nsd_read, -+ .open = nsd_open, -+ .release = nsd_release, -+ .poll = nsd_poll, -+ .unlocked_ioctl = nsd_ioctl, -+}; -+ -+static struct dvb_device dvbdev_nsd = { -+ .priv = 0, -+ .readers = 1, -+ .writers = 1, -+ .users = 1, -+ .fops = &nsd_fops, -+}; -+ -+static int ddb_nsd_attach(struct ddb *dev) -+{ -+ int ret; -+ -+ ret = dvb_register_device(&dev->adap[0], -+ &dev->nsd_dev, -+ &dvbdev_nsd, (void *) dev, -+ DVB_DEVICE_NSD); -+ return ret; -+} -+ -+static void ddb_nsd_detach(struct ddb *dev) -+{ -+ if (dev->nsd_dev->users > 2) { -+ wait_event(dev->nsd_dev->wait_queue, -+ dev->nsd_dev->users == 2); -+ } -+ dvb_unregister_device(dev->nsd_dev); -+} -+ -+#endif -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ - - static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) - { - u32 data, shift; - - if (wlen > 4) -- ddbwritel(1, SPI_CONTROL); -+ ddbwritel(dev, 1, SPI_CONTROL); - while (wlen > 4) { - /* FIXME: check for big-endian */ - data = swab32(*(u32 *)wbuf); - wbuf += 4; - wlen -= 4; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, data, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - } - - if (rlen) -- ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -+ ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), -+ SPI_CONTROL); - else -- ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -+ ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), -+ SPI_CONTROL); - - data = 0; - shift = ((4 - wlen) * 8); -@@ -1367,33 +2907,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) - } - if (shift) - data <<= shift; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, data, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - - if (!rlen) { -- ddbwritel(0, SPI_CONTROL); -+ ddbwritel(dev, 0, SPI_CONTROL); - return 0; - } - if (rlen > 4) -- ddbwritel(1, SPI_CONTROL); -+ ddbwritel(dev, 1, SPI_CONTROL); - - while (rlen > 4) { -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, 0xffffffff, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; -- data = ddbreadl(SPI_DATA); -+ data = ddbreadl(dev, SPI_DATA); - *(u32 *) rbuf = swab32(data); - rbuf += 4; - rlen -= 4; - } -- ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); -+ ddbwritel(dev, 0xffffffff, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - -- data = ddbreadl(SPI_DATA); -- ddbwritel(0, SPI_CONTROL); -+ data = ddbreadl(dev, SPI_DATA); -+ ddbwritel(dev, 0, SPI_CONTROL); - - if (rlen < 4) - data <<= ((4 - rlen) * 8); -@@ -1407,28 +2947,107 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) - return 0; - } - -+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len) -+{ -+ u8 cmd[4] = {0x03, (addr >> 16) & 0xff, -+ (addr >> 8) & 0xff, addr & 0xff}; -+ -+ return flashio(dev, cmd, 4, buf, len); -+} -+ -+static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val) -+{ -+ ddbwritel(dev, adr, MDIO_ADR); -+ ddbwritel(dev, reg, MDIO_REG); -+ ddbwritel(dev, val, MDIO_VAL); -+ ddbwritel(dev, 0x03, MDIO_CTRL); -+ while (ddbreadl(dev, MDIO_CTRL) & 0x02) -+ ndelay(500); -+ return 0; -+} -+ -+static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg) -+{ -+ ddbwritel(dev, adr, MDIO_ADR); -+ ddbwritel(dev, reg, MDIO_REG); -+ ddbwritel(dev, 0x07, MDIO_CTRL); -+ while (ddbreadl(dev, MDIO_CTRL) & 0x02) -+ ndelay(500); -+ return ddbreadl(dev, MDIO_VAL); -+} -+ - #define DDB_MAGIC 'd' - - struct ddb_flashio { -- __user __u8 *write_buf; -+ __u8 *write_buf; - __u32 write_len; -- __user __u8 *read_buf; -+ __u8 *read_buf; - __u32 read_len; - }; - --#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -+struct ddb_gpio { -+ __u32 mask; -+ __u32 data; -+}; -+ -+struct ddb_id { -+ __u16 vendor; -+ __u16 device; -+ __u16 subvendor; -+ __u16 subdevice; -+ __u32 hw; -+ __u32 regmap; -+}; -+ -+struct ddb_reg { -+ __u32 reg; -+ __u32 val; -+}; -+ -+struct ddb_mem { -+ __u32 off; -+ __u8 *buf; -+ __u32 len; -+}; -+ -+struct ddb_mdio { -+ __u8 adr; -+ __u8 reg; -+ __u16 val; -+}; -+ -+#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -+#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) -+#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) -+#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id) -+#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) -+#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg) -+#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) -+#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem) -+#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) -+#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) - - #define DDB_NAME "ddbridge" - - static u32 ddb_num; --static struct ddb *ddbs[32]; --static struct class *ddb_class; - static int ddb_major; -+static DEFINE_MUTEX(ddb_mutex); -+ -+static int ddb_release(struct inode *inode, struct file *file) -+{ -+ struct ddb *dev = file->private_data; -+ -+ dev->ddb_dev_users--; -+ return 0; -+} - - static int ddb_open(struct inode *inode, struct file *file) - { - struct ddb *dev = ddbs[iminor(inode)]; - -+ if (dev->ddb_dev_users) -+ return -EBUSY; -+ dev->ddb_dev_users++; - file->private_data = dev; - return 0; - } -@@ -1436,7 +3055,7 @@ static int ddb_open(struct inode *inode, struct file *file) - static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - { - struct ddb *dev = file->private_data; -- __user void *parg = (__user void *)arg; -+ void *parg = (void *)arg; - int res; - - switch (cmd) { -@@ -1447,7 +3066,6 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - - if (copy_from_user(&fio, parg, sizeof(fio))) - return -EFAULT; -- - if (fio.write_len > 1028 || fio.read_len > 1028) - return -EINVAL; - if (fio.write_len + fio.read_len > 1028) -@@ -1465,6 +3083,107 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - return -EFAULT; - break; - } -+ case IOCTL_DDB_GPIO_OUT: -+ { -+ struct ddb_gpio gpio; -+ if (copy_from_user(&gpio, parg, sizeof(gpio))) -+ return -EFAULT; -+ ddbwritel(dev, gpio.mask, GPIO_DIRECTION); -+ ddbwritel(dev, gpio.data, GPIO_OUTPUT); -+ break; -+ } -+ case IOCTL_DDB_ID: -+ { -+ struct ddb_id ddbid; -+ -+ ddbid.vendor = dev->ids.vendor; -+ ddbid.device = dev->ids.device; -+ ddbid.subvendor = dev->ids.subvendor; -+ ddbid.subdevice = dev->ids.subdevice; -+ ddbid.hw = ddbreadl(dev, 0); -+ ddbid.regmap = ddbreadl(dev, 4); -+ if (copy_to_user(parg, &ddbid, sizeof(ddbid))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_READ_REG: -+ { -+ struct ddb_reg reg; -+ -+ if (copy_from_user(®, parg, sizeof(reg))) -+ return -EFAULT; -+ if (reg.reg >= dev->regs_len) -+ return -EINVAL; -+ reg.val = ddbreadl(dev, reg.reg); -+ if (copy_to_user(parg, ®, sizeof(reg))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_REG: -+ { -+ struct ddb_reg reg; -+ -+ if (copy_from_user(®, parg, sizeof(reg))) -+ return -EFAULT; -+ if (reg.reg >= dev->regs_len) -+ return -EINVAL; -+ ddbwritel(dev, reg.val, reg.reg); -+ break; -+ } -+ case IOCTL_DDB_READ_MDIO: -+ { -+ struct ddb_mdio mdio; -+ -+ if (!dev->info->mdio_num) -+ return -EIO; -+ if (copy_from_user(&mdio, parg, sizeof(mdio))) -+ return -EFAULT; -+ mdio.val = mdio_read(dev, mdio.adr, mdio.reg); -+ if (copy_to_user(parg, &mdio, sizeof(mdio))) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_MDIO: -+ { -+ struct ddb_mdio mdio; -+ -+ if (!dev->info->mdio_num) -+ return -EIO; -+ if (copy_from_user(&mdio, parg, sizeof(mdio))) -+ return -EFAULT; -+ mdio_write(dev, mdio.adr, mdio.reg, mdio.val); -+ break; -+ } -+ case IOCTL_DDB_READ_MEM: -+ { -+ struct ddb_mem mem; -+ u8 *buf = &dev->iobuf[0]; -+ -+ if (copy_from_user(&mem, parg, sizeof(mem))) -+ return -EFAULT; -+ if ((mem.len + mem.off > dev->regs_len) || -+ mem.len > 1024) -+ return -EINVAL; -+ ddbcpyfrom(dev, buf, mem.off, mem.len); -+ if (copy_to_user(mem.buf, buf, mem.len)) -+ return -EFAULT; -+ break; -+ } -+ case IOCTL_DDB_WRITE_MEM: -+ { -+ struct ddb_mem mem; -+ u8 *buf = &dev->iobuf[0]; -+ -+ if (copy_from_user(&mem, parg, sizeof(mem))) -+ return -EFAULT; -+ if ((mem.len + mem.off > dev->regs_len) || -+ mem.len > 1024) -+ return -EINVAL; -+ if (copy_from_user(buf, mem.buf, mem.len)) -+ return -EFAULT; -+ ddbcpyto(dev, mem.off, buf, mem.len); -+ break; -+ } - default: - return -ENOTTY; - } -@@ -1474,284 +3193,508 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - static const struct file_operations ddb_fops = { - .unlocked_ioctl = ddb_ioctl, - .open = ddb_open, -+ .release = ddb_release, - }; - -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -+static char *ddb_devnode(struct device *device, mode_t *mode) -+#else - static char *ddb_devnode(struct device *device, umode_t *mode) -+#endif - { - struct ddb *dev = dev_get_drvdata(device); - - return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); - } - --static int ddb_class_create(void) --{ -- ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); -- if (ddb_major < 0) -- return ddb_major; -+#define __ATTR_MRO(_name, _show) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = _show, \ -+} - -- ddb_class = class_create(THIS_MODULE, DDB_NAME); -- if (IS_ERR(ddb_class)) { -- unregister_chrdev(ddb_major, DDB_NAME); -- return PTR_ERR(ddb_class); -- } -- ddb_class->devnode = ddb_devnode; -- return 0; -+#define __ATTR_MWO(_name, _store) { \ -+ .attr = { .name = __stringify(_name), .mode = 0222 }, \ -+ .store = _store, \ - } - --static void ddb_class_destroy(void) -+static ssize_t ports_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- class_destroy(ddb_class); -- unregister_chrdev(ddb_major, DDB_NAME); -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->info->port_num); - } - --static int ddb_device_create(struct ddb *dev) -+static ssize_t ts_irq_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- dev->nr = ddb_num++; -- dev->ddb_dev = device_create(ddb_class, NULL, -- MKDEV(ddb_major, dev->nr), -- dev, "ddbridge%d", dev->nr); -- ddbs[dev->nr] = dev; -- if (IS_ERR(dev->ddb_dev)) -- return -1; -- return 0; -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->ts_irq); - } - --static void ddb_device_destroy(struct ddb *dev) -+static ssize_t i2c_irq_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- ddb_num--; -- if (IS_ERR(dev->ddb_dev)) -- return; -- device_destroy(ddb_class, MKDEV(ddb_major, 0)); -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->i2c_irq); - } - -+static char *class_name[] = { -+ "NONE", "CI", "TUNER", "LOOP" -+}; - --/****************************************************************************/ --/****************************************************************************/ --/****************************************************************************/ -+static char *type_name[] = { -+ "NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", -+ "DVBCT_ST", "INTERNAL", "CXD2099", "TYPE07", -+ "TYPE08", "TYPE09", "TYPE0A", "TYPE0B", -+ "TYPE0C", "TYPE0D", "TYPE0E", "TYPE0F", -+ "DVBS", "DVBCT2_SONY", "ISDBT_SONY", "DVBC2T2_SONY", -+ "ATSC_ST", "DVBC2T2_ST" -+}; - --static void ddb_unmap(struct ddb *dev) -+static ssize_t fan_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- if (dev->regs) -- iounmap(dev->regs); -- vfree(dev); -+ struct ddb *dev = dev_get_drvdata(device); -+ u32 val; -+ -+ val = ddbreadl(dev, GPIO_OUTPUT) & 1; -+ return sprintf(buf, "%d\n", val); - } - -+static ssize_t fan_store(struct device *device, struct device_attribute *d, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ unsigned val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, val & 1, GPIO_OUTPUT); -+ return count; -+} - --static void ddb_remove(struct pci_dev *pdev) -+static ssize_t temp_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev = pci_get_drvdata(pdev); -+ struct ddb *dev = dev_get_drvdata(device); -+ struct i2c_adapter *adap; -+ int temp, temp2, temp3, i; -+ u8 tmp[2]; - -- ddb_ports_detach(dev); -- ddb_i2c_release(dev); -+ if (dev->info->type == DDB_MOD) { -+ ddbwritel(dev, 1, TEMPMON_CONTROL); -+ for (i = 0; i < 10; i++) { -+ if (0 == (1 & ddbreadl(dev, TEMPMON_CONTROL))) -+ break; -+ usleep_range(1000, 2000); -+ } -+ temp = ddbreadl(dev, TEMPMON_SENSOR1); -+ temp2 = ddbreadl(dev, TEMPMON_SENSOR2); -+ temp = (temp * 1000) >> 8; -+ temp2 = (temp2 * 1000) >> 8; -+ if (ddbreadl(dev, TEMPMON_CONTROL) & 0x8000) { -+ temp3 = ddbreadl(dev, TEMPMON_CORE); -+ temp3 = (temp3 * 1000) >> 8; -+ return sprintf(buf, "%d %d %d\n", temp, temp2, temp3); -+ } -+ return sprintf(buf, "%d %d\n", temp, temp2); -+ } -+ if (!dev->info->temp_num) -+ return sprintf(buf, "no sensor\n"); -+ adap = &dev->i2c[dev->info->temp_bus].adap; -+ if (i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0) -+ return sprintf(buf, "read_error\n"); -+ temp = (tmp[0] << 3) | (tmp[1] >> 5); -+ temp *= 125; -+ if (dev->info->temp_num == 2) { -+ if (i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0) -+ return sprintf(buf, "read_error\n"); -+ temp2 = (tmp[0] << 3) | (tmp[1] >> 5); -+ temp2 *= 125; -+ return sprintf(buf, "%d %d\n", temp, temp2); -+ } -+ return sprintf(buf, "%d\n", temp); -+} - -- ddbwritel(0, INTERRUPT_ENABLE); -- free_irq(dev->pdev->irq, dev); --#ifdef CONFIG_PCI_MSI -- if (dev->msi) -- pci_disable_msi(dev->pdev); --#endif -- ddb_ports_release(dev); -- ddb_buffers_free(dev); -- ddb_device_destroy(dev); -+#if 0 -+static ssize_t qam_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ struct i2c_adapter *adap; -+ u8 tmp[4]; -+ s16 i, q; - -- ddb_unmap(dev); -- pci_set_drvdata(pdev, NULL); -- pci_disable_device(pdev); -+ adap = &dev->i2c[1].adap; -+ if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0) -+ return sprintf(buf, "read_error\n"); -+ i = (s16) (((u16) tmp[1]) << 14) | (((u16) tmp[0]) << 6); -+ q = (s16) (((u16) tmp[3]) << 14) | (((u16) tmp[2]) << 6); -+ -+ return sprintf(buf, "%d %d\n", i, q); - } -+#endif -+ -+static ssize_t mod_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; - -+ return sprintf(buf, "%s:%s\n", -+ class_name[dev->port[num].class], -+ type_name[dev->port[num].type]); -+} - --static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) -+static ssize_t led_show(struct device *device, -+ struct device_attribute *attr, char *buf) - { -- struct ddb *dev; -- int stat = 0; -- int irq_flag = IRQF_SHARED; -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; - -- if (pci_enable_device(pdev) < 0) -- return -ENODEV; -+ return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); -+} - -- dev = vmalloc(sizeof(struct ddb)); -- if (dev == NULL) -- return -ENOMEM; -- memset(dev, 0, sizeof(struct ddb)); - -- dev->pdev = pdev; -- pci_set_drvdata(pdev, dev); -- dev->info = (struct ddb_info *) id->driver_data; -- printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name); -+static void ddb_set_led(struct ddb *dev, int num, int val) -+{ -+ if (!dev->info->led_num) -+ return; -+ switch (dev->port[num].class) { -+ case DDB_PORT_TUNER: -+ switch (dev->port[num].type) { -+ case DDB_TUNER_DVBS_ST: -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x69, 0xf14c, val ? 2 : 0); -+ break; -+ case DDB_TUNER_DVBCT_ST: -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00e, 0); -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00f, val ? 1 : 0); -+ break; -+ case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2_ST: -+ { -+ u8 v; - -- dev->regs = ioremap(pci_resource_start(dev->pdev, 0), -- pci_resource_len(dev->pdev, 0)); -- if (!dev->regs) { -- stat = -ENOMEM; -- goto fail; -+ i2c_read_reg(&dev->i2c[num].adap, 0x10, 0x08, &v); -+ v = (v & ~0x10) | (val ? 0x10 : 0); -+ i2c_write_reg(&dev->i2c[num].adap, 0x10, 0x08, v); -+ break; -+ } -+ default: -+ break; -+ } -+ break; - } -- printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); -+} -+ -+static ssize_t led_store(struct device *device, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ unsigned val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val) -+ dev->leds |= (1 << num); -+ else -+ dev->leds &= ~(1 << num); -+ ddb_set_led(dev, num, val); -+ return count; -+} -+ -+static ssize_t snr_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[32]; -+ int num = attr->attr.name[3] - 0x30; - --#ifdef CONFIG_PCI_MSI -- if (pci_msi_enabled()) -- stat = pci_enable_msi(dev->pdev); -- if (stat) { -- printk(KERN_INFO ": MSI not available.\n"); -+ if (dev->port[num].type >= DDB_TUNER_XO2) { -+ if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0) -+ return sprintf(buf, "NO SNR\n"); -+ snr[16] = 0; - } else { -- irq_flag = 0; -- dev->msi = 1; -+ /* serial number at 0x100-0x11f */ -+ if (i2c_read_regs16(&dev->i2c[num].adap, -+ 0x50, 0x100, snr, 32) < 0) -+ if (i2c_read_regs16(&dev->i2c[num].adap, -+ 0x57, 0x100, snr, 32) < 0) -+ return sprintf(buf, "NO SNR\n"); -+ snr[31] = 0; /* in case it is not terminated on EEPROM */ - } --#endif -- stat = request_irq(dev->pdev->irq, irq_handler, -- irq_flag, "DDBridge", (void *) dev); -- if (stat < 0) -- goto fail1; -- ddbwritel(0, DMA_BASE_WRITE); -- ddbwritel(0, DMA_BASE_READ); -- ddbwritel(0xffffffff, INTERRUPT_ACK); -- ddbwritel(0xfff0f, INTERRUPT_ENABLE); -- ddbwritel(0, MSI1_ENABLE); -- -- if (ddb_i2c_init(dev) < 0) -- goto fail1; -- ddb_ports_init(dev); -- if (ddb_buffers_alloc(dev) < 0) { -- printk(KERN_INFO ": Could not allocate buffer memory\n"); -- goto fail2; -- } -- if (ddb_ports_attach(dev) < 0) -- goto fail3; -- ddb_device_create(dev); -+ return sprintf(buf, "%s\n", snr); -+} -+ -+ -+static ssize_t snr_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ u8 snr[34] = { 0x01, 0x00 }; -+ -+ if (count > 31) -+ return -EINVAL; -+ if (dev->port[num].type >= DDB_TUNER_XO2) -+ return -EINVAL; -+ memcpy(snr + 2, buf, count); -+ i2c_write(&dev->i2c[num].adap, 0x57, snr, 34); -+ i2c_write(&dev->i2c[num].adap, 0x50, snr, 34); -+ return count; -+} -+ -+static ssize_t bsnr_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[16]; -+ -+ ddbridge_flashread(dev, snr, 0x10, 15); -+ snr[15] = 0; /* in case it is not terminated on EEPROM */ -+ return sprintf(buf, "%s\n", snr); -+} -+ -+static ssize_t redirect_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ - return 0; -+} - --fail3: -- ddb_ports_detach(dev); -- printk(KERN_ERR "fail3\n"); -- ddb_ports_release(dev); --fail2: -- printk(KERN_ERR "fail2\n"); -- ddb_buffers_free(dev); --fail1: -- printk(KERN_ERR "fail1\n"); -- if (dev->msi) -- pci_disable_msi(dev->pdev); -- free_irq(dev->pdev->irq, dev); --fail: -- printk(KERN_ERR "fail\n"); -- ddb_unmap(dev); -- pci_set_drvdata(pdev, NULL); -- pci_disable_device(pdev); -- return -1; -+static ssize_t redirect_store(struct device *device, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned int i, p; -+ int res; -+ -+ if (sscanf(buf, "%x %x\n", &i, &p) != 2) -+ return -EINVAL; -+ res = ddb_redirect(i, p); -+ if (res < 0) -+ return res; -+ pr_info("redirect: %02x, %02x\n", i, p); -+ return count; - } - --/******************************************************************************/ --/******************************************************************************/ --/******************************************************************************/ -+static ssize_t gap_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; - --static struct ddb_info ddb_none = { -- .type = DDB_NONE, -- .name = "Digital Devices PCIe bridge", --}; -+ return sprintf(buf, "%d\n", dev->port[num].gap); - --static struct ddb_info ddb_octopus = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus DVB adapter", -- .port_num = 4, --}; -+} -+static ssize_t gap_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ unsigned int val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val > 20) -+ return -EINVAL; -+ dev->port[num].gap = val; -+ return count; -+} - --static struct ddb_info ddb_octopus_le = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus LE DVB adapter", -- .port_num = 2, --}; -+static ssize_t version_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); - --static struct ddb_info ddb_octopus_mini = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus Mini", -- .port_num = 4, --}; -+ return sprintf(buf, "%08x %08x\n", -+ ddbreadl(dev, 0), ddbreadl(dev, 4)); -+} - --static struct ddb_info ddb_v6 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Cine S2 V6 DVB adapter", -- .port_num = 3, --}; --static struct ddb_info ddb_v6_5 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Cine S2 V6.5 DVB adapter", -- .port_num = 4, -+static ssize_t hwid_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "0x%08X\n", dev->ids.hwid); -+} -+ -+static ssize_t regmap_show(struct device *device, -+ struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "0x%08X\n", dev->ids.regmapid); -+} -+ -+static struct device_attribute ddb_attrs[] = { -+ __ATTR_RO(version), -+ __ATTR_RO(ports), -+ __ATTR_RO(ts_irq), -+ __ATTR_RO(i2c_irq), -+ __ATTR(gap0, 0664, gap_show, gap_store), -+ __ATTR(gap1, 0664, gap_show, gap_store), -+ __ATTR(gap2, 0664, gap_show, gap_store), -+ __ATTR(gap3, 0664, gap_show, gap_store), -+ __ATTR_RO(hwid), -+ __ATTR_RO(regmap), -+#if 0 -+ __ATTR_RO(qam), -+#endif -+ __ATTR(redirect, 0664, redirect_show, redirect_store), -+ __ATTR_MRO(snr, bsnr_show), -+ __ATTR_NULL, - }; - --static struct ddb_info ddb_dvbct = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices DVBCT V6.1 DVB adapter", -- .port_num = 3, -+static struct device_attribute ddb_attrs_temp[] = { -+ __ATTR_RO(temp), - }; - --static struct ddb_info ddb_satixS2v3 = { -- .type = DDB_OCTOPUS, -- .name = "Mystique SaTiX-S2 V3 DVB adapter", -- .port_num = 3, -+static struct device_attribute ddb_attrs_mod[] = { -+ __ATTR_MRO(mod0, mod_show), -+ __ATTR_MRO(mod1, mod_show), -+ __ATTR_MRO(mod2, mod_show), -+ __ATTR_MRO(mod3, mod_show), -+ __ATTR_MRO(mod4, mod_show), -+ __ATTR_MRO(mod5, mod_show), -+ __ATTR_MRO(mod6, mod_show), -+ __ATTR_MRO(mod7, mod_show), -+ __ATTR_MRO(mod8, mod_show), -+ __ATTR_MRO(mod9, mod_show), - }; - --static struct ddb_info ddb_octopusv3 = { -- .type = DDB_OCTOPUS, -- .name = "Digital Devices Octopus V3 DVB adapter", -- .port_num = 4, -+static struct device_attribute ddb_attrs_fan[] = { -+ __ATTR(fan, 0664, fan_show, fan_store), - }; - --#define DDVID 0xdd01 /* Digital Devices Vendor ID */ -- --#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ -- .vendor = _vend, .device = _dev, \ -- .subvendor = _subvend, .subdevice = _subdev, \ -- .driver_data = (unsigned long)&_driverdata } -- --static const struct pci_device_id ddb_id_tbl[] = { -- DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), -- DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), -- DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), -- /* in case sub-ids got deleted in flash */ -- DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -- {0} -+static struct device_attribute ddb_attrs_snr[] = { -+ __ATTR(snr0, 0664, snr_show, snr_store), -+ __ATTR(snr1, 0664, snr_show, snr_store), -+ __ATTR(snr2, 0664, snr_show, snr_store), -+ __ATTR(snr3, 0664, snr_show, snr_store), - }; --MODULE_DEVICE_TABLE(pci, ddb_id_tbl); - -+static struct device_attribute ddb_attrs_led[] = { -+ __ATTR(led0, 0664, led_show, led_store), -+ __ATTR(led1, 0664, led_show, led_store), -+ __ATTR(led2, 0664, led_show, led_store), -+ __ATTR(led3, 0664, led_show, led_store), -+}; - --static struct pci_driver ddb_pci_driver = { -- .name = "DDBridge", -- .id_table = ddb_id_tbl, -- .probe = ddb_probe, -- .remove = ddb_remove, -+static struct class ddb_class = { -+ .name = "ddbridge", -+ .owner = THIS_MODULE, -+#if 0 -+ .dev_attrs = ddb_attrs, -+#endif -+ .devnode = ddb_devnode, - }; - --static __init int module_init_ddbridge(void) -+static int ddb_class_create(void) - { -- int ret; -+ ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); -+ if (ddb_major < 0) -+ return ddb_major; -+ if (class_register(&ddb_class) < 0) -+ return -1; -+ return 0; -+} -+ -+static void ddb_class_destroy(void) -+{ -+ class_unregister(&ddb_class); -+ unregister_chrdev(ddb_major, DDB_NAME); -+} - -- printk(KERN_INFO "Digital Devices PCIE bridge driver, " -- "Copyright (C) 2010-11 Digital Devices GmbH\n"); -+static void ddb_device_attrs_del(struct ddb *dev) -+{ -+ int i; - -- ret = ddb_class_create(); -- if (ret < 0) -- return ret; -- ret = pci_register_driver(&ddb_pci_driver); -- if (ret < 0) -- ddb_class_destroy(); -- return ret; -+ for (i = 0; i < dev->info->temp_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]); -+ for (i = 0; i < dev->info->port_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]); -+ for (i = 0; i < dev->info->fan_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_fan[i]); -+ for (i = 0; i < dev->info->i2c_num; i++) { -+ if (dev->info->led_num) -+ device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]); -+ device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]); -+ } -+ for (i = 0; ddb_attrs[i].attr.name; i++) -+ device_remove_file(dev->ddb_dev, &ddb_attrs[i]); - } - --static __exit void module_exit_ddbridge(void) -+static int ddb_device_attrs_add(struct ddb *dev) - { -- pci_unregister_driver(&ddb_pci_driver); -- ddb_class_destroy(); -+ int i; -+ -+ for (i = 0; ddb_attrs[i].attr.name; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs[i])) -+ goto fail; -+ for (i = 0; i < dev->info->temp_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i])) -+ goto fail; -+ for (i = 0; i < dev->info->port_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i])) -+ goto fail; -+ for (i = 0; i < dev->info->fan_num; i++) -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_fan[i])) -+ goto fail; -+ for (i = 0; i < dev->info->i2c_num; i++) { -+ if (device_create_file(dev->ddb_dev, &ddb_attrs_snr[i])) -+ goto fail; -+ if (dev->info->led_num) -+ if (device_create_file(dev->ddb_dev, -+ &ddb_attrs_led[i])) -+ goto fail; -+ } -+ return 0; -+fail: -+ return -1; - } - --module_init(module_init_ddbridge); --module_exit(module_exit_ddbridge); -+static int ddb_device_create(struct ddb *dev) -+{ -+ int res = 0; -+ -+ if (ddb_num == DDB_MAX_ADAPTER) -+ return -ENOMEM; -+ mutex_lock(&ddb_mutex); -+ dev->nr = ddb_num; -+ ddbs[dev->nr] = dev; -+ dev->ddb_dev = device_create(&ddb_class, dev->dev, -+ MKDEV(ddb_major, dev->nr), -+ dev, "ddbridge%d", dev->nr); -+ if (IS_ERR(dev->ddb_dev)) { -+ res = PTR_ERR(dev->ddb_dev); -+ pr_info("Could not create ddbridge%d\n", dev->nr); -+ goto fail; -+ } -+ res = ddb_device_attrs_add(dev); -+ if (res) { -+ ddb_device_attrs_del(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); -+ ddbs[dev->nr] = 0; -+ dev->ddb_dev = ERR_PTR(-ENODEV); -+ } else -+ ddb_num++; -+fail: -+ mutex_unlock(&ddb_mutex); -+ return res; -+} - --MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); --MODULE_AUTHOR("Ralph Metzler"); --MODULE_LICENSE("GPL"); --MODULE_VERSION("0.5"); -+static void ddb_device_destroy(struct ddb *dev) -+{ -+ if (IS_ERR(dev->ddb_dev)) -+ return; -+ ddb_device_attrs_del(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c -new file mode 100644 -index 0000000..bd0d9b1 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c -@@ -0,0 +1,257 @@ -+/* -+ * ddbridge-i2c.c: Digital Devices bridge i2c driver -+ * -+ * Copyright (C) 2010-2014 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_regs16(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *val, u8 len) -+{ -+ u8 reg16[2] = { reg >> 8, reg }; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = reg16, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, -+ u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, -+ u8 reg, u8 val) -+{ -+ u8 msg[2] = {reg, val}; -+ -+ return i2c_write(adap, adr, msg, 2); -+} -+ -+static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) -+{ -+ struct ddb *dev = i2c->dev; -+ int stat; -+ u32 val; -+ -+ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND); -+ stat = wait_for_completion_timeout(&i2c->completion, HZ); -+ if (stat <= 0) { -+ pr_err("DDBridge I2C timeout, card %d, port %d\n", -+ dev->nr, i2c->nr); -+#ifdef CONFIG_PCI_MSI -+ { /* MSI debugging*/ -+ u32 istat = ddbreadl(dev, INTERRUPT_STATUS); -+ dev_err(dev->dev, "DDBridge IRS %08x\n", istat); -+ ddbwritel(dev, istat, INTERRUPT_ACK); -+ } -+#endif -+ return -EIO; -+ } -+ val = ddbreadl(dev, i2c->regs + I2C_COMMAND); -+ if (val & 0x70000) -+ return -EIO; -+ return 0; -+} -+ -+static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg msg[], int num) -+{ -+ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); -+ struct ddb *dev = i2c->dev; -+ u8 addr = 0; -+ -+ if (num) -+ addr = msg[0].addr; -+ if (num == 2 && msg[1].flags & I2C_M_RD && -+ !(msg[0].flags & I2C_M_RD)) { -+ memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, -+ msg[0].buf, msg[0].len); -+ ddbwritel(dev, msg[0].len|(msg[1].len << 16), -+ i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 1)) { -+ memcpy_fromio(msg[1].buf, -+ dev->regs + I2C_TASKMEM_BASE + -+ i2c->rbuf, -+ msg[1].len); -+ return num; -+ } -+ } -+ if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -+ ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, -+ msg[0].buf, msg[0].len); -+ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 2)) -+ return num; -+ } -+ if (num == 1 && (msg[0].flags & I2C_M_RD)) { -+ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); -+ if (!ddb_i2c_cmd(i2c, addr, 3)) { -+ ddbcpyfrom(dev, msg[0].buf, -+ I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); -+ return num; -+ } -+ } -+ return -EIO; -+} -+ -+#if 0 -+static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg msg[], int num) -+{ -+ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); -+ struct ddb *dev = i2c->dev; -+ int ret; -+ -+ if (dev->info->type != DDB_OCTONET || i2c->nr == 0 || i2c->nr == 3) -+ return ddb_i2c_master_xfer_locked(adapter, msg, num); -+ -+ mutex_lock(&dev->octonet_i2c_lock); -+ ret = ddb_i2c_master_xfer_locked(adapter, msg, num); -+ mutex_unlock(&dev->octonet_i2c_lock); -+ return ret; -+} -+#endif -+ -+static u32 ddb_i2c_functionality(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_SMBUS_EMUL; -+} -+ -+struct i2c_algorithm ddb_i2c_algo = { -+ .master_xfer = ddb_i2c_master_xfer, -+ .functionality = ddb_i2c_functionality, -+}; -+ -+static void ddb_i2c_release(struct ddb *dev) -+{ -+ int i; -+ struct ddb_i2c *i2c; -+ struct i2c_adapter *adap; -+ -+ for (i = 0; i < dev->info->i2c_num; i++) { -+ i2c = &dev->i2c[i]; -+ adap = &i2c->adap; -+ i2c_del_adapter(adap); -+ } -+} -+ -+static void i2c_handler(unsigned long priv) -+{ -+ struct ddb_i2c *i2c = (struct ddb_i2c *) priv; -+ -+ complete(&i2c->completion); -+} -+ -+static int ddb_i2c_init(struct ddb *dev) -+{ -+ int i, j, stat = 0; -+ struct ddb_i2c *i2c; -+ struct i2c_adapter *adap; -+ -+ for (i = 0; i < dev->info->i2c_num; i++) { -+ i2c = &dev->i2c[i]; -+ dev->handler[i] = i2c_handler; -+ dev->handler_data[i] = (unsigned long) i2c; -+ i2c->dev = dev; -+ i2c->nr = i; -+ i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); -+ i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); -+ i2c->regs = 0x80 + i * 0x20; -+ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); -+ ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf, -+ i2c->regs + I2C_TASKADDRESS); -+ init_completion(&i2c->completion); -+ -+ adap = &i2c->adap; -+ i2c_set_adapdata(adap, i2c); -+#ifdef I2C_ADAP_CLASS_TV_DIGITAL -+ adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; -+#else -+#ifdef I2C_CLASS_TV_ANALOG -+ adap->class = I2C_CLASS_TV_ANALOG; -+#endif -+#endif -+ strcpy(adap->name, "ddbridge"); -+ adap->algo = &ddb_i2c_algo; -+ adap->algo_data = (void *)i2c; -+ adap->dev.parent = dev->dev; -+ stat = i2c_add_adapter(adap); -+ if (stat) -+ break; -+ } -+ if (stat) -+ for (j = 0; j < i; j++) { -+ i2c = &dev->i2c[j]; -+ adap = &i2c->adap; -+ i2c_del_adapter(adap); -+ } -+ return stat; -+} -+ -diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.h b/drivers/media/pci/ddbridge/ddbridge-i2c.h -new file mode 100644 -index 0000000..4a9bc26 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.h -@@ -0,0 +1,105 @@ -+/* -+ * ddbridge-i2c.h: Digital Devices bridge i2c driver -+ * -+ * Copyright (C) 2010-2014 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef _DDBRIDGE_I2C_H_ -+#define _DDBRIDGE_I2C_H_ -+ -+#include -+#include -+ -+static inline int i2c_write(struct i2c_adapter *adap, u8 adr, -+ u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ -+static inline int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static inline int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_regs16(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *val, u8 len) -+{ -+ u8 reg16[2] = { reg >> 8, reg }; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = reg16, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, -+ u8 reg, u8 *val) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, -+ u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1 } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static inline int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, -+ u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ -+static inline int i2c_write_reg(struct i2c_adapter *adap, u8 adr, -+ u8 reg, u8 val) -+{ -+ u8 msg[2] = {reg, val}; -+ -+ return i2c_write(adap, adr, msg, 2); -+} -+ -+#endif -diff --git a/drivers/media/pci/ddbridge/ddbridge-mod.c b/drivers/media/pci/ddbridge/ddbridge-mod.c -new file mode 100644 -index 0000000..5a9c866 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-mod.c -@@ -0,0 +1,1148 @@ -+/* -+ * ddbridge.c: Digital Devices PCIe bridge driver -+ * -+ * Copyright (C) 2010-2014 Digital Devices GmbH -+ * Ralph Metzler -+ * Marcus Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+#include -+ -+inline s64 ConvertPCR(s64 a) -+{ -+ s32 ext; -+ s64 b; -+ -+ b = div_s64_rem(a, 300 << 22, &ext); -+ -+ return (b << 31) | ext; -+ -+} -+ -+inline s64 NegConvertPCR(s64 a) -+{ -+ s32 ext; -+ s64 b; -+ -+ b = -div_s64_rem(a, 300 << 22, &ext); -+ -+ if (ext != 0) { -+ ext = (300 << 22) - ext; -+ b -= 1; -+ } -+ return (b << 31) | ext; -+} -+ -+inline s64 RoundPCR(s64 a) -+{ -+ s64 b = a + (HW_LSB_MASK>>1); -+ return b & ~(HW_LSB_MASK - 1); -+} -+ -+inline s64 RoundPCRUp(s64 a) -+{ -+ s64 b = a + (HW_LSB_MASK - 1); -+ return b & ~(HW_LSB_MASK - 1); -+} -+ -+inline s64 RoundPCRDown(s64 a) -+{ -+ return a & ~(HW_LSB_MASK - 1); -+} -+ -+static int mod_busy(struct ddb *dev, int chan) -+{ -+ u32 creg; -+ -+ while (1) { -+ creg = ddbreadl(dev, CHANNEL_CONTROL(chan)); -+ if (creg == 0xffffffff) -+ return -EFAULT; -+ if ((creg & CHANNEL_CONTROL_BUSY) == 0) -+ break; -+ } -+ return 0; -+} -+ -+void ddbridge_mod_output_stop(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ mod->State = CM_IDLE; -+ mod->Control = 0; -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+#if 0 -+ udelay(10); -+ ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr)); -+ udelay(10); -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+#endif -+ mod_busy(dev, output->nr); -+ pr_info("mod_output_stop %d.%d\n", dev->nr, output->nr); -+} -+ -+static void mod_set_incs(struct ddb_output *output) -+{ -+ s64 pcr; -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ pcr = ConvertPCR(mod->PCRIncrement); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTH(output->nr)); -+ mod_busy(dev, output->nr); -+ -+ pcr = NegConvertPCR(mod->PCRDecrement); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_INL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_INH(output->nr)); -+ mod_busy(dev, output->nr); -+ -+} -+ -+static void mod_set_rateinc(struct ddb *dev, u32 chan) -+{ -+ ddbwritel(dev, dev->mod[chan].rate_inc, CHANNEL_RATE_INCR(chan)); -+ mod_busy(dev, chan); -+} -+ -+static u32 qamtab[6] = { 0x000, 0x600, 0x601, 0x602, 0x903, 0x604 }; -+ -+void ddbridge_mod_output_start(struct ddb_output *output) -+{ -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ /*PCRIncrement = RoundPCR(PCRIncrement);*/ -+ /*PCRDecrement = RoundPCR(PCRDecrement);*/ -+ -+ mod->LastInPacketCount = 0; -+ mod->LastOutPacketCount = 0; -+ mod->InOverflowPacketCount = 0; -+ mod->OutOverflowPacketCount = 0; -+ mod->LastInPackets = 0; -+ mod->LastOutPackets = 0; -+ mod->LastPCRAdjust = 0; -+ mod->PCRRunningCorr = 0; -+ /* we interrupt every 0x80000=524288 packets */ -+ mod->MinInputPackets = 524288 / 2; -+ mod->PCRIncrement = 0; -+ mod->PCRDecrement = 0; -+ -+ mod->State = CM_STARTUP; -+ mod->StateCounter = CM_STARTUP_DELAY; -+ -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+ udelay(10); -+ ddbwritel(dev, CHANNEL_CONTROL_RESET, CHANNEL_CONTROL(output->nr)); -+ udelay(10); -+ ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr)); -+ -+ /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ -+ /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ -+ ddbwritel(dev, qamtab[mod->modulation], CHANNEL_SETTINGS(output->nr)); -+ -+ mod_set_rateinc(dev, output->nr); -+ mod_set_incs(output); -+ -+ mod->Control = (CHANNEL_CONTROL_ENABLE_IQ | -+ CHANNEL_CONTROL_ENABLE_DVB | -+ CHANNEL_CONTROL_ENABLE_SOURCE); -+ -+ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); -+ pr_info("mod_output_start %d.%d\n", dev->nr, output->nr); -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void mod_write_dac_register(struct ddb *dev, u8 Index, u8 Value) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, Value, DAC_WRITE_DATA); -+ ddbwritel(dev, DAC_CONTROL_STARTIO | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+} -+ -+static void mod_write_dac_register2(struct ddb *dev, u8 Index, u16 Value) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, Value, DAC_WRITE_DATA); -+ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x20 | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+} -+ -+static int mod_read_dac_register(struct ddb *dev, u8 Index, u8 *pValue) -+{ -+ u32 RegValue = 0; -+ -+ ddbwritel(dev, DAC_CONTROL_STARTIO | 0x80 | Index, DAC_CONTROL); -+ do { -+ RegValue = ddbreadl(dev, DAC_CONTROL); -+ } while ((RegValue & DAC_CONTROL_STARTIO) != 0); -+ -+ RegValue = ddbreadl(dev, DAC_READ_DATA); -+ *pValue = (u8) RegValue; -+ return 0; -+} -+ -+static void mod_set_up_converter_vco1(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ /* Extra delay before writing N divider */ -+ if ((Value & 0x03) == 0x02) -+ msleep(50); -+ do { -+ RegValue = ddbreadl(dev, VCO1_CONTROL); -+ } while ((RegValue & VCO1_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO1_CONTROL_CE) == 0) { -+ RegValue |= VCO1_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO1_CONTROL); -+ msleep(20); -+ } -+ -+ ddbwritel(dev, Value, VCO1_DATA); -+ ddbwritel(dev, RegValue | VCO1_CONTROL_WRITE, VCO1_CONTROL); -+} -+ -+static void mod_set_up_converter_vco2(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ /* Extra delay before writing N divider */ -+ if ((Value & 0x03) == 0x02) -+ msleep(50); -+ do { -+ RegValue = ddbreadl(dev, VCO2_CONTROL); -+ } while ((RegValue & VCO2_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO2_CONTROL_CE) == 0) { -+ RegValue |= VCO2_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO2_CONTROL); -+ msleep(20); -+ } -+ -+ ddbwritel(dev, Value, VCO2_DATA); -+ ddbwritel(dev, RegValue | VCO2_CONTROL_WRITE, VCO2_CONTROL); -+} -+ -+static void mod_set_down_converter_vco(struct ddb *dev, u32 Value) -+{ -+ u32 RegValue = 0; -+ -+ do { -+ RegValue = ddbreadl(dev, VCO3_CONTROL); -+ } while ((RegValue & VCO3_CONTROL_WRITE) != 0); -+ -+ if ((RegValue & VCO3_CONTROL_CE) == 0) { -+ RegValue |= VCO3_CONTROL_CE; -+ ddbwritel(dev, RegValue, VCO3_CONTROL); -+ msleep(20); -+ } -+ ddbwritel(dev, Value, VCO3_DATA); -+ ddbwritel(dev, RegValue | VCO3_CONTROL_WRITE, VCO3_CONTROL); -+} -+ -+static int mod_set_attenuator(struct ddb *dev, u32 Value) -+{ -+ if (Value > 31) -+ return -EINVAL; -+ ddbwritel(dev, Value, RF_ATTENUATOR); -+ return 0; -+} -+ -+static void mod_si598_readreg(struct ddb *dev, u8 index, u8 *val) -+{ -+ ddbwritel(dev, index, CLOCKGEN_INDEX); -+ ddbwritel(dev, 1, CLOCKGEN_CONTROL); -+ usleep_range(5000, 6000); -+ *val = ddbreadl(dev, CLOCKGEN_READDATA); -+} -+ -+static void mod_si598_writereg(struct ddb *dev, u8 index, u8 val) -+{ -+ ddbwritel(dev, index, CLOCKGEN_INDEX); -+ ddbwritel(dev, val, CLOCKGEN_WRITEDATA); -+ ddbwritel(dev, 3, CLOCKGEN_CONTROL); -+ usleep_range(5000, 6000); -+} -+ -+static int mod_set_si598(struct ddb *dev, u32 freq) -+{ -+ u8 Data[6]; -+ u64 fDCO = 0; -+ u64 RFreq = 0; -+ u32 fOut = 10000000; -+ u64 m_fXtal = 0; -+ u32 N = 0; -+ u64 HSDiv = 0; -+ -+ u32 fxtal; -+ u64 MinDiv, MaxDiv, Div; -+ u64 RF; -+ -+ if (freq < 10000000 || freq > 525000000) -+ return -EINVAL; -+ mod_si598_writereg(dev, 137, 0x10); -+ -+ if (m_fXtal == 0) { -+ mod_si598_writereg(dev, 135, 0x01); -+ mod_si598_readreg(dev, 7, &Data[0]); -+ mod_si598_readreg(dev, 8, &Data[1]); -+ mod_si598_readreg(dev, 9, &Data[2]); -+ mod_si598_readreg(dev, 10, &Data[3]); -+ mod_si598_readreg(dev, 11, &Data[4]); -+ mod_si598_readreg(dev, 12, &Data[5]); -+ -+ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", -+ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); -+ RFreq = (((u64)Data[1] & 0x3F) << 32) | ((u64)Data[2] << 24) | -+ ((u64)Data[3] << 16) | ((u64)Data[4] << 8) | -+ ((u64)Data[5]); -+ if (RFreq == 0) -+ return -EINVAL; -+ HSDiv = ((Data[0] & 0xE0) >> 5) + 4; -+ if (HSDiv == 8 || HSDiv == 10) -+ return -EINVAL; -+ N = (((u32)(Data[0] & 0x1F) << 2) | -+ ((u32)(Data[1] & 0xE0) >> 6)) + 1; -+ fDCO = fOut * (u64)(HSDiv * N); -+ m_fXtal = fDCO << 28; -+ pr_info("fxtal %016llx rfreq %016llx\n", m_fXtal, RFreq); -+ -+ m_fXtal += RFreq >> 1; -+ m_fXtal = div64_u64(m_fXtal, RFreq); -+ -+ pr_info("fOut = %d fXtal = %d fDCO = %d HDIV = %2d, N = %3d\n", -+ (u32) fOut, (u32) m_fXtal, (u32) fDCO, (u32) HSDiv, N); -+ } -+ -+ fOut = freq; -+ MinDiv = 4850000000ULL; do_div(MinDiv, freq); MinDiv += 1; -+ MaxDiv = 5670000000ULL; do_div(MaxDiv, freq); -+ Div = 5260000000ULL; do_div(Div, freq); -+ -+ if (Div < MinDiv) -+ Div = Div + 1; -+ pr_info(" fOut = %u MinDiv = %llu MaxDiv = %llu StartDiv = %llu\n", -+ fOut, MinDiv, MaxDiv, Div); -+ -+ if (Div <= 11) { -+ N = 1; -+ HSDiv = Div; -+ } else { -+ int retry = 100; -+ while (retry > 0) { -+ N = 0; -+ HSDiv = Div; -+ while ((HSDiv > 11) /*|| ((HSDiv * N) != Div)*/) { -+ N = N + 2; -+ HSDiv = Div; -+ do_div(HSDiv, N); -+ if (N > 128) -+ break; -+ } -+ pr_info(" %3d: %llu %llu %llu %u\n", -+ retry, Div, HSDiv * N, HSDiv, N); -+ if (HSDiv * N < MinDiv) -+ Div = Div + 2; -+ else if (HSDiv * N > MaxDiv) -+ Div = Div - 2; -+ else -+ break; -+ retry = retry - 1; -+ } -+ if (retry == 0) { -+ pr_err(" FAIL\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if (HSDiv == 8 || HSDiv == 10) { -+ HSDiv = HSDiv >> 1; -+ N = N * 2; -+ } -+ -+ if (HSDiv < 4) -+ return -EINVAL; -+ -+ -+ fDCO = (u64)fOut * (u64)N * (u64)HSDiv; -+ pr_info("fdco %16llx\n", fDCO); -+ RFreq = fDCO<<28; -+ pr_info("%16llx %16llx\n", fDCO, RFreq); -+ -+ fxtal = m_fXtal; -+ do_div(RFreq, fxtal); -+ pr_info("%16llx %d\n", RFreq, fxtal); -+ RF = RFreq; -+ -+ pr_info("fOut = %u fXtal = %llu fDCO = %llu HSDIV = %llu, N = %u, RFreq = %llu\n", -+ fOut, m_fXtal, fDCO, HSDiv, N, RFreq); -+ -+ Data[0] = (u8)(((HSDiv - 4) << 5) | ((N - 1) >> 2)); -+ Data[1] = (u8)((((N - 1) & 0x03) << 6) | ((RF >> 32) & 0x3F)); -+ Data[2] = (u8)((RF >> 24) & 0xFF); -+ Data[3] = (u8)((RF >> 16) & 0xFF); -+ Data[4] = (u8)((RF >> 8) & 0xFF); -+ Data[5] = (u8)((RF) & 0xFF); -+ -+ pr_info(" Data = %02x %02x %02x %02x %02x %02x\n", -+ Data[0], Data[1], Data[2], Data[3], Data[4], Data[5]); -+ mod_si598_writereg(dev, 7, Data[0]); -+ mod_si598_writereg(dev, 8, Data[1]); -+ mod_si598_writereg(dev, 9, Data[2]); -+ mod_si598_writereg(dev, 10, Data[3]); -+ mod_si598_writereg(dev, 11, Data[4]); -+ mod_si598_writereg(dev, 12, Data[5]); -+ -+ mod_si598_writereg(dev, 137, 0x00); -+ mod_si598_writereg(dev, 135, 0x40); -+ return 0; -+} -+ -+ -+static void mod_bypass_equalizer(struct ddb *dev, int bypass) -+{ -+ u32 RegValue; -+ -+ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); -+ RegValue &= ~IQOUTPUT_CONTROL_BYPASS_EQUALIZER; -+ RegValue |= (bypass ? IQOUTPUT_CONTROL_BYPASS_EQUALIZER : 0x00); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+} -+ -+static int mod_set_equalizer(struct ddb *dev, u32 Num, s16 *cTable) -+{ -+ u32 i, adr = IQOUTPUT_EQUALIZER_0; -+ -+ if (Num > 11) -+ return -EINVAL; -+ -+ for (i = 0; i < 11 - Num; i += 1) { -+ ddbwritel(dev, 0, adr); -+ adr += 4; -+ } -+ for (i = 0; i < Num; i += 1) { -+ ddbwritel(dev, (u32) cTable[i], adr); -+ adr += 4; -+ } -+ return 0; -+} -+ -+#if 0 -+static void mod_peak(struct ddb *dev, u32 Time, s16 *pIPeak, s16 *pQPeak) -+{ -+ u32 val; -+ -+ val = ddbreadl(dev, IQOUTPUT_CONTROL); -+ val &= ~(IQOUTPUT_CONTROL_ENABLE_PEAK | IQOUTPUT_CONTROL_RESET_PEAK); -+ ddbwritel(dev, val, IQOUTPUT_CONTROL); -+ ddbwritel(dev, val | IQOUTPUT_CONTROL_RESET_PEAK, IQOUTPUT_CONTROL); -+ msleep(20); -+ ddbwritel(dev, val, IQOUTPUT_CONTROL); -+ ddbwritel(dev, val | IQOUTPUT_CONTROL_ENABLE_PEAK, IQOUTPUT_CONTROL); -+ msleep(Time); -+ ddbwritel(dev, val, IQOUTPUT_CONTROL); -+ val = ddbreadl(dev, IQOUTPUT_PEAK_DETECTOR); -+ -+ *pIPeak = val & 0xffff; -+ *pQPeak = (val >> 16) & 0xffff; -+} -+#endif -+ -+static int mod_init_dac_input(struct ddb *dev) -+{ -+ u8 Set = 0; -+ u8 Hld = 0; -+ u8 Sample = 0; -+ -+ u8 Seek = 0; -+ u8 ReadSeek = 0; -+ -+ u8 SetTable[32]; -+ u8 HldTable[32]; -+ u8 SeekTable[32]; -+ -+ u8 Sample1 = 0xFF; -+ u8 Sample2 = 0xFF; -+ -+ u8 SelectSample = 0xFF; -+ u8 DiffMin = 0xFF; -+ -+ for (Sample = 0; Sample < 32; Sample++) { -+ Set = 0; -+ Hld = 0; -+ -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_write_dac_register(dev, 0x05, Sample); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek = ReadSeek & 0x01; -+ SeekTable[Sample] = Seek; -+ -+ HldTable[Sample] = 15; -+ -+ for (Hld = 1; Hld < 16; Hld += 1) { -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ -+ if ((ReadSeek & 0x01) != Seek) { -+ HldTable[Sample] = Hld; -+ break; -+ } -+ } -+ -+ Hld = 0; -+ SetTable[Sample] = 15; -+ for (Set = 1; Set < 16; Set += 1) { -+ mod_write_dac_register(dev, 0x04, Set << 4 | Hld); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ -+ if ((ReadSeek & 0x01) != Seek) { -+ SetTable[Sample] = Set; -+ break; -+ } -+ } -+ } -+ -+ Seek = 1; -+ for (Sample = 0; Sample < 32; Sample += 1) { -+ /* printk(" %2d: %d %2d %2d\n", -+ Sample, SeekTable[Sample], SetTable[Sample], -+ HldTable[Sample]); -+ */ -+ -+ if (Sample1 == 0xFF && SeekTable[Sample] == 1 && Seek == 0) -+ Sample1 = Sample; -+ if (Sample1 != 0xFF && Sample2 == 0xFF && -+ SeekTable[Sample] == 0 && Seek == 1) -+ Sample2 = Sample; -+ Seek = SeekTable[Sample]; -+ } -+ -+ if (Sample1 == 0xFF || Sample2 == 0xFF) { -+ pr_err(" No valid window found\n"); -+ return -EINVAL; -+ } -+ -+ pr_err(" Window = %d - %d\n", Sample1, Sample2); -+ -+ for (Sample = Sample1; Sample < Sample2; Sample += 1) { -+ if (SetTable[Sample] < HldTable[Sample]) { -+ if (HldTable[Sample] - SetTable[Sample] < DiffMin) { -+ DiffMin = HldTable[Sample] - SetTable[Sample]; -+ SelectSample = Sample; -+ } -+ } -+ } -+ -+ pr_info("Select Sample %d\n", SelectSample); -+ -+ if (SelectSample == 0xFF) { -+ pr_err("No valid sample found\n"); -+ return -EINVAL; -+ } -+ -+ if (HldTable[SelectSample] + SetTable[SelectSample] < 8) { -+ pr_err("Too high jitter\n"); -+ return -EINVAL; -+ } -+ -+ mod_write_dac_register(dev, 0x04, 0x00); -+ mod_write_dac_register(dev, 0x05, (SelectSample - 1) & 0x1F); -+ mod_read_dac_register(dev, 0x06, &Seek); -+ mod_write_dac_register(dev, 0x05, (SelectSample + 1) & 0x1F); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek &= ReadSeek; -+ -+ mod_write_dac_register(dev, 0x05, SelectSample); -+ mod_read_dac_register(dev, 0x06, &ReadSeek); -+ Seek &= ReadSeek; -+ if ((Seek & 0x01) == 0) { -+ pr_err("Insufficient timing margin\n"); -+ return -EINVAL; -+ } -+ pr_info("Done\n"); -+ return 0; -+} -+ -+static void mod_set_up1(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 RDiv = Ext / Ref; -+ -+ Frequency = Frequency / Ref; -+ mod_set_up_converter_vco1(dev, 0x360001 | (RDiv << 2)); -+ mod_set_up_converter_vco1(dev, 0x0ff128); -+ mod_set_up_converter_vco1(dev, 0x02 | (Frequency << 8)); -+} -+ -+static void mod_set_up2(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 Rdiv = Ext / Ref; -+ u32 PreScale = 8; -+ -+ Frequency = Frequency / Ref; -+ mod_set_up_converter_vco2(dev, 0x360001 | (Rdiv << 2)); -+ mod_set_up_converter_vco2(dev, 0x0fc128 | -+ (((PreScale - 8) / 8) << 22)); -+ mod_set_up_converter_vco2(dev, 0x02 | ((Frequency / PreScale) << 8) -+ | (Frequency & (PreScale - 1)) << 2); -+} -+ -+static int mod_set_down(struct ddb *dev, u32 Frequency, u32 Ref, u32 Ext) -+{ -+ u32 BandSelect = Ref * 8; -+ u32 RefMul = 1; -+ u32 RefDiv2 = 1; -+ u32 RefDiv = Ext * RefMul / (Ref * RefDiv2); -+ -+ if (Frequency < 2200 || Frequency > 4000) -+ return -EINVAL; -+ -+ Frequency = Frequency / Ref; -+ -+ mod_set_down_converter_vco(dev, 0x0080003C | -+ ((BandSelect & 0xFF) << 12)); -+ mod_set_down_converter_vco(dev, 0x00000003); -+ mod_set_down_converter_vco(dev, 0x18001E42 | ((RefMul-1) << 25) | -+ ((RefDiv2-1) << 24) | (RefDiv << 14)); -+ mod_set_down_converter_vco(dev, 0x08008021); -+ mod_set_down_converter_vco(dev, Frequency << 15); -+ return 0; -+} -+ -+static int mod_set_dac_clock(struct ddb *dev, u32 Frequency) -+{ -+ int hr, i; -+ -+ if (Frequency) { -+ ddbwritel(dev, DAC_CONTROL_RESET, DAC_CONTROL); -+ msleep(20); -+ if (mod_set_si598(dev, Frequency)) { -+ pr_err("mod_set_si598 failed\n"); -+ return -1; -+ } -+ msleep(50); -+ ddbwritel(dev, 0x000, DAC_CONTROL); -+ msleep(20); -+ mod_write_dac_register(dev, 0, 0x02); -+ } -+ -+ for (i = 0; i < 10; i++) { -+ hr = mod_init_dac_input(dev); -+ if (hr == 0) -+ break; -+ msleep(100); -+ } -+ pr_info("mod_set_dac_clock OK\n"); -+ return hr; -+} -+ -+static void mod_set_dac_current(struct ddb *dev, u32 Current1, u32 Current2) -+{ -+ mod_write_dac_register2(dev, 0x0b, Current1 & 0x3ff); -+ mod_write_dac_register2(dev, 0x0f, Current2 & 0x3ff); -+} -+ -+static void mod_output_enable(struct ddb *dev, int enable) -+{ -+ -+ u32 RegValue; -+ -+ RegValue = ddbreadl(dev, IQOUTPUT_CONTROL); -+ RegValue &= ~(IQOUTPUT_CONTROL_ENABLE | IQOUTPUT_CONTROL_RESET); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+ -+ if (enable) { -+ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_RESET, -+ IQOUTPUT_CONTROL); -+ msleep(20); -+ ddbwritel(dev, RegValue, IQOUTPUT_CONTROL); -+ ddbwritel(dev, RegValue | IQOUTPUT_CONTROL_ENABLE, -+ IQOUTPUT_CONTROL); -+ } -+} -+ -+static int mod_set_iq(struct ddb *dev, u32 steps, u32 chan, u32 freq) -+{ -+ u32 i, j, k, fac = 8; -+ u32 s1 = 22, s2 = 33; -+ u64 amp = (1ULL << 17) - 1ULL; -+ u64 s = 0, c = (amp << s1), ss; -+ u64 frq = 0xC90FDAA22168C234ULL; -+ u32 *iqtab; -+ u32 iqtabadr; -+ u32 regval; -+ -+ iqtab = kmalloc((steps + 1) * 4, GFP_KERNEL); -+ if (!iqtab) -+ return -ENOMEM; -+ frq = div64_u64(frq, steps * fac) >> (61 - s2); -+ -+ /* create sine table */ -+ for (i = 0; i <= steps * fac / 4; i++) { -+ if (!(i & (fac - 1))) { -+ j = i / fac; -+ ss = s >> s1; -+ /*round? ss = ((s >> (s1 - 1)) + 1) >> 1; */ -+ -+ iqtab[j] = iqtab[steps / 2 - j] = ss; -+ iqtab[steps / 2 + j] = iqtab[steps - j] = -ss; -+ } -+ c -= ((s * frq) >> s2); -+ s += ((c * frq) >> s2); -+ } -+ iqtabadr = chan << 16; -+ ddbwritel(dev, chan & 0x0f, MODULATOR_IQTABLE_INDEX); -+ for (i = j = 0, k = steps / 4; i < steps; i++) { -+ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_I, -+ MODULATOR_IQTABLE_INDEX); -+ ddbwritel(dev, iqtab[j], MODULATOR_IQTABLE_DATA); -+ regval = ddbreadl(dev, MODULATOR_CONTROL); -+ ddbwritel(dev, (iqtabadr + i) | MODULATOR_IQTABLE_INDEX_SEL_Q, -+ MODULATOR_IQTABLE_INDEX); -+ ddbwritel(dev, iqtab[k], MODULATOR_IQTABLE_DATA); -+ regval = ddbreadl(dev, MODULATOR_CONTROL); -+ j += freq; -+ j %= steps; -+ k += freq; -+ k %= steps; -+ } -+ ddbwritel(dev, steps - 1, MODULATOR_IQTABLE_END); -+ kfree(iqtab); -+ return 0; -+} -+ -+u32 eqtab[] = { -+ 0x0000FFDB, 0x00000121, 0x0000FF0A, 0x000003D7, -+ 0x000001C4, 0x000005A5, 0x000009CC, 0x0000F50D, -+ 0x00001B23, 0x0000EEB7, 0x00006A28 -+}; -+ -+static int mod_set_modulation(struct ddb *dev, int chan, enum fe_modulation mod) -+{ -+ if (mod > QAM_256 || mod < QAM_16) -+ return -EINVAL; -+ dev->mod[chan].modulation = mod; -+ dev->mod[chan].obitrate = 0x0061072787900000 * (mod + 3); -+ dev->mod[chan].ibitrate = dev->mod[chan].obitrate; -+ ddbwritel(dev, qamtab[mod], CHANNEL_SETTINGS(chan)); -+ return 0; -+} -+ -+static void mod_set_channelsumshift(struct ddb *dev, u32 shift) -+{ -+ ddbwritel(dev, (shift & 3) << 2, MODULATOR_CONTROL); -+} -+ -+static void mod_pre_eq_gain(struct ddb *dev, u16 gain) -+{ -+ ddbwritel(dev, gain, IQOUTPUT_PRESCALER); -+} -+ -+static void mod_post_eq_gain(struct ddb *dev, u16 igain, u16 qgain) -+{ -+ ddbwritel(dev, ((u32)qgain << 16) | igain, IQOUTPUT_POSTSCALER); -+} -+ -+static int set_base_frequency(struct ddb *dev, u32 freq) -+{ -+ u32 Ext = 40; -+ u32 UP1Frequency = 290; -+ u32 UP2Frequency = 1896; -+ u32 down, freq10; -+ -+ pr_info("set base to %u\n", freq); -+ dev->mod_base.frequency = freq; -+ freq /= 1000000; -+ freq10 = dev->mod_base.flat_start + 4; -+ down = freq + 9 * 8 + freq10 + UP1Frequency + UP2Frequency; -+ -+ if ((freq10 + 9 * 8) > (dev->mod_base.flat_end - 4)) { -+ pr_err("Frequency out of range %d\n", freq10); -+ return -EINVAL; -+ } -+ if (down % 8) { -+ pr_err(" Invalid Frequency %d\n", down); -+ return -EINVAL; -+ } -+ return mod_set_down(dev, down, 8, Ext); -+} -+ -+static int mod_init(struct ddb *dev, u32 Frequency) -+{ -+ int stat = 0; -+ u8 *buffer; -+ struct DDMOD_FLASH *flash; -+ u32 Ext = 40; -+ u32 UP1Frequency = 290; -+ u32 UP2Frequency = 1896; -+ u32 DownFrequency; -+ u32 FrequencyCH10; -+ u32 iqfreq, iqsteps, i; -+ -+ buffer = kmalloc(4096, GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ flash = (struct DDMOD_FLASH *) buffer; -+ -+ ddbridge_flashread(dev, buffer, DDMOD_FLASH_START, 4096); -+ -+ if (flash->Magic != DDMOD_FLASH_MAGIC && flash->Magic != 1) { -+ stat = -EINVAL; -+ goto fail; -+ } -+ pr_info("srate = %d\n", flash->DataSet[0].Symbolrate * 1000); -+ -+ mod_output_enable(dev, 0); -+ stat = mod_set_dac_clock(dev, flash->DataSet[0].DACFrequency * 1000); -+ if (stat < 0) { -+ pr_err("setting DAC clock failed\n"); -+ goto fail; -+ } -+ mod_set_dac_current(dev, 512, 512); -+ -+ ddbwritel(dev, flash->DataSet[0].Control2, IQOUTPUT_CONTROL2); -+ -+ mod_set_up1(dev, UP1Frequency, 5, Ext); -+ mod_set_up2(dev, UP2Frequency, 8, Ext); -+ -+ dev->mod_base.flat_start = flash->DataSet[0].FlatStart; -+ dev->mod_base.flat_end = flash->DataSet[0].FlatEnd; -+ -+ Frequency /= 1000000; -+ FrequencyCH10 = flash->DataSet[0].FlatStart + 4; -+ DownFrequency = Frequency + 9 * 8 + FrequencyCH10 + -+ UP1Frequency + UP2Frequency; -+ pr_info("CH10 = %d, Down = %d\n", FrequencyCH10, DownFrequency); -+ -+ if ((FrequencyCH10 + 9 * 8) > (flash->DataSet[0].FlatEnd - 4)) { -+ pr_err("Frequency out of range %d\n", FrequencyCH10); -+ stat = -EINVAL; -+ goto fail; -+ } -+ -+ if (DownFrequency % 8 != 0) { -+ pr_err(" Invalid Frequency %d\n", DownFrequency); -+ stat = -EINVAL; -+ goto fail; -+ } -+ -+ mod_set_down(dev, DownFrequency, 8, Ext); -+ -+ for (i = 0; i < 10; i++) { -+ ddbwritel(dev, 0, CHANNEL_CONTROL(i)); -+ -+ iqfreq = flash->DataSet[0].FrequencyFactor * -+ (FrequencyCH10 + (9 - i) * 8); -+ iqsteps = flash->DataSet[0].IQTableLength; -+ mod_set_iq(dev, iqsteps, i, iqfreq); -+ mod_set_modulation(dev, i, QAM_256); -+ } -+ -+ mod_bypass_equalizer(dev, 1); -+ mod_set_equalizer(dev, 11, flash->DataSet[0].EQTap); -+ mod_bypass_equalizer(dev, 0); -+ mod_post_eq_gain(dev, flash->DataSet[0].PostScaleI, -+ flash->DataSet[0].PostScaleQ); -+ mod_pre_eq_gain(dev, flash->DataSet[0].PreScale); -+ /*mod_pre_eq_gain(dev, 0x0680);*/ -+ pr_info("prescaler %04x\n", flash->DataSet[0].PreScale); -+ mod_set_channelsumshift(dev, 2); -+ mod_output_enable(dev, 1); -+ -+ /*mod_set_attenuator(dev, 10);*/ -+fail: -+ kfree(buffer); -+ return stat; -+} -+ -+#define PACKET_CLOCKS (27000000ULL*1504) -+#define FACTOR (1ULL << 22) -+ -+/* -+ double Increment = FACTOR*PACKET_CLOCKS/double(m_OutputBitrate); -+ double Decrement = FACTOR*PACKET_CLOCKS/double(m_InputBitrate); -+ -+ 27000000 * 1504 * 2^22 / (6900000 * 188 / 204) = 26785190066.1 -+*/ -+ -+void ddbridge_mod_rate_handler(unsigned long data) -+{ -+ struct ddb_output *output = (struct ddb_output *) data; -+ struct ddb_dma *dma = output->dma; -+ struct ddb *dev = output->port->dev; -+ struct mod_state *mod = &dev->mod[output->nr]; -+ -+ u32 chan = output->nr; -+ u32 OutPacketCount; -+ u32 InPacketCount; -+ u64 OutPackets, InPackets; -+ s64 PCRAdjust; -+ u32 PCRAdjustExt, PCRAdjustExtFrac, InPacketDiff, OutPacketDiff; -+ s32 PCRCorr; -+ -+ s64 pcr; -+ s64 PCRIncrementDiff; -+ s64 PCRIncrement; -+ u64 mul; -+ -+ if (!mod->pcr_correction) -+ return; -+ spin_lock(&dma->lock); -+ ddbwritel(dev, mod->Control | CHANNEL_CONTROL_FREEZE_STATUS, -+ CHANNEL_CONTROL(output->nr)); -+ -+ OutPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_OUT(chan)); -+ if (OutPacketCount < mod->LastOutPacketCount) -+ mod->OutOverflowPacketCount += 1; -+ mod->LastOutPacketCount = OutPacketCount; -+ -+ InPacketCount = ddbreadl(dev, CHANNEL_PKT_COUNT_IN(chan)); -+ if (InPacketCount < mod->LastInPacketCount) -+ mod->InOverflowPacketCount += 1; -+ mod->LastInPacketCount = InPacketCount; -+ -+ OutPackets = ((u64) (mod->OutOverflowPacketCount) << 20) | -+ OutPacketCount; -+ InPackets = ((u64) (mod->InOverflowPacketCount) << 20) | -+ InPacketCount; -+ -+ PCRAdjust = (s64) ((u64) ddbreadl(dev, -+ CHANNEL_PCR_ADJUST_ACCUL(chan)) | -+ (((u64) ddbreadl(dev, -+ CHANNEL_PCR_ADJUST_ACCUH(chan)) -+ << 32))); -+ PCRAdjustExt = (u32)((PCRAdjust & 0x7FFFFFFF) >> 22); -+ PCRAdjustExtFrac = (u32)((PCRAdjust & 0x003FFFFF) >> 12); -+ PCRAdjust >>= 31; -+ InPacketDiff = (u32) (InPackets - mod->LastInPackets); -+ OutPacketDiff = (u32) (OutPackets - mod->LastOutPackets); -+ PCRCorr = 0; -+ -+ switch (mod->State) { -+ case CM_STARTUP: -+ if (mod->StateCounter) { -+ if (mod->StateCounter == 1) { -+ if (mod->ibitrate == 0) { -+ mul = (0x1000000 * (u64) (OutPacketDiff - -+ InPacketDiff - -+ InPacketDiff/1000)); -+ if (OutPacketDiff) -+ mod->rate_inc = -+ div_u64(mul, OutPacketDiff); -+ else -+ mod->rate_inc = 0; -+ mod_set_rateinc(dev, output->nr); -+ mod->PCRIncrement = -+ div_u64(26785190066ULL, -+ mod->modulation + 3); -+ if (InPacketDiff) -+ mod->PCRDecrement = -+ div_u64(mod->PCRIncrement * -+ (u64) OutPacketDiff, -+ InPacketDiff); -+ else -+ mod->PCRDecrement = 0; -+ mod_set_incs(output); -+ } else { -+ mod->PCRIncrement = -+ div_u64(26785190066ULL, -+ mod->modulation + 3); -+ mod->PCRDecrement = -+ div_u64(FACTOR*PACKET_CLOCKS, -+ mod->ibitrate >> 32); -+ mod_set_incs(output); -+ } -+ } -+ mod->StateCounter--; -+ break; -+ } else if (InPacketDiff >= mod->MinInputPackets) { -+ mod->State = CM_ADJUST; -+ mod->Control |= CHANNEL_CONTROL_ENABLE_PCRADJUST; -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ } -+ break; -+ -+ case CM_ADJUST: -+ if (InPacketDiff < mod->MinInputPackets) { -+ pr_info("PCR Adjust reset IN: %u Min: %u\n", -+ InPacketDiff, mod->MinInputPackets); -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ ddbwritel(dev, -+ (mod->Control | -+ CHANNEL_CONTROL_FREEZE_STATUS) & -+ ~CHANNEL_CONTROL_ENABLE_PCRADJUST, -+ CHANNEL_CONTROL(chan)); -+ break; -+ } -+ -+ mod->PCRAdjustSum += (s32) PCRAdjust; -+ mod->InPacketsSum += InPacketDiff; -+ mod->OutPacketsSum += OutPacketDiff; -+ if (mod->StateCounter--) -+ break; -+ -+ if (mod->OutPacketsSum) -+ PCRIncrement = div_s64((s64)mod->InPacketsSum * -+ (s64)mod->PCRDecrement + -+ (s64)(mod->OutPacketsSum >> 1), -+ mod->OutPacketsSum); -+ else -+ PCRIncrement = 0; -+ -+ if (mod->PCRAdjustSum > 0) -+ PCRIncrement = RoundPCRDown(PCRIncrement); -+ else -+ PCRIncrement = RoundPCRUp(PCRIncrement); -+ -+ PCRIncrementDiff = PCRIncrement - mod->PCRIncrement; -+ if (PCRIncrementDiff > HW_LSB_MASK) -+ PCRIncrementDiff = HW_LSB_MASK; -+ if (PCRIncrementDiff < -HW_LSB_MASK) -+ PCRIncrementDiff = -HW_LSB_MASK; -+ -+ mod->PCRIncrement += PCRIncrementDiff; -+ pcr = ConvertPCR(mod->PCRIncrement); -+ pr_info("outl %016llx\n", pcr); -+ ddbwritel(dev, pcr & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTL(output->nr)); -+ ddbwritel(dev, (pcr >> 32) & 0xffffffff, -+ CHANNEL_PCR_ADJUST_OUTH(output->nr)); -+ mod_busy(dev, chan); -+ -+ PCRCorr = (s32) (PCRIncrementDiff >> HW_LSB_SHIFT); -+ mod->PCRRunningCorr += PCRCorr; -+ -+ mod->InPacketsSum = 0; -+ mod->OutPacketsSum = 0; -+ mod->PCRAdjustSum = 0; -+ mod->StateCounter = CM_AVERAGE; -+ break; -+ -+ default: -+ break; -+ } -+ ddbwritel(dev, mod->Control, CHANNEL_CONTROL(chan)); -+ -+ mod->LastInPackets = InPackets; -+ mod->LastOutPackets = OutPackets; -+ mod->LastPCRAdjust = (s32) PCRAdjust; -+ -+ spin_unlock(&dma->lock); -+ -+ pr_info("chan %d out %016llx in %016llx indiff %08x\n", -+ chan, OutPackets, InPackets, InPacketDiff); -+ pr_info("cnt %d pcra %016llx pcraext %08x pcraextfrac %08x pcrcorr %08x pcri %016llx\n", -+ mod->StateCounter, PCRAdjust, PCRAdjustExt, -+ PCRAdjustExtFrac, PCRCorr, mod->PCRIncrement); -+} -+ -+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb *dev = output->port->dev; -+ -+ /* unsigned long arg = (unsigned long) parg; */ -+ int ret = 0; -+ -+ switch (cmd) { -+ case DVB_MOD_SET: -+ { -+ struct dvb_mod_params *mp = parg; -+ -+ pr_info("set base freq\n"); -+ if (mp->base_frequency != dev->mod_base.frequency) -+ if (set_base_frequency(dev, mp->base_frequency)) -+ return -EINVAL; -+ pr_info("set attenuator\n"); -+ mod_set_attenuator(dev, mp->attenuator); -+ break; -+ } -+ case DVB_MOD_CHANNEL_SET: -+ { -+ struct dvb_mod_channel_params *cp = parg; -+ int res; -+ u32 ri; -+ -+ pr_info("set modulation\n"); -+ res = mod_set_modulation(dev, output->nr, cp->modulation); -+ if (res) -+ return res; -+ -+ if (cp->input_bitrate > dev->mod[output->nr].obitrate) -+ return -EINVAL; -+ dev->mod[output->nr].ibitrate = cp->input_bitrate; -+ dev->mod[output->nr].pcr_correction = cp->pcr_correction; -+ -+ pr_info("ibitrate %llu\n", dev->mod[output->nr].ibitrate); -+ pr_info("obitrate %llu\n", dev->mod[output->nr].obitrate); -+ if (cp->input_bitrate != 0) { -+ u64 d = dev->mod[output->nr].obitrate - -+ dev->mod[output->nr].ibitrate; -+ -+ d = div64_u64(d, dev->mod[output->nr].obitrate >> 24); -+ if (d > 0xfffffe) -+ ri = 0xfffffe; -+ else -+ ri = d; -+ } else -+ ri = 0; -+ dev->mod[output->nr].rate_inc = ri; -+ pr_info("ibr=%llu, obr=%llu, ri=0x%06x\n", -+ dev->mod[output->nr].ibitrate >> 32, -+ dev->mod[output->nr].obitrate >> 32, -+ ri); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+int ddbridge_mod_init(struct ddb *dev) -+{ -+ return mod_init(dev, 722000000); -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-ns.c b/drivers/media/pci/ddbridge/ddbridge-ns.c -new file mode 100644 -index 0000000..9d86cba ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge-ns.c -@@ -0,0 +1,489 @@ -+/* -+ * ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming -+ * -+ * Copyright (C) 2010-2014 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+static int ddb_dvb_input_start(struct ddb_input *input); -+static int ddb_dvb_input_stop(struct ddb_input *input); -+ -+static u16 calc_pcs(struct dvb_ns_params *p) -+{ -+ u32 sum = 0; -+ u16 pcs; -+ -+ sum += (p->sip[0] << 8) | p->sip[1]; -+ sum += (p->sip[2] << 8) | p->sip[3]; -+ sum += (p->dip[0] << 8) | p->dip[1]; -+ sum += (p->dip[2] << 8) | p->dip[3]; -+ sum += 0x11; /* UDP proto */ -+ sum = (sum >> 16) + (sum & 0xffff); -+ pcs = sum; -+ return pcs; -+} -+ -+static u16 calc_pcs16(struct dvb_ns_params *p, int ipv) -+{ -+ u32 sum = 0, i; -+ u16 pcs; -+ -+ for (i = 0; i < ipv ? 16 : 4; i += 2) { -+ sum += (p->sip[i] << 8) | p->sip[i + 1]; -+ sum += (p->dip[i] << 8) | p->dip[i + 1]; -+ } -+ sum += 0x11; /* UDP proto */ -+ sum = (sum >> 16) + (sum & 0xffff); -+ pcs = sum; -+ return pcs; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void ns_free(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ -+ mutex_lock(&dev->mutex); -+ dns->input = 0; -+ mutex_unlock(&dev->mutex); -+} -+ -+static int ns_alloc(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ int i, ret = -EBUSY; -+ -+ mutex_lock(&dev->mutex); -+ for (i = 0; i < dev->ns_num; i++) { -+ if (dev->ns[i].input) -+ continue; -+ dev->ns[i].input = input; -+ dev->ns[i].fe = input->nr; -+ nss->priv = &dev->ns[i]; -+ ret = 0; -+ /*pr_info("%s i=%d fe=%d\n", __func__, i, input->nr); */ -+ break; -+ } -+ ddbwritel(dev, 0x03, RTP_MASTER_CONTROL); -+ mutex_unlock(&dev->mutex); -+ return ret; -+} -+ -+static int ns_set_pids(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ -+ if (dev->ids.devid == 0x0301dd01) { -+ u32 sys = 0; -+ int pid, j = 1; -+ -+ sys |= nss->pids[0] & 3; -+ sys |= (nss->pids[2] & 0x1f) << 4; -+ ddbwritel(dev, sys, PID_FILTER_SYSTEM_PIDS(dns->nr)); -+ for (pid = 20; j < 5 && pid < 8192; pid++) -+ if (nss->pids[pid >> 3] & (1 << (pid & 7))) { -+ ddbwritel(dev, 0x8000 | pid, -+ PID_FILTER_PID(dns->nr, j)); -+ j++; -+ } -+ /* disable unused pids */ -+ for (; j < 5; j++) -+ ddbwritel(dev, 0, PID_FILTER_PID(dns->nr, j)); -+ } else -+ ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400); -+ return 0; -+} -+ -+static int ns_set_pid(struct dvbnss *nss, u16 pid) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u16 byte = (pid & 0x1fff) >> 3; -+ u8 bit = 1 << (pid & 7); -+ u32 off = STREAM_PIDS(dns->nr); -+ -+#if 1 -+ if (dev->ids.devid == 0x0301dd01) { -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ memset(nss->pids, 0xff, 0x400); -+ else -+ memset(nss->pids, 0x00, 0x400); -+ } else { -+ if (pid & 0x8000) -+ nss->pids[byte] |= bit; -+ else -+ nss->pids[byte] &= ~bit; -+ } -+ ns_set_pids(nss); -+ } else { -+ if (pid & 0x2000) { -+ if (pid & 0x8000) -+ ddbmemset(dev, off, 0xff, 0x400); -+ else -+ ddbmemset(dev, off, 0x00, 0x400); -+ } else { -+ u8 val = ddbreadb(dev, off + byte); -+ if (pid & 0x8000) -+ ddbwriteb(dev, val | bit, off + byte); -+ else -+ ddbwriteb(dev, val & ~bit, off + byte); -+ } -+ } -+#else -+ ddbcpyto(dev, STREAM_PIDS(dns->nr), nss->pids, 0x400); -+#endif -+ return 0; -+} -+ -+static int citoport(struct ddb *dev, u8 ci) -+{ -+ int i, j; -+ -+ for (i = j = 0; i < dev->info->port_num; i++) { -+ if (dev->port[i].class == DDB_PORT_CI) { -+ if (j == ci) -+ return i; -+ j++; -+ } -+ } -+ return -1; -+} -+ -+static int ns_set_ci(struct dvbnss *nss, u8 ci) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ int ciport; -+ -+ if (ci == 255) { -+ dns->fe = input->nr; -+ return 0; -+ } -+ ciport = citoport(dev, ci); -+ if (ciport < 0) -+ return -EINVAL; -+ pr_info("input %d to ci %d at port %d\n", input->nr, ci, ciport); -+ ddbwritel(dev, (input->nr << 16) | 0x1c, TS_OUTPUT_CONTROL(ciport)); -+ usleep_range(1, 5); -+ ddbwritel(dev, (input->nr << 16) | 0x1d, TS_OUTPUT_CONTROL(ciport)); -+ dns->fe = ciport * 2; -+ return 0; -+} -+ -+static u8 rtp_head[] = { -+ 0x80, 0x21, -+ 0x00, 0x00, /* seq number */ -+ 0x00, 0x00, 0x00, 0x00, /* time stamp*/ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+}; -+ -+static u8 rtcp_head[] = { -+ /* SR off 42:8 len 28*/ -+ 0x80, 0xc8, /* SR type */ -+ 0x00, 0x06, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* NTP */ -+ 0x73, 0x64, 0x00, 0x00, /* RTP TS */ -+ 0x00, 0x00, 0x00, 0x00, /* packet count */ -+ 0x00, 0x00, 0x00, 0x00, /* octet count */ -+ /* SDES off 70:36 len 20 */ -+ 0x81, 0xca, /* SDES */ -+ 0x00, 0x03, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x01, 0x05, /* CNAME item */ -+ 0x53, 0x41, 0x54, 0x49, 0x50, /* "SATIP" */ -+ 0x00, /* item type 0 */ -+ /* APP off 86:52 len 16+string length */ -+ 0x80, 0xcc, /* APP */ -+ 0x00, 0x04, /* len */ -+ 0x91, 0x82, 0x73, 0x64, /* SSRC */ -+ 0x53, 0x45, 0x53, 0x31, /* "SES1" */ -+ 0x00, 0x00, /* identifier */ -+ 0x00, 0x00, /* string length */ -+ /* string off 102:68 */ -+}; -+ -+static int ns_set_rtcp_msg(struct dvbnss *nss, u8 *msg, u32 len) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ u32 coff = 96; -+ u16 wlen; -+ -+ if (!len) { -+ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) & -+ ~0x10, -+ STREAM_CONTROL(dns->nr)); -+ return 0; -+ } -+ if (copy_from_user(dns->p + coff + dns->rtcp_len, msg, len)) -+ return -EFAULT; -+ dns->p[coff + dns->rtcp_len - 2] = (len >> 8); -+ dns->p[coff + dns->rtcp_len - 1] = (len & 0xff); -+ if (len & 3) { -+ u32 pad = 4 - (len & 3); -+ memset(dns->p + coff + dns->rtcp_len + len, 0, pad); -+ len += pad; -+ } -+ wlen = len / 4; -+ wlen += 3; -+ dns->p[coff + dns->rtcp_len - 14] = (wlen >> 8); -+ dns->p[coff + dns->rtcp_len - 13] = (wlen & 0xff); -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ ddbwritel(dev, (dns->rtcp_udplen + len) | -+ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), -+ STREAM_RTCP_PACKET(dns->nr)); -+ ddbwritel(dev, ddbreadl(dev, STREAM_CONTROL(dns->nr)) | 0x10, -+ STREAM_CONTROL(dns->nr)); -+ return 0; -+} -+ -+static u32 set_nsbuf(struct dvb_ns_params *p, u8 *buf, u32 *udplen, int rtcp) -+{ -+ u32 c = 0; -+ u16 pcs; -+ u16 sport, dport; -+ -+ sport = rtcp ? p->sport2 : p->sport; -+ dport = rtcp ? p->dport2 : p->dport; -+ -+ /* MAC header */ -+ memcpy(buf + c, p->dmac, 6); -+ memcpy(buf + c + 6, p->smac, 6); -+ c += 12; -+ if (vlan) { -+ buf[c + 0] = 0x81; -+ buf[c + 1] = 0x00; -+ buf[c + 2] = ((p->qos & 7) << 5) | ((p->vlan & 0xf00) >> 8); -+ buf[c + 3] = p->vlan & 0xff; -+ c += 4; -+ } -+ buf[c + 0] = 0x08; -+ buf[c + 1] = 0x00; -+ c += 2; -+ -+ /* IP header */ -+ if (p->flags & DVB_NS_IPV6) { -+ u8 ip6head[8] = { 0x65, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x11, 0x00, }; -+ memcpy(buf + c, ip6head, sizeof(ip6head)); -+ buf[c + 7] = p->ttl; -+ memcpy(buf + c + 8, p->sip, 16); -+ memcpy(buf + c + 24, p->dip, 16); -+ c += 40; -+ -+ /* UDP */ -+ buf[c + 0] = sport >> 8; -+ buf[c + 1] = sport & 0xff; -+ buf[c + 2] = dport >> 8; -+ buf[c + 3] = dport & 0xff; -+ buf[c + 4] = 0; /* length */ -+ buf[c + 5] = 0; -+ pcs = calc_pcs16(p, p->flags & DVB_NS_IPV6); -+ buf[c + 6] = pcs >> 8; -+ buf[c + 7] = pcs & 0xff; -+ c += 8; -+ *udplen = 8; -+ -+ } else { -+ u8 ip4head[12] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x40, 0x00, 0x40, 0x11, 0x00, 0x00 }; -+ -+ memcpy(buf + c, ip4head, sizeof(ip4head)); -+ buf[c + 8] = p->ttl; -+ memcpy(buf + c + 12, p->sip, 4); -+ memcpy(buf + c + 16, p->dip, 4); -+ c += 20; -+ -+ /* UDP */ -+ buf[c + 0] = sport >> 8; -+ buf[c + 1] = sport & 0xff; -+ buf[c + 2] = dport >> 8; -+ buf[c + 3] = dport & 0xff; -+ buf[c + 4] = 0; /* length */ -+ buf[c + 5] = 0; -+ pcs = calc_pcs(p); -+ buf[c + 6] = pcs >> 8; -+ buf[c + 7] = pcs & 0xff; -+ c += 8; -+ *udplen = 8; -+ } -+ -+ if (rtcp) { -+ memcpy(buf + c, rtcp_head, sizeof(rtcp_head)); -+ memcpy(buf + c + 4, p->ssrc, 4); -+ memcpy(buf + c + 32, p->ssrc, 4); -+ memcpy(buf + c + 48, p->ssrc, 4); -+ c += sizeof(rtcp_head); -+ *udplen += sizeof(rtcp_head); -+ } else if (p->flags & DVB_NS_RTP) { -+ memcpy(buf + c, rtp_head, sizeof(rtp_head)); -+ memcpy(buf + c + 8, p->ssrc, 4); -+ c += sizeof(rtp_head); -+ *udplen += sizeof(rtp_head); -+ } -+ return c; -+} -+ -+static int ns_set_ts_packets(struct dvbnss *nss, u8 *buf, u32 len) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ return -EINVAL; -+ -+ if (copy_from_user(dns->p + dns->ts_offset, buf, len)) -+ return -EFAULT; -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ return 0; -+} -+ -+static int ns_insert_ts_packets(struct dvbnss *nss, u8 count) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 value = count; -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ return -EINVAL; -+ -+ if (count < 1 || count > 2) -+ return -EINVAL; -+ -+ ddbwritel(dev, value, STREAM_INSERT_PACKET(dns->nr)); -+ return 0; -+} -+ -+static int ns_set_net(struct dvbnss *nss) -+{ -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ struct dvb_ns_params *p = &nss->params; -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ u32 off = STREAM_PACKET_ADR(dns->nr); -+ u32 coff = 96; -+ -+ dns->ts_offset = set_nsbuf(p, dns->p, &dns->udplen, 0); -+ if (nss->params.flags & DVB_NS_RTCP) -+ dns->rtcp_len = set_nsbuf(p, dns->p + coff, -+ &dns->rtcp_udplen, 1); -+ ddbcpyto(dev, off, dns->p, sizeof(dns->p)); -+ ddbwritel(dev, dns->udplen | (STREAM_PACKET_OFF(dns->nr) << 16), -+ STREAM_RTP_PACKET(dns->nr)); -+ ddbwritel(dev, dns->rtcp_udplen | -+ ((STREAM_PACKET_OFF(dns->nr) + coff) << 16), -+ STREAM_RTCP_PACKET(dns->nr)); -+ return 0; -+} -+ -+static int ns_start(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ u32 reg = 0x8003; -+ -+ -+ if (nss->params.flags & DVB_NS_RTCP) -+ reg |= 0x10; -+ if (nss->params.flags & DVB_NS_RTP_TO) -+ reg |= 0x20; -+ if (nss->params.flags & DVB_NS_RTP) -+ reg |= 0x40; -+ if (nss->params.flags & DVB_NS_IPV6) -+ reg |= 0x80; -+ if (dns->fe != input->nr) -+ ddb_dvb_input_start(&dev->input[dns->fe]); -+ ddb_dvb_input_start(input); -+ ddbwritel(dev, reg | (dns->fe << 8), STREAM_CONTROL(dns->nr)); -+ return 0; -+} -+ -+static int ns_stop(struct dvbnss *nss) -+{ -+ struct ddb_ns *dns = (struct ddb_ns *) nss->priv; -+ struct dvb_netstream *ns = nss->ns; -+ struct ddb_input *input = ns->priv; -+ struct ddb *dev = input->port->dev; -+ -+ ddbwritel(dev, 0x00, STREAM_CONTROL(dns->nr)); -+ ddb_dvb_input_stop(input); -+ if (dns->fe != input->nr) -+ ddb_dvb_input_stop(&dev->input[dns->fe]); -+ return 0; -+} -+ -+static int netstream_init(struct ddb_input *input) -+{ -+ struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; -+ struct dvb_adapter *adap = dvb->adap; -+ struct dvb_netstream *ns = &dvb->dvbns; -+ struct ddb *dev = input->port->dev; -+ int i, res; -+ -+ ddbmemset(dev, STREAM_PIDS(input->nr), 0x00, 0x400); -+ if (dev->ids.devid == 0x0301dd01) -+ dev->ns_num = 15; -+ else -+ dev->ns_num = 12; -+ for (i = 0; i < dev->ns_num; i++) -+ dev->ns[i].nr = i; -+ ns->priv = input; -+ ns->set_net = ns_set_net; -+ ns->set_rtcp_msg = ns_set_rtcp_msg; -+ ns->set_ts_packets = ns_set_ts_packets; -+ ns->insert_ts_packets = ns_insert_ts_packets; -+ ns->set_pid = ns_set_pid; -+ ns->set_pids = ns_set_pids; -+ ns->set_ci = ns_set_ci; -+ ns->start = ns_start; -+ ns->stop = ns_stop; -+ ns->alloc = ns_alloc; -+ ns->free = ns_free; -+ res = dvb_netstream_init(adap, ns); -+ return res; -+} -diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h -index a3ccb31..eca8574 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-regs.h -+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h -@@ -1,7 +1,7 @@ - /* - * ddbridge-regs.h: Digital Devices PCIe bridge driver - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2014 Digital Devices GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -21,11 +21,11 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */ -- - /* Register Definitions */ - --#define CUR_REGISTERMAP_VERSION 0x10000 -+#define CUR_REGISTERMAP_VERSION 0x10003 -+#define CUR_REGISTERMAP_VERSION_CI 0x10000 -+#define CUR_REGISTERMAP_VERSION_MOD 0x10000 - - #define HARDWARE_VERSION 0x00 - #define REGISTERMAP_VERSION 0x04 -@@ -37,10 +37,30 @@ - #define SPI_DATA 0x14 - - /* ------------------------------------------------------------------------- */ -+/* GPIO */ -+ -+#define GPIO_OUTPUT 0x20 -+#define GPIO_INPUT 0x24 -+#define GPIO_DIRECTION 0x28 -+ -+/* ------------------------------------------------------------------------- */ -+/* MDIO */ -+ -+#define MDIO_CTRL 0x20 -+#define MDIO_ADR 0x24 -+#define MDIO_REG 0x28 -+#define MDIO_VAL 0x2C -+ -+/* ------------------------------------------------------------------------- */ - --/* Interrupt controller */ --/* How many MSI's are available depends on HW (Min 2 max 8) */ --/* How many are usable also depends on Host platform */ -+#define BOARD_CONTROL 0x30 -+ -+/* ------------------------------------------------------------------------- */ -+ -+/* Interrupt controller -+ How many MSI's are available depends on HW (Min 2 max 8) -+ How many are usable also depends on Host platform -+*/ - - #define INTERRUPT_BASE (0x40) - -@@ -57,6 +77,9 @@ - #define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20) - #define INTERRUPT_ACK (INTERRUPT_BASE + 0x20) - -+#define INTMASK_CLOCKGEN (0x00000001) -+#define INTMASK_TEMPMON (0x00000002) -+ - #define INTMASK_I2C1 (0x00000001) - #define INTMASK_I2C2 (0x00000002) - #define INTMASK_I2C3 (0x00000004) -@@ -81,6 +104,32 @@ - #define INTMASK_TSOUTPUT3 (0x00040000) - #define INTMASK_TSOUTPUT4 (0x00080000) - -+ -+/* Clock Generator ( Sil598 @ 0xAA I2c ) */ -+#define CLOCKGEN_BASE (0x80) -+#define CLOCKGEN_CONTROL (CLOCKGEN_BASE + 0x00) -+#define CLOCKGEN_INDEX (CLOCKGEN_BASE + 0x04) -+#define CLOCKGEN_WRITEDATA (CLOCKGEN_BASE + 0x08) -+#define CLOCKGEN_READDATA (CLOCKGEN_BASE + 0x0C) -+ -+/* DAC ( AD9781/AD9783 SPI ) */ -+#define DAC_BASE (0x090) -+#define DAC_CONTROL (DAC_BASE) -+#define DAC_WRITE_DATA (DAC_BASE+4) -+#define DAC_READ_DATA (DAC_BASE+8) -+ -+#define DAC_CONTROL_INSTRUCTION_REG (0xFF) -+#define DAC_CONTROL_STARTIO (0x100) -+#define DAC_CONTROL_RESET (0x200) -+ -+/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */ -+#define TEMPMON_BASE (0xA0) -+#define TEMPMON_CONTROL (TEMPMON_BASE + 0x00) -+/* SHORT Temperature in °C x 256 */ -+#define TEMPMON_CORE (TEMPMON_BASE + 0x04) -+#define TEMPMON_SENSOR1 (TEMPMON_BASE + 0x08) -+#define TEMPMON_SENSOR2 (TEMPMON_BASE + 0x0C) -+ - /* ------------------------------------------------------------------------- */ - /* I2C Master Controller */ - -@@ -90,19 +139,14 @@ - #define I2C_TIMING (0x04) - #define I2C_TASKLENGTH (0x08) /* High read, low write */ - #define I2C_TASKADDRESS (0x0C) /* High read, low write */ -- - #define I2C_MONITOR (0x1C) - --#define I2C_BASE_1 (I2C_BASE + 0x00) --#define I2C_BASE_2 (I2C_BASE + 0x20) --#define I2C_BASE_3 (I2C_BASE + 0x40) --#define I2C_BASE_4 (I2C_BASE + 0x60) -- - #define I2C_BASE_N(i) (I2C_BASE + (i) * 0x20) - - #define I2C_TASKMEM_BASE (0x1000) /* Byte offset */ --#define I2C_TASKMEM_SIZE (0x1000) -+#define I2C_TASKMEM_SIZE (0x0800) - -+#define I2C_SPEED_666 (0x02010202) - #define I2C_SPEED_400 (0x04030404) - #define I2C_SPEED_200 (0x09080909) - #define I2C_SPEED_154 (0x0C0B0C0C) -@@ -117,35 +161,276 @@ - #define DMA_BASE_WRITE (0x100) - #define DMA_BASE_READ (0x140) - --#define DMA_CONTROL (0x00) /* 64 */ --#define DMA_ERROR (0x04) /* 65 ( only read instance ) */ -+#define DMA_CONTROL (0x00) -+#define DMA_ERROR (0x04) - --#define DMA_DIAG_CONTROL (0x1C) /* 71 */ --#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) /* 72 */ --#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) /* 73 */ --#define DMA_DIAG_TIMECOUNTER_LOW (0x28) /* 74 */ --#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) /* 75 */ --#define DMA_DIAG_RECHECKCOUNTER (0x30) /* 76 ( Split completions on read ) */ --#define DMA_DIAG_WAITTIMEOUTINIT (0x34) /* 77 */ --#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) /* 78 */ --#define DMA_DIAG_WAITCOUNTER (0x3C) /* 79 */ -+#define DMA_DIAG_CONTROL (0x1C) -+#define DMA_DIAG_PACKETCOUNTER_LOW (0x20) -+#define DMA_DIAG_PACKETCOUNTER_HIGH (0x24) -+#define DMA_DIAG_TIMECOUNTER_LOW (0x28) -+#define DMA_DIAG_TIMECOUNTER_HIGH (0x2C) -+#define DMA_DIAG_RECHECKCOUNTER (0x30) -+#define DMA_DIAG_WAITTIMEOUTINIT (0x34) -+#define DMA_DIAG_WAITOVERFLOWCOUNTER (0x38) -+#define DMA_DIAG_WAITCOUNTER (0x3C) - - /* ------------------------------------------------------------------------- */ - /* DMA Buffer */ - - #define TS_INPUT_BASE (0x200) --#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 16 + 0x00) -+#define TS_INPUT_CONTROL(i) (TS_INPUT_BASE + (i) * 0x10 + 0x00) -+#define TS_INPUT_CONTROL2(i) (TS_INPUT_BASE + (i) * 0x10 + 0x04) - - #define TS_OUTPUT_BASE (0x280) --#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 16 + 0x00) -+#define TS_OUTPUT_CONTROL(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x00) -+#define TS_OUTPUT_CONTROL2(i) (TS_OUTPUT_BASE + (i) * 0x10 + 0x04) - - #define DMA_BUFFER_BASE (0x300) - --#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 16 + 0x00) --#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 16 + 0x04) --#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 16 + 0x08) --#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 16 + 0x0c) -+#define DMA_BUFFER_CONTROL(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x00) -+#define DMA_BUFFER_ACK(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x04) -+#define DMA_BUFFER_CURRENT(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x08) -+#define DMA_BUFFER_SIZE(i) (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c) - - #define DMA_BASE_ADDRESS_TABLE (0x2000) - #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512) - -+ -+/* ------------------------------------------------------------------------- */ -+ -+#define LNB_BASE (0x400) -+#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00) -+#define LNB_CMD (7ULL << 0) -+#define LNB_CMD_NOP 0 -+#define LNB_CMD_INIT 1 -+#define LNB_CMD_STATUS 2 -+#define LNB_CMD_LOW 3 -+#define LNB_CMD_HIGH 4 -+#define LNB_CMD_OFF 5 -+#define LNB_CMD_DISEQC 6 -+#define LNB_CMD_UNI 7 -+ -+#define LNB_BUSY (1ULL << 4) -+#define LNB_TONE (1ULL << 15) -+ -+#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04) -+#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08) -+#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c) -+#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) -+#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14) -+ -+/* ------------------------------------------------------------------------- */ -+/* CI Interface (only CI-Bridge) */ -+ -+#define CI_BASE (0x400) -+#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) -+ -+#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) -+#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) -+#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) -+#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) -+ -+#define CI_RESET_CAM (0x00000001) -+#define CI_POWER_ON (0x00000002) -+#define CI_ENABLE (0x00000004) -+#define CI_BLOCKIO_ENABLE (0x00000008) -+#define CI_BYPASS_DISABLE (0x00000010) -+#define CI_DISABLE_AUTO_OFF (0x00000020) -+ -+#define CI_CAM_READY (0x00010000) -+#define CI_CAM_DETECT (0x00020000) -+#define CI_READY (0x80000000) -+#define CI_BLOCKIO_ACTIVE (0x40000000) -+#define CI_BLOCKIO_RCVDATA (0x20000000) -+#define CI_BLOCKIO_SEND_PENDING (0x10000000) -+#define CI_BLOCKIO_SEND_COMPLETE (0x08000000) -+ -+#define CI_READ_CMD (0x40000000) -+#define CI_WRITE_CMD (0x80000000) -+ -+#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) -+#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) -+ -+#define CI_BLOCKIO_SEND_COMMAND (0x80000000) -+#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) -+#define CI_BLOCKIO_RCVDATA_ACK (0x40000000) -+ -+#define CI_BUFFER_BASE (0x3000) -+#define CI_BUFFER_SIZE (0x0800) -+#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2) -+ -+#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_SEND_BUFFER(i) \ -+ (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) -+ -+#define VCO1_BASE (0xC0) -+#define VCO1_CONTROL (VCO1_BASE + 0x00) -+#define VCO1_DATA (VCO1_BASE + 0x04) /* 24 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO1_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO1_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO1_CONTROL_MUXOUT (0x00000004) -+ -+#define VCO2_BASE (0xC8) -+#define VCO2_CONTROL (VCO2_BASE + 0x00) -+#define VCO2_DATA (VCO2_BASE + 0x04) /* 24 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO2_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO2_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO2_CONTROL_MUXOUT (0x00000004) -+ -+#define VCO3_BASE (0xD0) -+#define VCO3_CONTROL (VCO3_BASE + 0x00) -+#define VCO3_DATA (VCO3_BASE + 0x04) /* 32 Bit */ -+/* 1 = Trigger write, resets when done */ -+#define VCO3_CONTROL_WRITE (0x00000001) -+/* 0 = Put VCO into power down */ -+#define VCO3_CONTROL_CE (0x00000002) -+/* Muxout from VCO (usually = Lock) */ -+#define VCO3_CONTROL_MUXOUT (0x00000004) -+ -+#define RF_ATTENUATOR (0xD8) -+/* 0x00 = 0 dB -+ 0x01 = 1 dB -+ ... -+ 0x1F = 31 dB -+*/ -+ -+#define RF_POWER (0xE0) -+#define RF_POWER_BASE (0xE0) -+#define RF_POWER_CONTROL (RF_POWER_BASE + 0x00) -+#define RF_POWER_DATA (RF_POWER_BASE + 0x04) -+ -+#define RF_POWER_CONTROL_START (0x00000001) -+#define RF_POWER_CONTROL_DONE (0x00000002) -+#define RF_POWER_CONTROL_VALIDMASK (0x00000700) -+#define RF_POWER_CONTROL_VALID (0x00000500) -+ -+ -+/* -------------------------------------------------------------------------- -+ Output control -+*/ -+ -+#define IQOUTPUT_BASE (0x240) -+#define IQOUTPUT_CONTROL (IQOUTPUT_BASE + 0x00) -+#define IQOUTPUT_CONTROL2 (IQOUTPUT_BASE + 0x04) -+#define IQOUTPUT_PEAK_DETECTOR (IQOUTPUT_BASE + 0x08) -+#define IQOUTPUT_POSTSCALER (IQOUTPUT_BASE + 0x0C) -+#define IQOUTPUT_PRESCALER (IQOUTPUT_BASE + 0x10) -+ -+#define IQOUTPUT_EQUALIZER_0 (IQOUTPUT_BASE + 0x14) -+#define IQOUTPUT_EQUALIZER_1 (IQOUTPUT_BASE + 0x18) -+#define IQOUTPUT_EQUALIZER_2 (IQOUTPUT_BASE + 0x1C) -+#define IQOUTPUT_EQUALIZER_3 (IQOUTPUT_BASE + 0x20) -+#define IQOUTPUT_EQUALIZER_4 (IQOUTPUT_BASE + 0x24) -+#define IQOUTPUT_EQUALIZER_5 (IQOUTPUT_BASE + 0x28) -+#define IQOUTPUT_EQUALIZER_6 (IQOUTPUT_BASE + 0x2C) -+#define IQOUTPUT_EQUALIZER_7 (IQOUTPUT_BASE + 0x30) -+#define IQOUTPUT_EQUALIZER_8 (IQOUTPUT_BASE + 0x34) -+#define IQOUTPUT_EQUALIZER_9 (IQOUTPUT_BASE + 0x38) -+#define IQOUTPUT_EQUALIZER_10 (IQOUTPUT_BASE + 0x3C) -+ -+#define IQOUTPUT_EQUALIZER(i) (IQOUTPUT_EQUALIZER_0 + (i) * 4) -+ -+#define IQOUTPUT_CONTROL_RESET (0x00000001) -+#define IQOUTPUT_CONTROL_ENABLE (0x00000002) -+#define IQOUTPUT_CONTROL_RESET_PEAK (0x00000004) -+#define IQOUTPUT_CONTROL_ENABLE_PEAK (0x00000008) -+#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER (0x00000010) -+ -+ -+/* Modulator Base */ -+ -+#define MODULATOR_BASE (0x200) -+#define MODULATOR_CONTROL (MODULATOR_BASE) -+#define MODULATOR_IQTABLE_END (MODULATOR_BASE+4) -+#define MODULATOR_IQTABLE_INDEX (MODULATOR_BASE+8) -+#define MODULATOR_IQTABLE_DATA (MODULATOR_BASE+12) -+ -+#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK (0x000F0000) -+#define MODULATOR_IQTABLE_INDEX_IQ_MASK (0x00008000) -+#define MODULATOR_IQTABLE_INDEX_ADDRESS_MASK (0x000007FF) -+#define MODULATOR_IQTABLE_INDEX_SEL_I (0x00000000) -+#define MODULATOR_IQTABLE_INDEX_SEL_Q (MODULATOR_IQTABLE_INDEX_IQ_MASK) -+#define MODULATOR_IQTABLE_SIZE (2048) -+ -+ -+/* Modulator Channels */ -+ -+#define CHANNEL_BASE (0x400) -+#define CHANNEL_CONTROL(i) (CHANNEL_BASE + (i) * 64 + 0x00) -+#define CHANNEL_SETTINGS(i) (CHANNEL_BASE + (i) * 64 + 0x04) -+#define CHANNEL_RATE_INCR(i) (CHANNEL_BASE + (i) * 64 + 0x0C) -+#define CHANNEL_PCR_ADJUST_OUTL(i) (CHANNEL_BASE + (i) * 64 + 0x10) -+#define CHANNEL_PCR_ADJUST_OUTH(i) (CHANNEL_BASE + (i) * 64 + 0x14) -+#define CHANNEL_PCR_ADJUST_INL(i) (CHANNEL_BASE + (i) * 64 + 0x18) -+#define CHANNEL_PCR_ADJUST_INH(i) (CHANNEL_BASE + (i) * 64 + 0x1C) -+#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20) -+#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24) -+#define CHANNEL_PKT_COUNT_OUT(i) (CHANNEL_BASE + (i) * 64 + 0x28) -+#define CHANNEL_PKT_COUNT_IN(i) (CHANNEL_BASE + (i) * 64 + 0x2C) -+ -+#define CHANNEL_CONTROL_RESET (0x00000001) -+#define CHANNEL_CONTROL_ENABLE_DVB (0x00000002) -+#define CHANNEL_CONTROL_ENABLE_IQ (0x00000004) -+#define CHANNEL_CONTROL_ENABLE_SOURCE (0x00000008) -+#define CHANNEL_CONTROL_ENABLE_PCRADJUST (0x00000010) -+#define CHANNEL_CONTROL_FREEZE_STATUS (0x00000100) -+ -+#define CHANNEL_CONTROL_RESET_ERROR (0x00010000) -+#define CHANNEL_CONTROL_BUSY (0x01000000) -+#define CHANNEL_CONTROL_ERROR_SYNC (0x20000000) -+#define CHANNEL_CONTROL_ERROR_UNDERRUN (0x40000000) -+#define CHANNEL_CONTROL_ERROR_FATAL (0x80000000) -+ -+#define CHANNEL_SETTINGS_QAM_MASK (0x00000007) -+#define CHANNEL_SETTINGS_QAM16 (0x00000000) -+#define CHANNEL_SETTINGS_QAM32 (0x00000001) -+#define CHANNEL_SETTINGS_QAM64 (0x00000002) -+#define CHANNEL_SETTINGS_QAM128 (0x00000003) -+#define CHANNEL_SETTINGS_QAM256 (0x00000004) -+ -+ -+/* OCTONET */ -+ -+#define ETHER_BASE (0x100) -+#define ETHER_CONTROL (ETHER_BASE + 0x00) -+#define ETHER_LENGTH (ETHER_BASE + 0x04) -+ -+#define RTP_MASTER_BASE (0x120) -+#define RTP_MASTER_CONTROL (RTP_MASTER_BASE + 0x00) -+#define RTP_RTCP_INTERRUPT (RTP_MASTER_BASE + 0x04) -+#define RTP_MASTER_RTCP_SETTINGS (RTP_MASTER_BASE + 0x0c) -+ -+#define STREAM_BASE (0x400) -+#define STREAM_CONTROL(i) (STREAM_BASE + (i) * 0x20 + 0x00) -+#define STREAM_RTP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x04) -+#define STREAM_RTCP_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x08) -+#define STREAM_RTP_SETTINGS(i) (STREAM_BASE + (i) * 0x20 + 0x0c) -+#define STREAM_INSERT_PACKET(i) (STREAM_BASE + (i) * 0x20 + 0x10) -+ -+#define STREAM_PACKET_OFF(i) ((i) * 0x200) -+#define STREAM_PACKET_ADR(i) (0x2000 + (STREAM_PACKET_OFF(i))) -+ -+#define STREAM_PIDS(i) (0x4000 + (i) * 0x400) -+ -+#define TS_CAPTURE_BASE (0x0140) -+#define TS_CAPTURE_CONTROL (TS_CAPTURE_BASE + 0x00) -+#define TS_CAPTURE_PID (TS_CAPTURE_BASE + 0x04) -+#define TS_CAPTURE_RECEIVED (TS_CAPTURE_BASE + 0x08) -+#define TS_CAPTURE_TIMEOUT (TS_CAPTURE_BASE + 0x0c) -+#define TS_CAPTURE_TABLESECTION (TS_CAPTURE_BASE + 0x10) -+ -+#define TS_CAPTURE_MEMORY (0x7000) -+ -+#define PID_FILTER_BASE (0x800) -+#define PID_FILTER_SYSTEM_PIDS(i) (PID_FILTER_BASE + (i) * 0x20) -+#define PID_FILTER_PID(i, j) (PID_FILTER_BASE + (i) * 0x20 + (j) * 4) -+ -+ -+ -diff --git a/drivers/media/pci/ddbridge/ddbridge.c b/drivers/media/pci/ddbridge/ddbridge.c -new file mode 100644 -index 0000000..9784f10 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/ddbridge.c -@@ -0,0 +1,470 @@ -+/* -+ * ddbridge.c: Digital Devices PCIe bridge driver -+ * -+ * Copyright (C) 2010-2013 Digital Devices GmbH -+ * Ralph Metzler -+ * Marcus Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*#define DDB_ALT_DMA*/ -+#define DDB_USE_WORK -+/*#define DDB_TEST_THREADED*/ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+static struct workqueue_struct *ddb_wq; -+ -+static int adapter_alloc; -+module_param(adapter_alloc, int, 0444); -+MODULE_PARM_DESC(adapter_alloc, -+ "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); -+ -+#ifdef CONFIG_PCI_MSI -+static int msi = 1; -+module_param(msi, int, 0444); -+MODULE_PARM_DESC(msi, -+ " Control MSI interrupts: 0-disable, 1-enable (default)"); -+#endif -+ -+#include "ddbridge-core.c" -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static void ddb_unmap(struct ddb *dev) -+{ -+ if (dev->regs) -+ iounmap(dev->regs); -+ vfree(dev); -+} -+ -+ -+static void __devexit ddb_remove(struct pci_dev *pdev) -+{ -+ struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev); -+ -+ ddb_ports_detach(dev); -+ ddb_i2c_release(dev); -+ -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0, MSI1_ENABLE); -+ if (dev->msi == 2) -+ free_irq(dev->pdev->irq + 1, dev); -+ free_irq(dev->pdev->irq, dev); -+#ifdef CONFIG_PCI_MSI -+ if (dev->msi) -+ pci_disable_msi(dev->pdev); -+#endif -+ ddb_ports_release(dev); -+ ddb_buffers_free(dev); -+ ddb_device_destroy(dev); -+ -+ ddb_unmap(dev); -+ pci_set_drvdata(pdev, 0); -+ pci_disable_device(pdev); -+} -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) -+#define __devinit -+#define __devinitdata -+#endif -+ -+static int __devinit ddb_probe(struct pci_dev *pdev, -+ const struct pci_device_id *id) -+{ -+ struct ddb *dev; -+ int stat = 0; -+ int irq_flag = IRQF_SHARED; -+ -+ if (pci_enable_device(pdev) < 0) -+ return -ENODEV; -+ -+ dev = vzalloc(sizeof(struct ddb)); -+ if (dev == NULL) -+ return -ENOMEM; -+ -+ dev->has_dma = 1; -+ dev->pdev = pdev; -+ dev->dev = &pdev->dev; -+ pci_set_drvdata(pdev, dev); -+ -+ dev->ids.vendor = id->vendor; -+ dev->ids.device = id->device; -+ dev->ids.subvendor = id->subvendor; -+ dev->ids.subdevice = id->subdevice; -+ -+ dev->info = (struct ddb_info *) id->driver_data; -+ pr_info("DDBridge driver detected: %s\n", dev->info->name); -+ -+ dev->regs_len = pci_resource_len(dev->pdev, 0); -+ dev->regs = ioremap(pci_resource_start(dev->pdev, 0), -+ pci_resource_len(dev->pdev, 0)); -+ if (!dev->regs) { -+ pr_err("DDBridge: not enough memory for register map\n"); -+ stat = -ENOMEM; -+ goto fail; -+ } -+ if (ddbreadl(dev, 0) == 0xffffffff) { -+ pr_err("DDBridge: cannot read registers\n"); -+ stat = -ENODEV; -+ goto fail; -+ } -+ -+ dev->ids.hwid = ddbreadl(dev, 0); -+ dev->ids.regmapid = ddbreadl(dev, 4); -+ -+ pr_info("HW %08x REGMAP %08x\n", -+ dev->ids.hwid, dev->ids.regmapid); -+ -+ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI1_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI2_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI3_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI4_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI5_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI6_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI7_ENABLE); -+ -+#ifdef CONFIG_PCI_MSI -+ if (msi && pci_msi_enabled()) { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) // OE -+ stat = pci_enable_msi_range(dev->pdev, 1, 2); -+ if (stat >= 1) { -+ dev->msi = stat; -+ pr_info(": Using %d MSI interrupts\n", dev->msi); -+ irq_flag = 0; -+ } else -+ pr_info(": MSI not available.\n"); -+#else -+ stat = pci_enable_msi_block(dev->pdev, 2); -+ if (stat == 0) { -+ dev->msi = 1; -+ pr_info("DDBrige using 2 MSI interrupts\n"); -+ } -+ if (stat == 1) -+ stat = pci_enable_msi(dev->pdev); -+ if (stat < 0) { -+ pr_info(": MSI not available.\n"); -+ } else { -+ irq_flag = 0; -+ dev->msi++; -+ } -+#endif -+ } -+ if (dev->msi == 2) { -+ stat = request_irq(dev->pdev->irq, irq_handler0, -+ irq_flag, "ddbridge", (void *) dev); -+ if (stat < 0) -+ goto fail0; -+ stat = request_irq(dev->pdev->irq + 1, irq_handler1, -+ irq_flag, "ddbridge", (void *) dev); -+ if (stat < 0) { -+ free_irq(dev->pdev->irq, dev); -+ goto fail0; -+ } -+ } else -+#endif -+ { -+#ifdef DDB_TEST_THREADED -+ stat = request_threaded_irq(dev->pdev->irq, irq_handler, -+ irq_thread, -+ irq_flag, -+ "ddbridge", (void *) dev); -+#else -+ stat = request_irq(dev->pdev->irq, irq_handler, -+ irq_flag, "ddbridge", (void *) dev); -+#endif -+ if (stat < 0) -+ goto fail0; -+ } -+ ddbwritel(dev, 0, DMA_BASE_READ); -+ if (dev->info->type != DDB_MOD) -+ ddbwritel(dev, 0, DMA_BASE_WRITE); -+ -+ /*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/ -+ if (dev->msi == 2) { -+ ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x0000000f, MSI1_ENABLE); -+ } else { -+ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x00000000, MSI1_ENABLE); -+ } -+ mutex_init(&dev->lnb_lock); -+ if (ddb_i2c_init(dev) < 0) -+ goto fail1; -+ ddb_ports_init(dev); -+ if (ddb_buffers_alloc(dev) < 0) { -+ pr_info(": Could not allocate buffer memory\n"); -+ goto fail2; -+ } -+ if (ddb_ports_attach(dev) < 0) -+ goto fail3; -+ -+ /* ignore if this fails */ -+ ddb_device_create(dev); -+ -+ if (dev->info->fan_num) { -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, 1, GPIO_OUTPUT); -+ } -+ if (dev->info->type == DDB_MOD) -+ ddbridge_mod_init(dev); -+ -+ return 0; -+ -+fail3: -+ ddb_ports_detach(dev); -+ pr_err("fail3\n"); -+ ddb_ports_release(dev); -+fail2: -+ pr_err("fail2\n"); -+ ddb_buffers_free(dev); -+ ddb_i2c_release(dev); -+fail1: -+ pr_err("fail1\n"); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0, MSI1_ENABLE); -+ free_irq(dev->pdev->irq, dev); -+ if (dev->msi == 2) -+ free_irq(dev->pdev->irq + 1, dev); -+fail0: -+ pr_err("fail0\n"); -+ if (dev->msi) -+ pci_disable_msi(dev->pdev); -+fail: -+ pr_err("fail\n"); -+ ddb_unmap(dev); -+ pci_set_drvdata(pdev, 0); -+ pci_disable_device(pdev); -+ return -1; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static struct ddb_regset octopus_i2c = { -+ .base = 0x80, -+ .num = 0x04, -+ .size = 0x20, -+}; -+ -+static struct ddb_regmap octopus_map = { -+ .i2c = &octopus_i2c, -+}; -+ -+static struct ddb_info ddb_none = { -+ .type = DDB_NONE, -+ .name = "unknown Digital Devices PCIe card, install newer driver", -+ .regmap = &octopus_map, -+}; -+ -+static struct ddb_info ddb_octopus = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+}; -+ -+static struct ddb_info ddb_octopusv3 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus V3 DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+}; -+ -+static struct ddb_info ddb_octopus_le = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus LE DVB adapter", -+ .port_num = 2, -+ .i2c_num = 2, -+}; -+ -+static struct ddb_info ddb_octopus_oem = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus OEM", -+ .port_num = 4, -+ .i2c_num = 4, -+ .led_num = 1, -+ .fan_num = 1, -+ .temp_num = 1, -+ .temp_bus = 0, -+}; -+ -+static struct ddb_info ddb_octopus_mini = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus Mini", -+ .port_num = 4, -+ .i2c_num = 4, -+}; -+ -+static struct ddb_info ddb_v6 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V6 DVB adapter", -+ .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_v6_5 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V6.5 DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+}; -+ -+static struct ddb_info ddb_v7 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V7 DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+ .board_control = 2, -+}; -+ -+static struct ddb_info ddb_s2_48 = { -+ .type = DDB_OCTOPUS_MAX, -+ .name = "Digital Devices Cine S2 4/8", -+ .port_num = 4, -+ .i2c_num = 1, -+ .board_control = 1, -+}; -+ -+static struct ddb_info ddb_ctv7 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine CT V7 DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+ .board_control = 3, -+}; -+ -+static struct ddb_info ddb_satixS2v3 = { -+ .type = DDB_OCTOPUS, -+ .name = "Mystique SaTiX-S2 V3 DVB adapter", -+ .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_ci = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI", -+ .port_num = 4, -+ .i2c_num = 2, -+}; -+ -+static struct ddb_info ddb_cis = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI single", -+ .port_num = 3, -+ .i2c_num = 2, -+}; -+ -+static struct ddb_info ddb_dvbct = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices DVBCT V6.1 DVB adapter", -+ .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_mod = { -+ .type = DDB_MOD, -+ .name = "Digital Devices DVB-C modulator", -+ .port_num = 10, -+ .temp_num = 1, -+}; -+ -+#define DDVID 0xdd01 /* Digital Devices Vendor ID */ -+ -+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ -+ .vendor = _vend, .device = _dev, \ -+ .subvendor = _subvend, .subdevice = _subdev, \ -+ .driver_data = (unsigned long)&_driverdata } -+ -+static const struct pci_device_id ddb_id_tbl[] __devinitconst = { -+ DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), -+ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), -+ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7), -+ DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7), -+ DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), -+ DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod), -+ /* in case sub-ids got deleted in flash */ -+ DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none), -+ {0} -+}; -+MODULE_DEVICE_TABLE(pci, ddb_id_tbl); -+ -+static struct pci_driver ddb_pci_driver = { -+ .name = "ddbridge", -+ .id_table = ddb_id_tbl, -+ .probe = ddb_probe, -+ .remove = ddb_remove, -+}; -+ -+static __init int module_init_ddbridge(void) -+{ -+ int stat = -1; -+ -+ pr_info("Digital Devices PCIE bridge driver " -+ DDBRIDGE_VERSION -+ ", Copyright (C) 2010-14 Digital Devices GmbH\n"); -+ if (ddb_class_create() < 0) -+ return -1; -+ ddb_wq = create_workqueue("ddbridge"); -+ if (ddb_wq == NULL) -+ goto exit1; -+ stat = pci_register_driver(&ddb_pci_driver); -+ if (stat < 0) -+ goto exit2; -+ return stat; -+exit2: -+ destroy_workqueue(ddb_wq); -+exit1: -+ ddb_class_destroy(); -+ return stat; -+} -+ -+static __exit void module_exit_ddbridge(void) -+{ -+ pci_unregister_driver(&ddb_pci_driver); -+ destroy_workqueue(ddb_wq); -+ ddb_class_destroy(); -+} -+ -+module_init(module_init_ddbridge); -+module_exit(module_exit_ddbridge); -+ -+MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); -+MODULE_AUTHOR("Ralph Metzler, Metzler Brothers Systementwicklung"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DDBRIDGE_VERSION); -diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h -index be87fbd..a02e91a 100644 ---- a/drivers/media/pci/ddbridge/ddbridge.h -+++ b/drivers/media/pci/ddbridge/ddbridge.h -@@ -1,7 +1,8 @@ - /* - * ddbridge.h: Digital Devices PCIe bridge driver - * -- * Copyright (C) 2010-2011 Digital Devices GmbH -+ * Copyright (C) 2010-2014 Digital Devices GmbH -+ * Ralph Metzler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -24,16 +25,51 @@ - #ifndef _DDBRIDGE_H_ - #define _DDBRIDGE_H_ - -+#include -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) -+#define __devexit -+#define __devinit -+#define __devinitconst -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ - #include - #include - #include - #include - #include - #include --#include -+#include -+#include -+#include -+ - #include - #include -+#include -+#include - -+#include "dvb_netstream.h" - #include "dmxdev.h" - #include "dvbdev.h" - #include "dvb_demux.h" -@@ -41,95 +77,167 @@ - #include "dvb_ringbuffer.h" - #include "dvb_ca_en50221.h" - #include "dvb_net.h" -+ -+#include "tda18271c2dd.h" -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "lnbh24.h" -+#include "drxk.h" -+#include "stv0367.h" -+#include "stv0367dd.h" -+#include "tda18212.h" -+#include "tda18212dd.h" -+#include "cxd2843.h" - #include "cxd2099.h" -+#include "stv0910.h" -+#include "stv6111.h" -+#include "lnbh25.h" - - #define DDB_MAX_I2C 4 --#define DDB_MAX_PORT 4 -+#define DDB_MAX_PORT 10 - #define DDB_MAX_INPUT 8 --#define DDB_MAX_OUTPUT 4 -+#define DDB_MAX_OUTPUT 10 -+ -+struct ddb_regset { -+ u32 base; -+ u32 num; -+ u32 size; -+}; -+ -+struct ddb_regmap { -+ struct ddb_regset *i2c; -+ struct ddb_regset *i2c_buf; -+ struct ddb_regset *dma; -+ struct ddb_regset *dma_buf; -+ struct ddb_regset *input; -+ struct ddb_regset *output; -+ struct ddb_regset *channel; -+ struct ddb_regset *ci; -+ struct ddb_regset *pid_filter; -+ struct ddb_regset *ns; -+}; -+ -+struct ddb_ids { -+ u16 vendor; -+ u16 device; -+ u16 subvendor; -+ u16 subdevice; -+ -+ u32 hwid; -+ u32 regmapid; -+ u32 devid; -+ u32 mac; -+}; - - struct ddb_info { - int type; - #define DDB_NONE 0 - #define DDB_OCTOPUS 1 -+#define DDB_OCTOPUS_CI 2 -+#define DDB_MOD 3 -+#define DDB_OCTONET 4 -+#define DDB_OCTOPUS_MAX 5 - char *name; -- int port_num; -- u32 port_type[DDB_MAX_PORT]; -+ u8 port_num; -+ u8 i2c_num; -+ u8 led_num; -+ u8 fan_num; -+ u8 temp_num; -+ u8 temp_bus; -+ u8 board_control; -+ u8 ns_num; -+ u8 mdio_num; -+ struct ddb_regmap *regmap; - }; - --/* DMA_SIZE MUST be divisible by 188 and 128 !!! */ - --#define INPUT_DMA_MAX_BUFS 32 /* hardware table limit */ -+/* DMA_SIZE MUST be smaller than 256k and -+ MUST be divisible by 188 and 128 !!! */ -+ -+#define DMA_MAX_BUFS 32 /* hardware table limit */ -+ - #define INPUT_DMA_BUFS 8 - #define INPUT_DMA_SIZE (128*47*21) -+#define INPUT_DMA_IRQ_DIV 1 - --#define OUTPUT_DMA_MAX_BUFS 32 - #define OUTPUT_DMA_BUFS 8 - #define OUTPUT_DMA_SIZE (128*47*21) -+#define OUTPUT_DMA_IRQ_DIV 1 - - struct ddb; - struct ddb_port; - --struct ddb_input { -- struct ddb_port *port; -+struct ddb_dma { -+ void *io; - u32 nr; -- int attached; -- -- dma_addr_t pbuf[INPUT_DMA_MAX_BUFS]; -- u8 *vbuf[INPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -+ dma_addr_t pbuf[DMA_MAX_BUFS]; -+ u8 *vbuf[DMA_MAX_BUFS]; -+ u32 num; -+ u32 size; -+ u32 div; -+ u32 bufreg; - -+#ifdef DDB_USE_WORK -+ struct work_struct work; -+#else - struct tasklet_struct tasklet; -+#endif - spinlock_t lock; - wait_queue_head_t wq; - int running; - u32 stat; -+ u32 ctrl; - u32 cbuf; - u32 coff; -+}; - -- struct dvb_adapter adap; -+struct ddb_dvb { -+ struct dvb_adapter *adap; -+ int adap_registered; - struct dvb_device *dev; - struct dvb_frontend *fe; - struct dvb_frontend *fe2; - struct dmxdev dmxdev; - struct dvb_demux demux; - struct dvb_net dvbnet; -+ struct dvb_netstream dvbns; - struct dmx_frontend hw_frontend; - struct dmx_frontend mem_frontend; - int users; -- int (*gate_ctrl)(struct dvb_frontend *, int); -+ u32 attached; -+ u8 input; -+ -+ int (*i2c_gate_ctrl)(struct dvb_frontend *, int); -+ int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); -+ int (*set_input)(struct dvb_frontend *fe); - }; - --struct ddb_output { -+struct ddb_ci { -+ struct dvb_ca_en50221 en; - struct ddb_port *port; - u32 nr; -- dma_addr_t pbuf[OUTPUT_DMA_MAX_BUFS]; -- u8 *vbuf[OUTPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -- struct tasklet_struct tasklet; -- spinlock_t lock; -- wait_queue_head_t wq; -- int running; -- u32 stat; -- u32 cbuf; -- u32 coff; -+ struct mutex lock; -+}; - -- struct dvb_adapter adap; -- struct dvb_device *dev; -+struct ddb_io { -+ struct ddb_port *port; -+ u32 nr; -+ struct ddb_dma *dma; -+ struct ddb_io *redo; -+ struct ddb_io *redi; - }; - -+#define ddb_output ddb_io -+#define ddb_input ddb_io -+ - struct ddb_i2c { - struct ddb *dev; - u32 nr; - struct i2c_adapter adap; -- struct i2c_adapter adap2; - u32 regs; - u32 rbuf; - u32 wbuf; -- int done; -- wait_queue_head_t wq; -+ struct completion completion; - }; - - struct ddb_port { -@@ -141,43 +249,250 @@ struct ddb_port { - #define DDB_PORT_NONE 0 - #define DDB_PORT_CI 1 - #define DDB_PORT_TUNER 2 -- u32 type; --#define DDB_TUNER_NONE 0 --#define DDB_TUNER_DVBS_ST 1 --#define DDB_TUNER_DVBS_ST_AA 2 --#define DDB_TUNER_DVBCT_TR 16 --#define DDB_TUNER_DVBCT_ST 17 -- u32 adr; -+#define DDB_PORT_LOOP 3 -+#define DDB_PORT_MOD 4 -+ char *name; -+ u32 type; -+#define DDB_TUNER_NONE 0 -+#define DDB_TUNER_DVBS_ST 1 -+#define DDB_TUNER_DVBS_ST_AA 2 -+#define DDB_TUNER_DVBCT_TR 3 -+#define DDB_TUNER_DVBCT_ST 4 -+#define DDB_CI_INTERNAL 5 -+#define DDB_CI_EXTERNAL_SONY 6 -+#define DDB_TUNER_DVBCT2_SONY_P 7 -+#define DDB_TUNER_DVBC2T2_SONY_P 8 -+#define DDB_TUNER_ISDBT_SONY_P 9 -+#define DDB_TUNER_DVBS_STV0910_P 10 -+#define DDB_TUNER_MXL5XX 11 - -+#define DDB_TUNER_XO2 16 -+#define DDB_TUNER_DVBS_STV0910 16 -+#define DDB_TUNER_DVBCT2_SONY 17 -+#define DDB_TUNER_ISDBT_SONY 18 -+#define DDB_TUNER_DVBC2T2_SONY 19 -+#define DDB_TUNER_ATSC_ST 20 -+#define DDB_TUNER_DVBC2T2_ST 21 -+ -+ u32 adr; - struct ddb_input *input[2]; - struct ddb_output *output; - struct dvb_ca_en50221 *en; -+ struct ddb_dvb dvb[2]; -+ u32 gap; -+ u32 obr; -+}; -+ -+ -+struct mod_base { -+ u32 frequency; -+ -+ u32 flat_start; -+ u32 flat_end; -+}; -+ -+struct mod_state { -+ u32 modulation; -+ u64 obitrate; -+ u64 ibitrate; -+ u32 pcr_correction; -+ -+ u32 rate_inc; -+ u32 Control; -+ u32 State; -+ u32 StateCounter; -+ s32 LastPCRAdjust; -+ s32 PCRAdjustSum; -+ s32 InPacketsSum; -+ s32 OutPacketsSum; -+ s64 PCRIncrement; -+ s64 PCRDecrement; -+ s32 PCRRunningCorr; -+ u32 OutOverflowPacketCount; -+ u32 InOverflowPacketCount; -+ u32 LastOutPacketCount; -+ u32 LastInPacketCount; -+ u64 LastOutPackets; -+ u64 LastInPackets; -+ u32 MinInputPackets; -+}; -+ -+#define CM_STARTUP_DELAY 2 -+#define CM_AVERAGE 20 -+#define CM_GAIN 10 -+ -+#define HW_LSB_SHIFT 12 -+#define HW_LSB_MASK 0x1000 -+ -+#define CM_IDLE 0 -+#define CM_STARTUP 1 -+#define CM_ADJUST 2 -+ -+#define TS_CAPTURE_LEN (4096) -+ -+/* net streaming hardware block */ -+ -+#define DDB_NS_MAX 15 -+ -+struct ddb_ns { -+ struct ddb_input *input; -+ int nr; -+ int fe; -+ u32 rtcp_udplen; -+ u32 rtcp_len; -+ u32 ts_offset; -+ u32 udplen; -+ u8 p[512]; - }; - - struct ddb { - struct pci_dev *pdev; -- unsigned char __iomem *regs; -+ struct platform_device *pfdev; -+ struct device *dev; -+ struct ddb_ids ids; -+ struct ddb_info *info; -+ int msi; -+ struct workqueue_struct *wq; -+ u32 has_dma; -+ u32 has_ns; -+ -+ struct ddb_regmap regmap; -+ unsigned char *regs; -+ u32 regs_len; - struct ddb_port port[DDB_MAX_PORT]; - struct ddb_i2c i2c[DDB_MAX_I2C]; - struct ddb_input input[DDB_MAX_INPUT]; - struct ddb_output output[DDB_MAX_OUTPUT]; -+ struct dvb_adapter adap[DDB_MAX_INPUT]; -+ struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; -+ -+ void (*handler[32])(unsigned long); -+ unsigned long handler_data[32]; - - struct device *ddb_dev; -- int nr; -+ u32 ddb_dev_users; -+ u32 nr; - u8 iobuf[1028]; - -- struct ddb_info *info; -- int msi; -+ u8 leds; -+ u32 ts_irq; -+ u32 i2c_irq; -+ -+ int ns_num; -+ struct ddb_ns ns[DDB_NS_MAX]; -+ struct mutex mutex; -+ -+ struct dvb_device *nsd_dev; -+ u8 tsbuf[TS_CAPTURE_LEN]; -+ -+ struct mod_base mod_base; -+ struct mod_state mod[10]; -+ -+ struct mutex octonet_i2c_lock; -+ struct mutex lnb_lock; -+ u32 lnb_tone; - }; - -+ - /****************************************************************************/ - --#define ddbwritel(_val, _adr) writel((_val), \ -- dev->regs+(_adr)) --#define ddbreadl(_adr) readl(dev->regs+(_adr)) --#define ddbcpyto(_adr, _src, _count) memcpy_toio(dev->regs+(_adr), (_src), (_count)) --#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), dev->regs+(_adr), (_count)) -+static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr) -+{ -+ writeb(val, (char *) (dev->regs+(adr))); -+} -+ -+static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr) -+{ -+ writel(val, (char *) (dev->regs+(adr))); -+} -+ -+static inline void ddbwritew(struct ddb *dev, u16 val, u32 adr) -+{ -+ writew(val, (char *) (dev->regs+(adr))); -+} -+ -+static inline u32 ddbreadl(struct ddb *dev, u32 adr) -+{ -+ return readl((char *) (dev->regs+(adr))); -+} -+ -+static inline u32 ddbreadb(struct ddb *dev, u32 adr) -+{ -+ return readb((char *) (dev->regs+(adr))); -+} - -+#define ddbcpyto(_dev, _adr, _src, _count) \ -+ memcpy_toio((char *) (_dev->regs + (_adr)), (_src), (_count)) -+ -+#define ddbcpyfrom(_dev, _dst, _adr, _count) \ -+ memcpy_fromio((_dst), (char *) (_dev->regs + (_adr)), (_count)) -+ -+#define ddbmemset(_dev, _adr, _val, _count) \ -+ memset_io((char *) (_dev->regs + (_adr)), (_val), (_count)) -+ -+ -+/****************************************************************************/ -+/****************************************************************************/ - /****************************************************************************/ - -+#define dd_uint8 u8 -+#define dd_uint16 u16 -+#define dd_int16 s16 -+#define dd_uint32 u32 -+#define dd_int32 s32 -+#define dd_uint64 u64 -+#define dd_int64 s64 -+ -+#define DDMOD_FLASH_START 0x1000 -+ -+struct DDMOD_FLASH_DS { -+ dd_uint32 Symbolrate; /* kSymbols/s */ -+ dd_uint32 DACFrequency; /* kHz */ -+ dd_uint16 FrequencyResolution; /* kHz */ -+ dd_uint16 IQTableLength; -+ dd_uint16 FrequencyFactor; -+ dd_int16 PhaseCorr; /* TBD */ -+ dd_uint32 Control2; -+ dd_uint16 PostScaleI; -+ dd_uint16 PostScaleQ; -+ dd_uint16 PreScale; -+ dd_int16 EQTap[11]; -+ dd_uint16 FlatStart; -+ dd_uint16 FlatEnd; -+ dd_uint32 FlashOffsetPrecalculatedIQTables; /* 0 = none */ -+ dd_uint8 Reserved[28]; -+ -+}; -+ -+struct DDMOD_FLASH { -+ dd_uint32 Magic; -+ dd_uint16 Version; -+ dd_uint16 DataSets; -+ -+ dd_uint16 VCORefFrequency; /* MHz */ -+ dd_uint16 VCO1Frequency; /* MHz */ -+ dd_uint16 VCO2Frequency; /* MHz */ -+ -+ dd_uint16 DACAux1; /* TBD */ -+ dd_uint16 DACAux2; /* TBD */ -+ -+ dd_uint8 Reserved1[238]; -+ -+ struct DDMOD_FLASH_DS DataSet[1]; -+}; -+ -+#define DDMOD_FLASH_MAGIC 0x5F564d5F -+ -+ -+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg); -+int ddbridge_mod_init(struct ddb *dev); -+void ddbridge_mod_output_stop(struct ddb_output *output); -+void ddbridge_mod_output_start(struct ddb_output *output); -+void ddbridge_mod_rate_handler(unsigned long data); -+ -+ -+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len); -+ -+#define DDBRIDGE_VERSION "0.9.15" -+ - #endif -diff --git a/drivers/media/pci/ddbridge/octonet.c b/drivers/media/pci/ddbridge/octonet.c -new file mode 100644 -index 0000000..e803e73 ---- /dev/null -+++ b/drivers/media/pci/ddbridge/octonet.c -@@ -0,0 +1,199 @@ -+/* -+ * octonet.c: Digital Devices network tuner driver -+ * -+ * Copyright (C) 2012-14 Digital Devices GmbH -+ * Ralph Metzler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "ddbridge.h" -+#include "ddbridge-regs.h" -+ -+#include -+ -+static int adapter_alloc = 3; -+module_param(adapter_alloc, int, 0444); -+MODULE_PARM_DESC(adapter_alloc, -+"0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); -+ -+#define DVB_NSD -+ -+#include "ddbridge-core.c" -+ -+static struct ddb_info ddb_octonet = { -+ .type = DDB_OCTONET, -+ .name = "Digital Devices OctopusNet network DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+ .ns_num = 12, -+ .mdio_num = 1, -+}; -+ -+static void octonet_unmap(struct ddb *dev) -+{ -+ if (dev->regs) -+ iounmap(dev->regs); -+ vfree(dev); -+} -+ -+static int __exit octonet_remove(struct platform_device *pdev) -+{ -+ struct ddb *dev; -+ -+ dev = platform_get_drvdata(pdev); -+ -+ ddb_nsd_detach(dev); -+ ddb_ports_detach(dev); -+ ddb_i2c_release(dev); -+ -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ free_irq(platform_get_irq(dev->pfdev, 0), dev); -+ -+ ddb_ports_release(dev); -+ ddb_device_destroy(dev); -+ octonet_unmap(dev); -+ platform_set_drvdata(pdev, 0); -+ return 0; -+} -+ -+static int __init octonet_probe(struct platform_device *pdev) -+{ -+ struct ddb *dev; -+ struct resource *regs; -+ int i; -+ -+ dev = vzalloc(sizeof(struct ddb)); -+ if (!dev) -+ return -ENOMEM; -+ platform_set_drvdata(pdev, dev); -+ dev->dev = &pdev->dev; -+ dev->pfdev = pdev; -+ dev->info = &ddb_octonet; -+ -+ mutex_init(&dev->mutex); -+ regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ dev->regs_len = (regs->end - regs->start) + 1; -+ dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n", -+ (u32) regs->start, (u32) dev->regs_len); -+ dev->regs = ioremap(regs->start, dev->regs_len); -+ if (!dev->regs) { -+ dev_err(dev->dev, "ioremap failed\n"); -+ return -ENOMEM; -+ } -+ -+ dev->ids.hwid = ddbreadl(dev, 0); -+ dev->ids.regmapid = ddbreadl(dev, 4); -+ dev->ids.devid = ddbreadl(dev, 8); -+ dev->ids.mac = ddbreadl(dev, 12); -+ -+ dev->ids.vendor = dev->ids.devid & 0xffff; -+ dev->ids.device = dev->ids.devid >> 16; -+ dev->ids.subvendor = dev->ids.devid & 0xffff; -+ dev->ids.subdevice = dev->ids.devid >> 16; -+ -+ pr_info("HW %08x REGMAP %08x\n", dev->ids.hwid, dev->ids.regmapid); -+ pr_info("MAC %08x DEVID %08x\n", dev->ids.mac, dev->ids.devid); -+ -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS); -+ for (i = 0; i < 16; i++) -+ ddbwritel(dev, 0x00, TS_OUTPUT_CONTROL(i)); -+ usleep_range(5000, 6000); -+ -+ if (request_irq(platform_get_irq(dev->pfdev, 0), irq_handler, -+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, -+ "octonet-dvb", (void *) dev) < 0) -+ goto fail; -+ -+ ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0x1, ETHER_CONTROL); -+ ddbwritel(dev, 14 + (vlan ? 4 : 0), ETHER_LENGTH); -+ -+ -+ mutex_init(&dev->octonet_i2c_lock); -+ if (ddb_i2c_init(dev) < 0) -+ goto fail1; -+ -+ ddb_ports_init(dev); -+ if (ddb_ports_attach(dev) < 0) -+ goto fail3; -+ -+ ddb_nsd_attach(dev); -+ -+ ddb_device_create(dev); -+ -+ return 0; -+ -+fail3: -+ ddb_ports_detach(dev); -+ dev_err(dev->dev, "fail3\n"); -+fail1: -+ dev_err(dev->dev, "fail1\n"); -+fail: -+ dev_err(dev->dev, "fail\n"); -+ ddbwritel(dev, 0, ETHER_CONTROL); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); -+ octonet_unmap(dev); -+ platform_set_drvdata(pdev, 0); -+ return 0; -+} -+ -+static struct platform_driver octonet_driver = { -+ .remove = __exit_p(octonet_remove), -+ .probe = octonet_probe, -+ .driver = { -+ .name = "octonet-dvb", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static __init int init_octonet(void) -+{ -+ int res; -+ -+ pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION -+ ", Copyright (C) 2010-14 Digital Devices GmbH\n"); -+ res = ddb_class_create(); -+ if (res) -+ return res; -+ res = platform_driver_probe(&octonet_driver, octonet_probe); -+ if (res) { -+ ddb_class_destroy(); -+ return res; -+ } -+ return 0; -+} -+ -+static __exit void exit_octonet(void) -+{ -+ platform_driver_unregister(&octonet_driver); -+ ddb_class_destroy(); -+} -+ -+module_init(init_octonet); -+module_exit(exit_octonet); -+ -+MODULE_DESCRIPTION("GPL"); -+MODULE_AUTHOR("Marcus and Ralph Metzler, Metzler Brothers Systementwicklung"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("0.5"); -diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig -index 637d506..3896c12 100644 ---- a/drivers/media/pci/ngene/Kconfig -+++ b/drivers/media/pci/ngene/Kconfig -@@ -1,12 +1,16 @@ - config DVB_NGENE - tristate "Micronas nGene support" - depends on DVB_CORE && PCI && I2C -+ select DVB_CXD2099 - select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT - select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT - select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT - select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_STV0367DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_TDA18212DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_CXD2843 if MEDIA_SUBDRV_AUTOSELECT - select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT - ---help--- - Support for Micronas PCI express cards with nGene bridge. -diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile -index 5c0b5d6..42c036a 100644 ---- a/drivers/media/pci/ngene/Makefile -+++ b/drivers/media/pci/ngene/Makefile -@@ -2,7 +2,8 @@ - # Makefile for the nGene device driver - # - --ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o -+ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-av.o \ -+ ngene-eeprom.o ngene-dvb.o - - obj-$(CONFIG_DVB_NGENE) += ngene.o - -diff --git a/drivers/media/pci/ngene/ngene-av.c b/drivers/media/pci/ngene/ngene-av.c -new file mode 100644 -index 0000000..a86459e ---- /dev/null -+++ b/drivers/media/pci/ngene/ngene-av.c -@@ -0,0 +1,348 @@ -+/* -+ * ngene-av.c: nGene PCIe bridge driver - DVB video/audio support -+ * -+ * Copyright (C) 2005-2007 Micronas -+ * -+ * Copyright (C) 2008-2009 Ralph Metzler -+ * Modifications for new nGene firmware, -+ * support for EEPROM-copying, -+ * support for new dual DVB-S2 card prototype -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/* This file provides the support functions for DVB audio/video devices -+ (/dev/dvb/adapter0/[video|audio]), not to be confused with V4L2 support */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ngene.h" -+ -+#if 0 -+ -+static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -+{ -+ struct ngene_channel *chan = priv; -+ struct ngene *dev = chan->dev; -+ -+ if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { -+ dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); -+ wake_up_interruptible(&dev->ain_rbuf.queue); -+ } else -+ printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); -+ -+ return 0; -+} -+ -+static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -+{ -+ -+ struct ngene_channel *chan = priv; -+ struct ngene *dev = chan->dev; -+ -+ if (len >= 1920 * 1080) -+ len = 1920 * 1080; -+ if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { -+ dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); -+ wake_up_interruptible(&dev->vin_rbuf.queue); -+ } else { -+ ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ -+ } -+ return 0; -+} -+ -+static ssize_t audio_write(struct file *file, -+ const char *buf, size_t count, loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left; -+ int avail; -+ -+ left = count; -+ while (left) { -+ if (wait_event_interruptible( -+ dev->ain_rbuf.queue, -+ dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) -+ return -EAGAIN; -+ avail = dvb_ringbuffer_avail(&dev->ain_rbuf); -+ if (avail > left) -+ avail = left; -+ dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+static int audio_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan2 = &chan->dev->channel[2]; -+ int ret; -+ -+ ret = dvb_generic_open(inode, file); -+ if (ret < 0) -+ return ret; -+ dvb_ringbuffer_flush(&dev->ain_rbuf); -+ -+ chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; -+ chan2->pBufferExchange = ain_exchange; -+ ngene_command_stream_control(chan2->dev, chan2->number, 0x80, -+ SMODE_AUDIO_CAPTURE, 0); -+ return ret; -+} -+ -+static int audio_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan2 = &chan->dev->channel[2]; -+ -+ ngene_command_stream_control(dev, 2, 0, 0, 0); -+ chan2->pBufferExchange = 0; -+ -+ return dvb_generic_release(inode, file); -+} -+ -+static const struct file_operations audio_fops = { -+ .owner = THIS_MODULE, -+ .read = audio_read, -+ .write = audio_write, -+ .open = audio_open, -+ .release = audio_release, -+}; -+ -+static struct dvb_device dvbdev_audio = { -+ .priv = 0, -+ .readers = -1, -+ .writers = 1, -+ .users = 1, -+ .fops = &audio_fops, -+}; -+ -+static int video_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan0 = &chan->dev->channel[0]; -+ int ret; -+ -+ ret = dvb_generic_open(inode, file); -+ if (ret < 0) -+ return ret; -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) -+ return ret; -+ dvb_ringbuffer_flush(&dev->vin_rbuf); -+ -+ chan0->nBytesPerLine = 1920 * 2; -+ chan0->nLines = 540; -+ chan0->Capture1Length = 1920 * 2 * 540; -+ chan0->pBufferExchange = vcap_exchange; -+ chan0->itumode = 2; -+ ngene_command_stream_control(chan0->dev, chan0->number, -+ 0x80, SMODE_VIDEO_CAPTURE, 0); -+ return ret; -+} -+ -+static int video_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan0 = &chan->dev->channel[0]; -+ -+ ngene_command_stream_control(dev, 0, 0, 0, 0); -+ chan0->pBufferExchange = 0; -+ -+ return dvb_generic_release(inode, file); -+} -+ -+static ssize_t video_write(struct file *file, -+ const char *buf, size_t count, loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left, avail; -+ -+ left = count; -+ while (left) { -+ if (wait_event_interruptible( -+ dev->vin_rbuf.queue, -+ dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) -+ return -EAGAIN; -+ avail = dvb_ringbuffer_avail(&dev->vin_rbuf); -+ if (avail > left) -+ avail = left; -+ dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+/* Why is this not exported from dvb_core ?!?! */ -+ -+static int dvb_usercopy2(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg, -+ int (*func)(struct inode *inode, struct file *file, -+ unsigned int cmd, void *arg)) -+{ -+ char sbuf[128]; -+ void *mbuf = NULL; -+ void *parg = NULL; -+ int err = -EINVAL; -+ -+ /* Copy arguments into temp kernel buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_NONE: -+ /* -+ * For this command, the pointer is actually an integer -+ * argument. -+ */ -+ parg = (void *)arg; -+ break; -+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -+ case _IOC_WRITE: -+ case (_IOC_WRITE | _IOC_READ): -+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -+ parg = sbuf; -+ } else { -+ /* too big to allocate from stack */ -+ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); -+ if (NULL == mbuf) -+ return -ENOMEM; -+ parg = mbuf; -+ } -+ -+ err = -EFAULT; -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto out; -+ break; -+ } -+ -+ /* call driver */ -+ err = func(inode, file, cmd, parg); -+ if (err == -ENOIOCTLCMD) -+ err = -EINVAL; -+ -+ if (err < 0) -+ goto out; -+ -+ /* Copy results into user buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_READ: -+ case (_IOC_WRITE | _IOC_READ): -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ break; -+ } -+ -+out: -+ kfree(mbuf); -+ return err; -+} -+ -+static int video_do_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int ret = 0; -+ unsigned long arg = (unsigned long)parg; -+ -+ switch (cmd) { -+ case VIDEO_SET_STREAMTYPE: -+ switch (arg) { -+ case VIDEO_CAP_MPEG2: -+ /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ -+ send_cli(dev, "vdec mpeg2\n"); -+ break; -+ case VIDEO_CAP_AVC: -+ /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ -+ send_cli(dev, "vdec h264\n"); -+ break; -+ case VIDEO_CAP_VC1: -+ /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ -+ send_cli(dev, "vdec vc1\n"); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ break; -+ default: -+ ret = -ENOIOCTLCMD; -+ return -EINVAL; -+ } -+ return ret; -+} -+ -+static int video_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); -+} -+ -+static const struct file_operations video_fops = { -+ .owner = THIS_MODULE, -+ .read = video_read, -+ .write = video_write, -+ .open = video_open, -+ .release = video_release, -+ .ioctl = video_ioctl, -+}; -+ -+static struct dvb_device dvbdev_video = { -+ .priv = 0, -+ .readers = -1, -+ .writers = 1, -+ .users = -1, -+ .fops = &video_fops, -+}; -+#endif -diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c -index 039bed3..a8a1a03 100644 ---- a/drivers/media/pci/ngene/ngene-cards.c -+++ b/drivers/media/pci/ngene/ngene-cards.c -@@ -42,8 +42,18 @@ - #include "mt2131.h" - #include "tda18271c2dd.h" - #include "drxk.h" --#include "drxd.h" --#include "dvb-pll.h" -+#include "tda18212dd.h" -+#include "stv0367dd.h" -+#include "cxd2843.h" -+ -+ -+enum DEMOD_TYPE { -+ DMD_NONE = 0, -+ DMD_STV0900, -+ DMD_DRXK, -+ DMD_STV0367, -+ DMD_CXD28xx, -+}; - - - /****************************************************************************/ -@@ -86,8 +96,98 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) - return 0; - } - -+#if 0 -+static int tuner_attach_mt2060(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ void *tconf = dev->card_info->tuner_config[chan->number]; -+ u8 drxa = dev->card_info->demoda[chan->number]; -+ struct dvb_frontend *fe = chan->fe, *fe2; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ fe->misc_priv = chan; -+#else -+ fe->sec_priv = chan; -+#endif -+ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; -+ -+ dev->card_info->gate_ctrl(fe, 1); -+ fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); -+ dev->card_info->gate_ctrl(fe, 0); -+ -+ i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); -+ write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); -+ write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); -+ write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); -+ -+ return fe2 ? 0 : -ENODEV; -+} -+ -+static int tuner_attach_xc3028(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ void *tconf = dev->card_info->tuner_config[chan->number]; -+ struct dvb_frontend *fe = chan->fe, *fe2; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ fe->misc_priv = chan; -+#else -+ fe->sec_priv = chan; -+#endif -+ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; -+ -+ dev->card_info->gate_ctrl(fe, 1); -+ fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); -+ dev->card_info->gate_ctrl(fe, 0); -+ -+ /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ -+ -+ return fe2 ? 0 : -ENODEV; -+} -+ -+static int demod_attach_drxd(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = drxd_attach(feconf, -+ chan, &chan->i2c_adapter, -+ &chan->dev->pci_dev->dev); -+ return (chan->fe) ? 0 : -ENODEV; -+} -+ -+static int demod_attach_drxh(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = drxh_attach(feconf, chan, -+ &chan->i2c_adapter, &chan->dev->pci_dev->dev); -+ return (chan->fe) ? 0 : -ENODEV; -+} -+ -+static int demod_attach_stb0899(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = stb0899_attach(feconf, -+ chan, &chan->i2c_adapter, -+ &chan->dev->pci_dev->dev); -+ if (chan->fe) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -+ chan->set_tone = chan->fe->ops->set_tone; -+ chan->fe->ops->set_tone = lnbh21_set_tone; -+ chan->fe->ops->set_voltage = lnbh21_set_voltage; -+#else -+ chan->set_tone = chan->fe->ops.set_tone; -+ chan->fe->ops.set_tone = lnbh21_set_tone; -+ chan->fe->ops.set_voltage = lnbh21_set_voltage; -+#endif -+ } -+ -+ return (chan->fe) ? 0 : -ENODEV; -+} -+#endif - --static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct ngene_channel *chan = fe->sec_priv; - int status; -@@ -121,12 +221,41 @@ static int tuner_attach_tda18271(struct ngene_channel *chan) - return 0; - } - -+static int tuner_attach_tda18212dd(struct ngene_channel *chan) -+{ -+ struct i2c_adapter *i2c; -+ struct dvb_frontend *fe; -+ u8 addr = (chan->number & 1) ? 0x63 : 0x60; -+ -+ if (chan->demod_type == DMD_CXD28xx && chan->number < 2) -+ addr ^= 0x04; -+ i2c = &chan->dev->channel[0].i2c_adapter; -+ fe = dvb_attach(tda18212dd_attach, chan->fe, i2c, addr); -+ if (!fe) { -+ printk(KERN_ERR "No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+ - static int tuner_attach_probe(struct ngene_channel *chan) - { -- if (chan->demod_type == 0) -+ switch(chan->demod_type) -+ { -+ case DMD_STV0900: - return tuner_attach_stv6110(chan); -- if (chan->demod_type == 1) -+ -+ case DMD_DRXK: - return tuner_attach_tda18271(chan); -+ -+ case DMD_STV0367: -+ case DMD_CXD28xx: -+ return tuner_attach_tda18212dd(chan); -+ -+ default: -+ pr_err("Unknown demod %x\n", chan->demod_type); -+ break; -+ } - return -EINVAL; - } - -@@ -184,6 +313,26 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) - return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; - } - -+static int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, -+ u8 reg, u8 *val) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1} }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ - static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, - u16 reg, u8 *val) - { -@@ -195,6 +344,15 @@ static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, - return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; - } - -+static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, -+ u8 reg, u8 val) -+{ -+ u8 msg[2] = {reg, val}; -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2 } }; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ - static int port_has_stv0900(struct i2c_adapter *i2c, int port) - { - u8 val; -@@ -218,18 +376,154 @@ static int demod_attach_drxk(struct ngene_channel *chan, - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -- config.microcode_name = "drxk_a3.mc"; -- config.qam_demod_parameter_count = 4; - config.adr = 0x29 + (chan->number ^ 2); -+ config.microcode_name = "drxk_a3.mc"; - -+#ifdef USE_API3 -+ chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2); -+#else - chan->fe = dvb_attach(drxk_attach, &config, i2c); -+#endif - if (!chan->fe) { - printk(KERN_ERR "No DRXK found!\n"); - return -ENODEV; - } - chan->fe->sec_priv = chan; - chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; -- chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int port_has_stv0367(struct i2c_adapter *i2c, int port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(i2c, 0x1c + (port ^ 1), 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ return 1; -+} -+ -+static int demod_attach_stv0367dd(struct ngene_channel *chan, -+ struct i2c_adapter *i2c) -+{ -+ struct stv0367_cfg cfg; -+ -+ memset(&cfg, 0, sizeof cfg); -+ cfg.adr = 0x1c + (chan->number ^ 1); -+ -+ chan->fe = dvb_attach(stv0367_attach, i2c, &cfg, &chan->fe2); -+ if (!chan->fe) { -+ printk(KERN_ERR "No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ chan->fe->sec_priv = chan; -+ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; -+ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int port_has_xo2(struct i2c_adapter *i2c, int port, u8 *id) -+{ -+ u8 addr = (port < 2) ? 0x14 : 0x10; -+ u8 val; -+ u8 probe[1] = { 0x00 }, data[4]; -+ struct i2c_msg msgs[2] = {{ .addr = addr, .flags = 0, -+ .buf = probe, .len = 1 }, -+ { .addr = addr, .flags = I2C_M_RD, -+ .buf = data, .len = 4 } }; -+#if 0 -+ u8 cfg[] = { 0x79, 0x00, 0x00 }; -+ struct i2c_msg cmsg = { .addr = 0x44, .flags = 0, -+ .buf = cfg, .len = 3 }; -+ if (port == 0) -+ i2c_transfer(i2c, &cmsg, 1); -+ pr_info("chan %d addr %x\n", port, addr); -+ msleep(1000); -+#endif -+ val = i2c_transfer(i2c, msgs, 2); -+ if (val != 2) -+ return 0; -+ -+ if (data[0] != 'D' || data[1] != 'F') -+ return 0; -+ -+ *id = data[2]; -+ return 1; -+} -+ -+static int init_xo2(struct i2c_adapter *i2c, int port) -+{ -+ u8 addr = (port < 2) ? 0x14 : 0x10; -+ u8 val, data[2]; -+ int res; -+ -+ if (port & 1) -+ return 0; -+ -+ res = i2c_read_regs(i2c, addr, 0x04, data, 2); -+ if (res < 0) -+ return res; -+ -+ if (data[0] != 0x01) { -+ pr_info("Invalid XO2\n"); -+ return -1; -+ } -+ -+ i2c_read_reg(i2c, addr, 0x08, &val); -+ if (val != 0) { -+ i2c_write_reg(i2c, addr, 0x08, 0x00); -+ msleep(100); -+ } -+ /* Enable tuner power, disable pll, reset demods */ -+ i2c_write_reg(i2c, addr, 0x08, 0x04); -+ usleep_range(2000, 3000); -+ /* Release demod resets */ -+ i2c_write_reg(i2c, addr, 0x08, 0x07); -+ usleep_range(2000, 3000); -+ /* Start XO2 PLL */ -+ i2c_write_reg(i2c, addr, 0x08, 0x87); -+ -+ return 0; -+} -+ -+#define DDB_TUNER_XO2 16 -+#define DDB_TUNER_DVBS_STV0910 16 -+#define DDB_TUNER_DVBCT2_SONY 17 -+#define DDB_TUNER_ISDBT_SONY 18 -+#define DDB_TUNER_DVBC2T2_SONY 19 -+#define DDB_TUNER_ATSC_ST 20 -+#define DDB_TUNER_DVBC2T2_ST 21 -+ -+static char *xo2names[] = { -+ "DUAL DVB-S2", -+ "DUAL DVB-C/T/T2", -+ "DUAL DVB-ISDBT", -+ "DUAL DVB-C/C2/T/T2", -+ "DUAL ATSC", -+ "DUAL DVB-C/C2/T/T2", -+ "", "" -+}; -+ -+struct cxd2843_cfg cxd2843[] = { -+ { .adr = 0x68, }, -+ { .adr = 0x69, }, -+ { .adr = 0x6c, }, -+ { .adr = 0x6d, }, -+}; -+ -+static int demod_attach_cxd2843(struct ngene_channel *chan, -+ struct i2c_adapter *i2c) -+{ -+ chan->fe = dvb_attach(cxd2843_attach, i2c, cxd2843+chan->number); -+ if (!chan->fe) { -+ pr_err("No cxd2837/38/43 found!\n"); -+ return -ENODEV; -+ } -+ chan->fe->sec_priv = chan; -+ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; -+ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; - return 0; - } - -@@ -240,6 +534,7 @@ static int cineS2_probe(struct ngene_channel *chan) - u8 buf[3]; - struct i2c_msg i2c_msg = { .flags = 0, .buf = buf }; - int rc; -+ u8 id; - - /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ - if (chan->number < 2) -@@ -247,8 +542,33 @@ static int cineS2_probe(struct ngene_channel *chan) - else - i2c = &chan->dev->channel[1].i2c_adapter; - -- if (port_has_stv0900(i2c, chan->number)) { -- chan->demod_type = 0; -+ if (port_has_xo2(i2c, chan->number, &id)) { -+ id >>= 2; -+ if (id > 5) { -+ pr_info("Channel %d: Unknown XO2 DuoFlex %u\n", -+ chan->number, id); -+ return -ENODEV; -+ } -+ init_xo2(i2c, chan->number); -+ switch(DDB_TUNER_XO2 + id) -+ { -+ case DDB_TUNER_DVBCT2_SONY: -+ case DDB_TUNER_ISDBT_SONY: -+ case DDB_TUNER_DVBC2T2_SONY: -+ chan->demod_type = DMD_CXD28xx; -+ pr_info("Channel %d: %s\n", chan->number, xo2names[id]); -+ demod_attach_cxd2843(chan, i2c); -+ break; -+ default: -+ pr_info("Channel %d: %s not supported yet\n", -+ chan->number, xo2names[id]); -+ return -ENODEV; -+ } -+ -+ } else if (chan->dev->channel[0].demod_type != DMD_CXD28xx && -+ port_has_stv0900(i2c, chan->number)) { -+ chan->demod_type = DMD_STV0900; -+ pr_info("Channel %d: STV0900\n", chan->number); - fe_conf = chan->dev->card_info->fe_config[chan->number]; - /* demod found, attach it */ - rc = demod_attach_stv0900(chan); -@@ -276,9 +596,17 @@ static int cineS2_probe(struct ngene_channel *chan) - printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n"); - return -EIO; - } -+ - } else if (port_has_drxk(i2c, chan->number^2)) { -- chan->demod_type = 1; -+ chan->demod_type = DMD_DRXK; -+ pr_info("Channel %d: DRXK\n", chan->number); - demod_attach_drxk(chan, i2c); -+ -+ } else if (port_has_stv0367(i2c, chan->number)) { -+ chan->demod_type = DMD_STV0367; -+ pr_info("Channel %d: STV0367\n", chan->number); -+ demod_attach_stv0367dd(chan, i2c); -+ - } else { - printk(KERN_ERR "No demod found on chan %d\n", chan->number); - return -ENODEV; -@@ -315,249 +643,140 @@ static int demod_attach_lg330x(struct ngene_channel *chan) - return (chan->fe) ? 0 : -ENODEV; - } - --static int demod_attach_drxd(struct ngene_channel *chan) --{ -- struct drxd_config *feconf; -- -- feconf = chan->dev->card_info->fe_config[chan->number]; -- -- chan->fe = dvb_attach(drxd_attach, feconf, chan, -- &chan->i2c_adapter, &chan->dev->pci_dev->dev); -- if (!chan->fe) { -- pr_err("No DRXD found!\n"); -- return -ENODEV; -- } -- return 0; --} -+/****************************************************************************/ -+/* Switch control (I2C gates, etc.) *****************************************/ -+/****************************************************************************/ - --static int tuner_attach_dtt7520x(struct ngene_channel *chan) -+#if 0 -+static int avf_output(struct ngene_channel *chan, int state) - { -- struct drxd_config *feconf; -- -- feconf = chan->dev->card_info->fe_config[chan->number]; -- -- if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, -- &chan->i2c_adapter, -- feconf->pll_type)) { -- pr_err("No pll(%d) found!\n", feconf->pll_type); -- return -ENODEV; -- } -+ if (chan->dev->card_info->avf[chan->number]) -+ i2c_write_register(&chan->i2c_adapter, -+ chan->dev->card_info->avf[chan->number], -+ 0xf2, state ? 0x89 : 0x80); - return 0; - } - --/****************************************************************************/ --/* EEPROM TAGS **************************************************************/ --/****************************************************************************/ -- --#define MICNG_EE_START 0x0100 --#define MICNG_EE_END 0x0FF0 -- --#define MICNG_EETAG_END0 0x0000 --#define MICNG_EETAG_END1 0xFFFF -- --/* 0x0001 - 0x000F reserved for housekeeping */ --/* 0xFFFF - 0xFFFE reserved for housekeeping */ -- --/* Micronas assigned tags -- EEProm tags for hardware support */ -- --#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ --#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ -- --#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ --#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ -+/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ - --/* Tag range for OEMs */ -+static int exp_set(struct ngene *dev) -+{ -+ return i2c_write(&dev->channel[0].i2c_adapter, -+ dev->card_info->exp, dev->exp_val); -+} - --#define MICNG_EETAG_OEM_FIRST 0xC000 --#define MICNG_EETAG_OEM_LAST 0xFFEF -+static int exp_init(struct ngene *dev) -+{ -+ if (!dev->card_info->exp) -+ return 0; -+ dev->exp_val = dev->card_info->exp_init; -+ return exp_set(dev); -+} - --static int i2c_write_eeprom(struct i2c_adapter *adapter, -- u8 adr, u16 reg, u8 data) -+static int exp_set_bit(struct ngene *dev, int bit, int val) - { -- u8 m[3] = {(reg >> 8), (reg & 0xff), data}; -- struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, -- .len = sizeof(m)}; -+ if (val) -+ set_bit(bit, &dev->exp_val); -+ else -+ clear_bit(bit, &dev->exp_val); -+ return exp_set(dev); -+} - -- if (i2c_transfer(adapter, &msg, 1) != 1) { -- pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); -- return -EIO; -+static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) -+{ -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ return exp_set_bit(chan->dev, 4 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return exp_set_bit(chan->dev, 6 + chan->number, val); -+ case 2: /* Input: 0=digital 1=analog antenna input */ -+ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); -+ exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); -+ break; - } - return 0; - } - --static int i2c_read_eeprom(struct i2c_adapter *adapter, -- u8 adr, u16 reg, u8 *data, int len) -+static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) - { -- u8 msg[2] = {(reg >> 8), (reg & 0xff)}; -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = msg, .len = 2 }, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = data, .len = len} }; -- -- if (i2c_transfer(adapter, msgs, 2) != 2) { -- pr_err(DEVICE_NAME ": Error reading EEPROM\n"); -- return -EIO; -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ return exp_set_bit(chan->dev, 4 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return exp_set_bit(chan->dev, 6 + chan->number, val); -+ case 2: /* Input: 0=digital 1=analog antenna input */ -+ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); -+ exp_set_bit(chan->dev, 1 + chan->number * 2, 0); -+ break; - } - return 0; - } - --static int ReadEEProm(struct i2c_adapter *adapter, -- u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) -+static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) - { -- int status = 0; -- u16 Addr = MICNG_EE_START, Length, tag = 0; -- u8 EETag[3]; -- -- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -- return -1; -- tag = (EETag[0] << 8) | EETag[1]; -- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -- return -1; -- if (tag == Tag) -- break; -- Addr += sizeof(u16) + 1 + EETag[2]; -- } -- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -- pr_err(DEVICE_NAME -- ": Reached EOEE @ Tag = %04x Length = %3d\n", -- tag, EETag[2]); -- return -1; -- } -- Length = EETag[2]; -- if (Length > MaxLen) -- Length = (u16) MaxLen; -- if (Length > 0) { -- Addr += sizeof(u16) + 1; -- status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); -- if (!status) { -- *pLength = EETag[2]; --#if 0 -- if (Length < EETag[2]) -- status = STATUS_BUFFER_OVERFLOW; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else /* Why is there no misc_priv available anymore !?!?! */ -+ /* Well, just abuse sec :-) */ -+ struct ngene_channel *chan = fe->sec_priv; - #endif -- } -- } -- return status; -+ struct ngene *dev = chan->dev; -+ -+ return dev->card_info->switch_ctrl(chan, 0, enable); - } - --static int WriteEEProm(struct i2c_adapter *adapter, -- u16 Tag, u32 Length, u8 *data) -+static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) - { -- int status = 0; -- u16 Addr = MICNG_EE_START; -- u8 EETag[3]; -- u16 tag = 0; -- int retry, i; -- -- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -- return -1; -- tag = (EETag[0] << 8) | EETag[1]; -- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -- return -1; -- if (tag == Tag) -- break; -- Addr += sizeof(u16) + 1 + EETag[2]; -- } -- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -- pr_err(DEVICE_NAME -- ": Reached EOEE @ Tag = %04x Length = %3d\n", -- tag, EETag[2]); -- return -1; -- } -- -- if (Length > EETag[2]) -- return -EINVAL; -- /* Note: We write the data one byte at a time to avoid -- issues with page sizes. (which are different for -- each manufacture and eeprom size) -- */ -- Addr += sizeof(u16) + 1; -- for (i = 0; i < Length; i++, Addr++) { -- status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); -- -- if (status) -- break; -- -- /* Poll for finishing write cycle */ -- retry = 10; -- while (retry) { -- u8 Tmp; -- -- msleep(50); -- status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); -- if (status) -- break; -- if (Tmp != data[i]) -- pr_err(DEVICE_NAME -- "eeprom write error\n"); -- retry -= 1; -- } -- if (status) { -- pr_err(DEVICE_NAME -- ": Timeout polling eeprom\n"); -- break; -- } -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ if (chan->number > 1) -+ return -EINVAL; -+ return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return 0; - } -- return status; -+ return 0; - } - --static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) -+static int viper_reset_xc(struct dvb_frontend *fe) - { -- int stat; -- u8 buf[2]; -- u32 len = 0; -- -- stat = ReadEEProm(adapter, tag, 2, buf, &len); -- if (stat) -- return stat; -- if (len != 2) -- return -EINVAL; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else -+ struct ngene_channel *chan = fe->sec_priv; -+#endif -+ struct ngene *dev = chan->dev; - -- *data = (buf[0] << 8) | buf[1]; -- return 0; --} -+ printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); - --static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) --{ -- int stat; -- u8 buf[2]; -+ if (chan->number > 1) -+ return -EINVAL; - -- buf[0] = data >> 8; -- buf[1] = data & 0xff; -- stat = WriteEEProm(adapter, tag, 2, buf); -- if (stat) -- return stat; -+ ngene_command_gpio_set(dev, 3 + chan->number, 0); -+ msleep(150); -+ ngene_command_gpio_set(dev, 3 + chan->number, 1); - return 0; - } - --static s16 osc_deviation(void *priv, s16 deviation, int flag) -+static int python_gate_ctrl(struct dvb_frontend *fe, int enable) - { -- struct ngene_channel *chan = priv; -- struct i2c_adapter *adap = &chan->i2c_adapter; -- u16 data = 0; -- -- if (flag) { -- data = (u16) deviation; -- pr_info(DEVICE_NAME ": write deviation %d\n", -- deviation); -- eeprom_write_ushort(adap, 0x1000 + chan->number, data); -- } else { -- if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) -- data = 0; -- pr_info(DEVICE_NAME ": read deviation %d\n", -- (s16) data); -- } -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else /* Why is there no misc_priv available anymore !?!?! */ -+ struct ngene_channel *chan = fe->sec_priv; -+#endif -+ struct ngene *dev = chan->dev; - -- return (s16) data; -+ if (chan->number == 0) -+ return ngene_command_gpio_set(dev, 3, enable); -+ if (chan->number == 1) -+ return ngene_command_gpio_set(dev, 4, enable); -+ return -EINVAL; - } -- --/****************************************************************************/ --/* Switch control (I2C gates, etc.) *****************************************/ --/****************************************************************************/ -- -+#endif - - static struct stv090x_config fe_cineS2 = { - .device = STV0900, -@@ -696,7 +915,7 @@ static struct ngene_info ngene_info_m780 = { - .demod_attach = { NULL, demod_attach_lg330x }, - - /* Ensure these are NULL else the frame will call them (as funcs) */ -- .tuner_attach = { NULL, NULL, NULL, NULL }, -+ .tuner_attach = { 0, 0, 0, 0 }, - .fe_config = { NULL, &aver_m780 }, - .avf = { 0 }, - -@@ -705,14 +924,18 @@ static struct ngene_info ngene_info_m780 = { - .fw_version = 15, - }; - -+/****************************************************************************/ -+ -+#if 0 - static struct drxd_config fe_terratec_dvbt_0 = { - .index = 0, - .demod_address = 0x70, - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, -- .pll_type = DVB_PLL_THOMSON_DTT7520X, -+ .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, -+ .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, - }; - -@@ -722,8 +945,9 @@ static struct drxd_config fe_terratec_dvbt_1 = { - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, -- .pll_type = DVB_PLL_THOMSON_DTT7520X, -+ .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, -+ .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, - }; - -@@ -732,13 +956,293 @@ static struct ngene_info ngene_info_terratec = { - .name = "Terratec Integra/Cinergy2400i Dual DVB-T", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -- .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, - .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, - .i2c_access = 1, - }; - - /****************************************************************************/ - -+static struct mt2060_config tuner_python_0 = { -+ .i2c_address = 0x60, -+ .clock_out = 3, -+ .input = 0 -+}; -+ -+static struct mt2060_config tuner_python_1 = { -+ .i2c_address = 0x61, -+ .clock_out = 3, -+ .input = 1 -+}; -+ -+static struct drxd_config fe_python_0 = { -+ .index = 0, -+ .demod_address = 0x71, -+ .demod_revision = 0xb1, -+ .demoda_address = 0x41, -+ .clock = 16000, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct drxd_config fe_python_1 = { -+ .index = 1, -+ .demod_address = 0x70, -+ .demod_revision = 0xb1, -+ .demoda_address = 0x45, -+ .clock = 16000, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct ngene_info ngene_info_python = { -+ .type = NGENE_PYTHON, -+ .name = "Micronas MicPython/Hedgehog Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, -+ .fe_config = {&fe_python_0, &fe_python_1}, -+ .tuner_config = {&tuner_python_0, &tuner_python_1}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .demoda = {0x41, 0x45}, -+ .gate_ctrl = python_gate_ctrl, -+ .switch_ctrl = python_switch_ctrl, -+}; -+ -+/****************************************************************************/ -+ -+static struct drxd_config fe_appb_dvbt_0 = { -+ .index = 0, -+ .demod_address = 0x71, -+ .demod_revision = 0xa2, -+ .demoda_address = 0x41, -+ .pll_address = 0x63, -+ .pll_type = DRXD_PLL_MT3X0823, -+ .clock = 20000, -+ .pll_set = ngene_pll_set_mt_3x0823, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct drxd_config fe_appb_dvbt_1 = { -+ .index = 1, -+ .demod_address = 0x70, -+ .demod_revision = 0xa2, -+ .demoda_address = 0x45, -+ .pll_address = 0x60, -+ .pll_type = DRXD_PLL_MT3X0823, -+ .clock = 20000, -+ .pll_set = ngene_pll_set_mt_3x0823, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct ngene_info ngene_info_appboard = { -+ .type = NGENE_APP, -+ .name = "Micronas Application Board Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, -+ .avf = {0x43, 0x47}, -+}; -+ -+static struct ngene_info ngene_info_appboard_ntsc = { -+ .type = NGENE_APP, -+ .name = "Micronas Application Board Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, -+ .avf = {0x43, 0x47}, -+ .ntsc = 1, -+}; -+ -+/****************************************************************************/ -+ -+static struct stb0899_config fe_sidewinder_0 = { -+ .demod_address = 0x68, -+ .pll_address = 0x63, -+}; -+ -+static struct stb0899_config fe_sidewinder_1 = { -+ .demod_address = 0x6b, -+ .pll_address = 0x60, -+}; -+ -+static struct ngene_info ngene_info_sidewinder = { -+ .type = NGENE_SIDEWINDER, -+ .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, -+ .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, -+ .lnb = {0x0b, 0x08}, -+}; -+ -+/****************************************************************************/ -+/* Yet unnamed S2 card with dual DVB-S2 demod */ -+/****************************************************************************/ -+ -+static struct stv0900_config fe_s2_0 = { -+ .addr = 0x68, -+ .pll = 0x63, -+ .pll_type = 0, -+ .nr = 0, -+}; -+ -+static struct stv0900_config fe_s2_1 = { -+ .addr = 0x68, -+ .pll = 0x60, -+ .pll_type = 0, -+ .nr = 1, -+}; -+ -+static struct ngene_info ngene_info_s2 = { -+ .type = NGENE_SIDEWINDER, -+ .name = "S2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, -+ NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, -+ .fe_config = {&fe_s2_0, &fe_s2_1}, -+ .lnb = {0x0b, 0x08}, -+ .tsf = {3, 3}, -+ .fw_version = 15, -+}; -+ -+static struct stv0900_config fe_s2b_0 = { -+ .addr = 0x68, -+ .pll = 0x60, -+ .pll_type = 0x10, -+ .nr = 0, -+}; -+ -+static struct stv0900_config fe_s2b_1 = { -+ .addr = 0x68, -+ .pll = 0x63, -+ .pll_type = 0x10, -+ .nr = 1, -+}; -+ -+static struct ngene_info ngene_info_s2_b = { -+ .type = NGENE_SIDEWINDER, -+ .name = "S2 V2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, -+ NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, -+ .fe_config = {&fe_s2b_0, &fe_s2b_1}, -+ .lnb = {0x0b, 0x08}, -+ .tsf = {3, 3}, -+ .fw_version = 17, -+}; -+ -+/****************************************************************************/ -+ -+static struct xc3028_config tuner_viper_0 = { -+ .adr = 0x61, -+ .reset = viper_reset_xc -+}; -+ -+static struct xc3028_config tuner_viper_1 = { -+ .adr = 0x64, -+ .reset = viper_reset_xc -+}; -+ -+static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; -+ -+static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; -+ -+static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; -+ -+static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; -+ -+static struct ngene_info ngene_info_viper_v1 = { -+ .type = NGENE_VIPER, -+ .name = "Micronas MicViper Dual ATSC DRXH", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+static struct ngene_info ngene_info_viper_v2 = { -+ .type = NGENE_VIPER, -+ .name = "Micronas MicViper Dual ATSC DRXL", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x38, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_vbox_v1 = { -+ .type = NGENE_VBOX_V1, -+ .name = "VBox Cat's Eye 164E", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_vbox_v2 = { -+ .type = NGENE_VBOX_V2, -+ .name = "VBox Cat's Eye 164E", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl2, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_racer = { -+ .type = NGENE_RACER, -+ .name = "Micronas MicRacer HDTV Decoder Card", -+ .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, -+ NGENE_IO_AIN, NGENE_IO_NONE, -+ NGENE_IO_TSOUT}, -+ .i2s = {0, 0, 1, 0}, -+ .fw_version = 17, -+}; -+#endif - - - /****************************************************************************/ -@@ -753,6 +1257,8 @@ static struct ngene_info ngene_info_terratec = { - /****************************************************************************/ - - static const struct pci_device_id ngene_id_tbl[] = { -+ NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2), -+ NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5), - NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), - NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), - NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), -@@ -761,7 +1267,32 @@ static const struct pci_device_id ngene_id_tbl[] = { - NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), - NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), - NGENE_ID(0x1461, 0x062e, ngene_info_m780), -+#if 0 /* not (yet?) supported */ -+ NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), - NGENE_ID(0x153b, 0x1167, ngene_info_terratec), -+ NGENE_ID(0x18c3, 0x0030, ngene_info_python), -+ NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), -+ NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), -+ NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), -+ NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), -+ NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), -+ NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), -+ NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), -+ NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), -+ NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), -+ NGENE_ID(0x18c3, 0x0001, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0005, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0009, ngene_info_appboard_atsc), -+ NGENE_ID(0x18c3, 0x000b, ngene_info_appboard_atsc), -+ NGENE_ID(0x18c3, 0x0010, ngene_info_shrek_50_fp), -+ NGENE_ID(0x18c3, 0x0011, ngene_info_shrek_60_fp), -+ NGENE_ID(0x18c3, 0x0012, ngene_info_shrek_50), -+ NGENE_ID(0x18c3, 0x0013, ngene_info_shrek_60), -+ NGENE_ID(0x18c3, 0x0000, ngene_info_hognose), -+#endif - {0} - }; - MODULE_DEVICE_TABLE(pci, ngene_id_tbl); -@@ -798,7 +1329,7 @@ static void ngene_resume(struct pci_dev *dev) - printk(KERN_INFO DEVICE_NAME ": resume\n"); - } - --static const struct pci_error_handlers ngene_errors = { -+static struct pci_error_handlers ngene_errors = { - .error_detected = ngene_error_detected, - .link_reset = ngene_link_reset, - .slot_reset = ngene_slot_reset, -diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c -index e29bc3af..84510db 100644 ---- a/drivers/media/pci/ngene/ngene-core.c -+++ b/drivers/media/pci/ngene/ngene-core.c -@@ -57,13 +57,15 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - - #define dprintk if (debug) printk - --#define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) --#define ngwritel(dat, adr) writel((dat), dev->iomem + (adr)) --#define ngwriteb(dat, adr) writeb((dat), dev->iomem + (adr)) -+#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) -+#define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) -+#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) - #define ngreadl(adr) readl(dev->iomem + (adr)) - #define ngreadb(adr) readb(dev->iomem + (adr)) --#define ngcpyto(adr, src, count) memcpy_toio(dev->iomem + (adr), (src), (count)) --#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), dev->iomem + (adr), (count)) -+#define ngcpyto(adr, src, count) memcpy_toio((char *) \ -+ (dev->iomem + (adr)), (src), (count)) -+#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ -+ (dev->iomem + (adr)), (count)) - - /****************************************************************************/ - /* nGene interrupt handler **************************************************/ -@@ -84,6 +86,14 @@ static void event_tasklet(unsigned long data) - if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) - dev->RxEventNotify(dev, Event.TimeStamp, - Event.RXCharacter); -+#if 0 -+ if ((Event.GPIOStatus & 0x80) && (dev->Gpio2EventNotify)) -+ dev->Gpio2EventNotify(dev, Event.TimeStamp, -+ Event.GPIOStatus & 0x1f); -+ if ((Event.GPIOStatus & 0x40) && (dev->Gpio3EventNotify)) -+ dev->Gpio3EventNotify(dev, Event.TimeStamp, -+ Event.GPIOStatus & 0x1f); -+#endif - } - } - -@@ -212,6 +222,13 @@ static irqreturn_t irq_handler(int irq, void *dev_id) - u8 nextWriteIndex = - (dev->EventQueueWriteIndex + 1) & - (EVENT_QUEUE_SIZE - 1); -+#if 0 -+ printk(KERN_ERR DEVICE_NAME -+ ": Event interrupt %02x Uart = %02x Gpio = %02x\n", -+ dev->EventBuffer->EventStatus, -+ dev->EventBuffer->UARTStatus, -+ dev->EventBuffer->GPIOStatus); -+#endif - if (nextWriteIndex != dev->EventQueueReadIndex) { - dev->EventQueue[dev->EventQueueWriteIndex] = - *(dev->EventBuffer); -@@ -256,16 +273,22 @@ static void dump_command_io(struct ngene *dev) - u8 buf[8], *b; - - ngcpyfrom(buf, HOST_TO_NGENE, 8); -- printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf); -+ printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); - - ngcpyfrom(buf, NGENE_TO_HOST, 8); -- printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf); -+ printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); - - b = dev->hosttongene; -- printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b); -+ printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - - b = dev->ngenetohost; -- printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b); -+ printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - } - - static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) -@@ -314,12 +337,24 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) - ngwritel(1, FORCE_INT); - - ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); -+#if 0 -+ if (ret < 0) -+ return ret; -+ if (!dev->cmd_done) -+ ; -+#endif - if (!ret) { - /*ngwritel(0, FORCE_NMI);*/ - - printk(KERN_ERR DEVICE_NAME - ": Command timeout cmd=%02x prev=%02x\n", - com->cmd.hdr.Opcode, dev->prev_cmd); -+#if 0 -+ printk(KERN_ERR DEVICE_NAME ": Icounts=%08x\n", -+ ngreadl(NGENE_INT_COUNTS)); -+ if (ngreadl(NGENE_INT_COUNTS) == 0xffffffff) -+ ngwritel(0, NGENE_INT_ENABLE); -+#endif - dump_command_io(dev); - return -1; - } -@@ -346,6 +381,19 @@ int ngene_command(struct ngene *dev, struct ngene_command *com) - return result; - } - -+#if 0 -+int ngene_command_nop(struct ngene *dev) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_NOP; -+ com.cmd.hdr.Length = 0; -+ com.in_len = 0; -+ com.out_len = 0; -+ -+ return ngene_command(dev, &com); -+} -+#endif - - static int ngene_command_load_firmware(struct ngene *dev, - u8 *ngene_fw, u32 size) -@@ -380,6 +428,83 @@ static int ngene_command_load_firmware(struct ngene *dev, - return ngene_command(dev, &com); - } - -+#if 0 -+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; -+ com.cmd.hdr.Length = 1; -+ com.cmd.SfrIramRead.address = adr; -+ com.in_len = 1; -+ com.out_len = 2; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ *data = com.cmd.raw8[1]; -+ return 0; -+} -+ -+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; -+ com.cmd.hdr.Length = 2; -+ com.cmd.SfrIramWrite.address = adr; -+ com.cmd.SfrIramWrite.data = data; -+ com.in_len = 2; -+ com.out_len = 1; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static int ngene_command_config_uart(struct ngene *dev, u8 config, -+ tx_cb_t *tx_cb, rx_cb_t *rx_cb) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; -+ com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; -+ com.cmd.ConfigureUart.UartControl = config; -+ com.in_len = sizeof(struct FW_CONFIGURE_UART); -+ com.out_len = 0; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ dev->TxEventNotify = tx_cb; -+ dev->RxEventNotify = rx_cb; -+ -+ dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); -+ -+ return 0; -+} -+ -+static void tx_cb(struct ngene *dev, u32 ts) -+{ -+ dev->tx_busy = 0; -+ wake_up_interruptible(&dev->tx_wq); -+} -+ -+static void rx_cb(struct ngene *dev, u32 ts, u8 c) -+{ -+ int rp = dev->uart_rp; -+ int nwp, wp = dev->uart_wp; -+ -+ /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ -+ nwp = (wp + 1) % (UART_RBUF_LEN); -+ if (nwp == rp) -+ return; -+ dev->uart_rbuf[wp] = c; -+ dev->uart_wp = nwp; -+ wake_up_interruptible(&dev->rx_wq); -+} -+#endif - - static int ngene_command_config_buf(struct ngene *dev, u8 config) - { -@@ -425,6 +550,18 @@ int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) - return ngene_command(dev, &com); - } - -+#if 0 -+/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! -+ Also better set bootdelay to 1 in nvram or less. */ -+static void ngene_reset_decypher(struct ngene *dev) -+{ -+ printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); -+ ngene_command_gpio_set(dev, 4, 0); -+ msleep(1); -+ ngene_command_gpio_set(dev, 4, 1); -+ msleep(2000); -+} -+#endif - - /* - 02000640 is sample on rising edge. -@@ -510,6 +647,17 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags) - } - } - -+#if 0 -+static void clear_tsin(struct ngene_channel *chan) -+{ -+ struct SBufferHeader *Cur = chan->nextBuffer; -+ -+ do { -+ memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); -+ Cur = Cur->Next; -+ } while (Cur != chan->nextBuffer); -+} -+#endif - - static void flush_buffers(struct ngene_channel *chan) - { -@@ -730,6 +878,14 @@ void set_transfer(struct ngene_channel *chan, int state) - if (dev->card_info->switch_ctrl) - dev->card_info->switch_ctrl(chan, 1, state ^ 1); - -+#if 0 -+ /* Disable AVF output if present. */ -+ if (dev->card_info->avf[chan->number]) -+ i2c_write_register(&chan->i2c_adapter, -+ chan->dev->card_info->avf[chan->number], -+ 0xf2, state ? 0x80 : 0x89); -+ -+#endif - if (state) { - spin_lock_irq(&chan->state_lock); - -@@ -750,8 +906,8 @@ void set_transfer(struct ngene_channel *chan, int state) - if (chan->mode & NGENE_IO_TSIN) - chan->pBufferExchange = tsin_exchange; - spin_unlock_irq(&chan->state_lock); -- } -- /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", -+ } else -+ ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", - ngreadl(0x9310)); */ - - ret = ngene_command_stream_control(dev, chan->number, -@@ -769,6 +925,89 @@ void set_transfer(struct ngene_channel *chan, int state) - } - } - -+#if 0 -+/****************************************************************************/ -+/* Decypher firmware loading ************************************************/ -+/****************************************************************************/ -+ -+#define DECYPHER_FW "decypher.fw" -+ -+static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) -+{ -+#if 0 -+ if (wait_event_interruptible(dev->tsout_rbuf.queue, -+ dvb_ringbuffer_free -+ (&dev->tsout_rbuf) >= len) < 0) -+ return 0; -+#else -+ while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) -+ msleep(1); -+ -+#endif -+ -+ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); -+ -+ return len; -+} -+ -+u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; -+ -+int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) -+{ -+ struct ngene_channel *chan = &dev->channel[4]; -+ u32 len = 180, cc = 0; -+ u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; -+ -+ set_transfer(chan, 1); -+ msleep(100); -+ while (size) { -+ len = 180; -+ if (len > size) -+ len = size; -+ buf[3] = 0x10 | (cc & 0x0f); -+ buf[4] = (cc >> 8); -+ buf[5] = cc & 0xff; -+ buf[6] = len; -+ -+ dec_ts_send(dev, buf, 8); -+ dec_ts_send(dev, fw, len); -+ if (len < 180) -+ dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); -+ cc++; -+ size -= len; -+ fw += len; -+ } -+ for (len = 0; len < 512; len++) -+ dec_ts_send(dev, dec_fw_fill_ts, 188); -+ while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) -+ msleep(10); -+ msleep(100); -+ set_transfer(chan, 0); -+ return 0; -+} -+ -+int dec_fw_boot(struct ngene *dev) -+{ -+ u32 size; -+ const struct firmware *fw = NULL; -+ u8 *dec_fw; -+ -+ if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { -+ printk(KERN_ERR DEVICE_NAME -+ ": %s not found. Check hotplug directory.\n", -+ DECYPHER_FW); -+ return -1; -+ } -+ printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", -+ DECYPHER_FW); -+ -+ size = fw->size; -+ dec_fw = (u8 *)fw->data; -+ dec_fw_send(dev, dec_fw, size); -+ release_firmware(fw); -+ return 0; -+} -+#endif - - /****************************************************************************/ - /* nGene hardware init and release functions ********************************/ -@@ -908,6 +1147,7 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, - { - dma_addr_t tmp; - u32 i, j; -+ int status = 0; - u32 SCListMemSize = pRingBuffer->NumBuffers - * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : - NUM_SCATTER_GATHER_ENTRIES) -@@ -1007,12 +1247,14 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, - - } - -- return 0; -+ return status; - } - - static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, - struct SRingBufferDescriptor *pRingBuffer) - { -+ int status = 0; -+ - /* Copy pointer to scatter gather list in TSRingbuffer - structure for buffer 2 - Load number of buffer -@@ -1033,7 +1275,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, - pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; - Cur = Cur->Next; - } -- return 0; -+ return status; - } - - static u32 RingBufferSizes[MAX_STREAM] = { -@@ -1060,6 +1302,85 @@ static u32 Buffer2Sizes[MAX_STREAM] = { - 0 - }; - -+#if 0 -+static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, -+ struct SRingBufferDescriptor *rbuf, -+ u32 entries, u32 size1, u32 size2) -+{ -+ if (create_ring_buffer(pci_dev, rbuf, entries) < 0) -+ return -ENOMEM; -+ -+ if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static int channel_allocate_buffers(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ int type = dev->card_info->io_type[chan->number]; -+ int status; -+ -+ chan->State = KSSTATE_STOP; -+ -+ if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->RingBuffer, -+ RingBufferSizes[chan->number]); -+ if (status < 0) -+ return -ENOMEM; -+ -+ if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->RingBuffer, -+ Buffer1Sizes[chan->number], -+ Buffer2Sizes[chan-> -+ number]); -+ if (status < 0) -+ return -ENOMEM; -+ } else if (type & NGENE_IO_HDTV) { -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->RingBuffer, -+ MAX_HDTV_BUFFER_SIZE, 0); -+ if (status < 0) -+ return -ENOMEM; -+ } -+ } -+ -+ if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { -+ -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->TSRingBuffer, RING_SIZE_TS); -+ if (status < 0) -+ return -ENOMEM; -+ -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->TSRingBuffer, -+ MAX_TS_BUFFER_SIZE, 0); -+ if (status) -+ return -ENOMEM; -+ } -+ -+ if (type & NGENE_IO_TSOUT) { -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->TSIdleBuffer, 1); -+ if (status < 0) -+ return -ENOMEM; -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->TSIdleBuffer, -+ MAX_TS_BUFFER_SIZE, 0); -+ if (status) -+ return -ENOMEM; -+ FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); -+ } -+ return 0; -+} -+#endif - - static int AllocCommonBuffers(struct ngene *dev) - { -@@ -1073,11 +1394,12 @@ static int AllocCommonBuffers(struct ngene *dev) - dev->ngenetohost = dev->FWInterfaceBuffer + 256; - dev->EventBuffer = dev->FWInterfaceBuffer + 512; - -- dev->OverflowBuffer = pci_zalloc_consistent(dev->pci_dev, -- OVERFLOW_BUFFER_SIZE, -- &dev->PAOverflowBuffer); -+ dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, -+ OVERFLOW_BUFFER_SIZE, -+ &dev->PAOverflowBuffer); - if (!dev->OverflowBuffer) - return -ENOMEM; -+ memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); - - for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { - int type = dev->card_info->io_type[i]; -@@ -1312,6 +1634,10 @@ static int ngene_buffer_config(struct ngene *dev) - u8 tsin12_config[6] = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 }; - u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 }; - u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 }; -+#if 0 -+ u8 tsin34_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x60, 0x00 }; -+ u8 tsio35_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x00, 0x60 }; -+#endif - u8 *bconf = tsin12_config; - - if (dev->card_info->io_type[2]&NGENE_IO_TSIN && -@@ -1321,10 +1647,22 @@ static int ngene_buffer_config(struct ngene *dev) - dev->ci.en) - bconf = tsio1235_config; - } -+#if 0 -+ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { -+ bconf = hdtv_config; -+ ngene_reset_decypher(dev); -+ } -+#endif - stat = ngene_command_config_free_buf(dev, bconf); - } else { - int bconf = BUFFER_CONFIG_4422; - -+#if 0 -+ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { -+ bconf = BUFFER_CONFIG_8022; -+ ngene_reset_decypher(dev); -+ } -+#endif - if (dev->card_info->io_type[3] == NGENE_IO_TSIN) - bconf = BUFFER_CONFIG_3333; - stat = ngene_command_config_buf(dev, bconf); -@@ -1397,8 +1735,10 @@ static int ngene_start(struct ngene *dev) - if (stat < 0) - goto fail; - -- return 0; -+ if (!stat) -+ return stat; - -+ /* otherwise error: fall through */ - fail: - ngwritel(0, NGENE_INT_ENABLE); - free_irq(dev->pci_dev->irq, dev); -@@ -1590,7 +1930,7 @@ static void cxd_detach(struct ngene *dev) - - dvb_ca_en50221_release(ci->en); - kfree(ci->en); -- ci->en = NULL; -+ ci->en = 0; - } - - /***********************************/ -@@ -1616,7 +1956,7 @@ static void ngene_unlink(struct ngene *dev) - - void ngene_shutdown(struct pci_dev *pdev) - { -- struct ngene *dev = pci_get_drvdata(pdev); -+ struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); - - if (!dev || !shutdown_workaround) - return; -@@ -1642,6 +1982,7 @@ void ngene_remove(struct pci_dev *pdev) - cxd_detach(dev); - ngene_stop(dev); - ngene_release_buffers(dev); -+ pci_set_drvdata(pdev, NULL); - pci_disable_device(pdev); - } - -@@ -1681,10 +2022,36 @@ int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) - - - dev->i2c_current_bus = -1; -+#if 0 -+ exp_init(dev); -+ -+ /* Disable analog TV decoder chips if present */ -+ if (dev->card_info->msp[0]) -+ i2c_write_msp_register(&dev->channel[0].i2c_adapter, -+ dev->card_info->msp[0], 0x00, 0x0000); -+ if (dev->card_info->msp[1]) -+ i2c_write_msp_register(&dev->channel[1].i2c_adapter, -+ dev->card_info->msp[1], 0x00, 0x0000); -+ { -+ u16 data; -+ read_msp(&dev->channel[0].i2c_adapter, -+ dev->card_info->msp[0], 0x00, &data); -+ } -+ if (dev->card_info->avf[0]) -+ i2c_write_register(&dev->channel[0].i2c_adapter, -+ dev->card_info->avf[0], 0xf2, 0x80); -+ if (dev->card_info->avf[1]) -+ i2c_write_register(&dev->channel[1].i2c_adapter, -+ dev->card_info->avf[1], 0xf2, 0x80); -+ if (copy_eeprom) { -+ i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); -+ i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); -+ } -+ /*i2c_check_eeprom(&dev->i2c_adapter);*/ -+#endif - - /* Register DVB adapters and devices for both channels */ -- stat = init_channels(dev); -- if (stat < 0) -+ if (init_channels(dev) < 0) - goto fail2; - - return 0; -@@ -1695,5 +2062,6 @@ fail1: - ngene_release_buffers(dev); - fail0: - pci_disable_device(pci_dev); -+ pci_set_drvdata(pci_dev, NULL); - return stat; - } -diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c -index 59bb285..8049e2b 100644 ---- a/drivers/media/pci/ngene/ngene-dvb.c -+++ b/drivers/media/pci/ngene/ngene-dvb.c -@@ -42,12 +42,321 @@ - - #include "ngene.h" - -+#if 0 -+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, -+ u16 lines, u16 bpl, u16 vblines, u16 vbibpl) -+{ -+ if (!(mode & SMODE_TRANSPORT_STREAM)) -+ return -EINVAL; -+ -+ if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) -+ return -EINVAL; -+ -+ if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) -+ return -EINVAL; -+ -+ if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) -+ return -EINVAL; -+ -+ return ngene_command_stream_control(dev, stream, control, mode, 0); -+} -+#endif - - /****************************************************************************/ - /* COMMAND API interface ****************************************************/ - /****************************************************************************/ -+#if 0 -+ -+static int command_do_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int err = 0; -+ -+ switch (cmd) { -+ case IOCTL_MIC_NO_OP: -+ err = ngene_command_nop(dev); -+ break; -+ -+ case IOCTL_MIC_DOWNLOAD_FIRMWARE: -+ break; -+ -+ case IOCTL_MIC_I2C_READ: -+ { -+ MIC_I2C_READ *msg = parg; -+ -+ err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, -+ msg->OutData, msg->OutLength, -+ msg->OutData, msg->InLength, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_I2C_WRITE: -+ { -+ MIC_I2C_WRITE *msg = parg; -+ -+ err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, -+ msg->Data, msg->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_TEST_GETMEM: -+ { -+ MIC_MEM *m = parg; -+ -+ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) -+ return -EINVAL; -+ -+ /* WARNING, only use this on x86, -+ other archs may not swallow this */ -+ err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_TEST_SETMEM: -+ { -+ MIC_MEM *m = parg; -+ -+ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) -+ return -EINVAL; -+ -+ err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_SFR_READ: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_SFR_WRITE: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_write(dev, m->Address, m->Data, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_IRAM_READ: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); -+ break; -+ } -+ -+ case IOCTL_MIC_IRAM_WRITE: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_write(dev, m->Address, m->Data, 0); -+ break; -+ } -+ -+ case IOCTL_MIC_STREAM_CONTROL: -+ { -+ MIC_STREAM_CONTROL *m = parg; -+ -+ err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, -+ m->nLines, m->nBytesPerLine, -+ m->nVBILines, m->nBytesPerVBILine); -+ break; -+ } -+ -+ default: -+ err = -EINVAL; -+ break; -+ } -+ return err; -+} -+ -+static int command_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ void *parg = (void *)arg, *pbuf = NULL; -+ char buf[64]; -+ int res = -EFAULT; -+ -+ if (_IOC_DIR(cmd) & _IOC_WRITE) { -+ parg = buf; -+ if (_IOC_SIZE(cmd) > sizeof(buf)) { -+ pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); -+ if (!pbuf) -+ return -ENOMEM; -+ parg = pbuf; -+ } -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto error; -+ } -+ res = command_do_ioctl(inode, file, cmd, parg); -+ if (res < 0) -+ goto error; -+ if (_IOC_DIR(cmd) & _IOC_READ) -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ res = -EFAULT; -+error: -+ kfree(pbuf); -+ return res; -+} -+ -+struct page *ngene_nopage(struct vm_area_struct *vma, -+ unsigned long address, int *type) -+{ -+ return 0; -+} -+ -+static int ngene_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ -+ unsigned long size = vma->vm_end - vma->vm_start; -+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT; -+ unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; -+ unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; -+ -+ if (size > psize) -+ return -EINVAL; -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, -+ vma->vm_page_prot)) -+ return -EAGAIN; -+ return 0; -+} -+ -+ -+static int write_uart(struct ngene *dev, u8 *data, int len) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_WRITE_UART; -+ com.cmd.hdr.Length = len; -+ memcpy(com.cmd.WriteUart.Data, data, len); -+ com.cmd.WriteUart.Data[len] = 0; -+ com.cmd.WriteUart.Data[len + 1] = 0; -+ com.in_len = len; -+ com.out_len = 0; - --static ssize_t ts_write(struct file *file, const char __user *buf, -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static int send_cli(struct ngene *dev, char *cmd) -+{ -+ /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ -+ return write_uart(dev, cmd, strlen(cmd)); -+} -+ -+static int send_cli_val(struct ngene *dev, char *cmd, u32 val) -+{ -+ char s[32]; -+ -+ snprintf(s, 32, "%s %d\n", cmd, val); -+ /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ -+ return write_uart(dev, s, strlen(s)); -+} -+ -+static int ngene_command_write_uart_user(struct ngene *dev, -+ const u8 *data, int len) -+{ -+ struct ngene_command com; -+ -+ dev->tx_busy = 1; -+ com.cmd.hdr.Opcode = CMD_WRITE_UART; -+ com.cmd.hdr.Length = len; -+ -+ if (copy_from_user(com.cmd.WriteUart.Data, data, len)) -+ return -EFAULT; -+ com.in_len = len; -+ com.out_len = 0; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static ssize_t uart_write(struct file *file, const char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int len, ret = 0; -+ size_t left = count; -+ -+ while (left) { -+ len = left; -+ if (len > 250) -+ len = 250; -+ ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); -+ if (ret < 0) -+ return ret; -+ ngene_command_write_uart_user(dev, buf, len); -+ left -= len; -+ buf += len; -+ } -+ return count; -+} -+ -+static ssize_t uart_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left; -+ int wp, rp, avail, len; -+ -+ if (!dev->uart_rbuf) -+ return -EINVAL; -+ if (count > 128) -+ count = 128; -+ left = count; -+ while (left) { -+ if (wait_event_interruptible(dev->rx_wq, -+ dev->uart_wp != dev->uart_rp) < 0) -+ return -EAGAIN; -+ wp = dev->uart_wp; -+ rp = dev->uart_rp; -+ avail = (wp - rp); -+ -+ if (avail < 0) -+ avail += UART_RBUF_LEN; -+ if (avail > left) -+ avail = left; -+ if (wp < rp) { -+ len = UART_RBUF_LEN - rp; -+ if (len > avail) -+ len = avail; -+ if (copy_to_user(buf, dev->uart_rbuf + rp, len)) -+ return -EFAULT; -+ if (len < avail) -+ if (copy_to_user(buf + len, dev->uart_rbuf, -+ avail - len)) -+ return -EFAULT; -+ } else { -+ if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) -+ return -EFAULT; -+ } -+ dev->uart_rp = (rp + avail) % UART_RBUF_LEN; -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+#endif -+ -+static ssize_t ts_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) - { - struct dvb_device *dvbdev = file->private_data; -@@ -59,12 +368,12 @@ static ssize_t ts_write(struct file *file, const char __user *buf, - (&dev->tsout_rbuf) >= count) < 0) - return 0; - -- dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count); -+ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); - - return count; - } - --static ssize_t ts_read(struct file *file, char __user *buf, -+static ssize_t ts_read(struct file *file, char *buf, - size_t count, loff_t *ppos) - { - struct dvb_device *dvbdev = file->private_data; -@@ -97,6 +406,7 @@ static const struct file_operations ci_fops = { - }; - - struct dvb_device ngene_dvbdev_ci = { -+ .priv = 0, - .readers = -1, - .writers = -1, - .users = -1, -@@ -132,6 +442,11 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) - struct ngene_channel *chan = priv; - struct ngene *dev = chan->dev; - -+#if 0 -+ printk(KERN_INFO DEVICE_NAME ": tsin %08x %02x %02x %02x %02x\n", -+ len, ((u8 *) buf)[512 * 188], ((u8 *) buf)[0], -+ ((u8 *) buf)[1], ((u8 *) buf)[2]); -+#endif - - if (flags & DF_SWAP32) - swap_buffer(buf, len); -@@ -190,12 +505,49 @@ void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) - return buf; - } - -+#if 0 -+static void set_dto(struct ngene_channel *chan, u32 rate) -+{ -+ u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ -+ -+ val = ((val >> 25) + 1) >> 1; -+ chan->AudioDTOValue = (u32) val; -+ /* chan->AudioDTOUpdated=1; */ -+ /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ -+} -+#endif - - - int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ngene_channel *chan = dvbdmx->priv; -+#if 0 -+ struct ngene *dev = chan->dev; -+ -+ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { -+ switch (dvbdmxfeed->pes_type) { -+ case DMX_TS_PES_VIDEO: -+ send_cli_val(dev, "vpid", dvbdmxfeed->pid); -+ send_cli(dev, "res 1080i50\n"); -+ /* send_cli(dev, "vdec mpeg2\n"); */ -+ break; -+ -+ case DMX_TS_PES_AUDIO: -+ send_cli_val(dev, "apid", dvbdmxfeed->pid); -+ send_cli(dev, "start\n"); -+ break; -+ -+ case DMX_TS_PES_PCR: -+ send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); -+ break; -+ -+ default: -+ break; -+ } -+ -+ } -+#endif - - if (chan->users == 0) { - if (!chan->dev->cmd_timeout_workaround || !chan->running) -@@ -209,6 +561,27 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ngene_channel *chan = dvbdmx->priv; -+#if 0 -+ struct ngene *dev = chan->dev; -+ -+ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { -+ switch (dvbdmxfeed->pes_type) { -+ case DMX_TS_PES_VIDEO: -+ send_cli(dev, "stop\n"); -+ break; -+ -+ case DMX_TS_PES_AUDIO: -+ break; -+ -+ case DMX_TS_PES_PCR: -+ break; -+ -+ default: -+ break; -+ } -+ -+ } -+#endif - - if (--chan->users) - return chan->users; -diff --git a/drivers/media/pci/ngene/ngene-eeprom.c b/drivers/media/pci/ngene/ngene-eeprom.c -new file mode 100644 -index 0000000..281d9f9 ---- /dev/null -+++ b/drivers/media/pci/ngene/ngene-eeprom.c -@@ -0,0 +1,284 @@ -+/* -+ * ngene-eeprom.c: nGene PCIe bridge driver - eeprom support -+ * -+ * Copyright (C) 2005-2007 Micronas -+ * -+ * Copyright (C) 2008-2009 Ralph Metzler -+ * Modifications for new nGene firmware, -+ * support for EEPROM-copying, -+ * support for new dual DVB-S2 card prototype -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#if 0 -+static int copy_eeprom; -+module_param(copy_eeprom, int, 0444); -+MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); -+ -+#define MICNG_EE_START 0x0100 -+#define MICNG_EE_END 0x0FF0 -+ -+#define MICNG_EETAG_END0 0x0000 -+#define MICNG_EETAG_END1 0xFFFF -+ -+/* 0x0001 - 0x000F reserved for housekeeping */ -+/* 0xFFFF - 0xFFFE reserved for housekeeping */ -+ -+/* Micronas assigned tags -+ EEProm tags for hardware support */ -+ -+#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ -+#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ -+ -+#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ -+#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ -+ -+/* Tag range for OEMs */ -+ -+#define MICNG_EETAG_OEM_FIRST 0xC000 -+#define MICNG_EETAG_OEM_LAST 0xFFEF -+ -+static int i2c_write_eeprom(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 data) -+{ -+ u8 m[3] = {(reg >> 8), (reg & 0xff), data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, -+ .len = sizeof(m)}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int i2c_read_eeprom(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *data, int len) -+{ -+ u8 msg[2] = {(reg >> 8), (reg & 0xff)}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = data, .len = len} }; -+ -+ if (i2c_transfer(adapter, msgs, 2) != 2) { -+ dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int ReadEEProm(struct i2c_adapter *adapter, -+ u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) -+{ -+ int status = 0; -+ u16 Addr = MICNG_EE_START, Length, tag = 0; -+ u8 EETag[3]; -+ -+ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -+ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -+ return -1; -+ tag = (EETag[0] << 8) | EETag[1]; -+ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -+ return -1; -+ if (tag == Tag) -+ break; -+ Addr += sizeof(u16) + 1 + EETag[2]; -+ } -+ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Reached EOEE @ Tag = %04x Length = %3d\n", -+ tag, EETag[2]); -+ return -1; -+ } -+ Length = EETag[2]; -+ if (Length > MaxLen) -+ Length = (u16) MaxLen; -+ if (Length > 0) { -+ Addr += sizeof(u16) + 1; -+ status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); -+ if (!status) { -+ *pLength = EETag[2]; -+ if (Length < EETag[2]) -+ ; /*status=STATUS_BUFFER_OVERFLOW; */ -+ } -+ } -+ return status; -+} -+ -+static int WriteEEProm(struct i2c_adapter *adapter, -+ u16 Tag, u32 Length, u8 *data) -+{ -+ int status = 0; -+ u16 Addr = MICNG_EE_START; -+ u8 EETag[3]; -+ u16 tag = 0; -+ int retry, i; -+ -+ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -+ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -+ return -1; -+ tag = (EETag[0] << 8) | EETag[1]; -+ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -+ return -1; -+ if (tag == Tag) -+ break; -+ Addr += sizeof(u16) + 1 + EETag[2]; -+ } -+ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Reached EOEE @ Tag = %04x Length = %3d\n", -+ tag, EETag[2]); -+ return -1; -+ } -+ -+ if (Length > EETag[2]) -+ return -EINVAL; -+ /* Note: We write the data one byte at a time to avoid -+ issues with page sizes. (which are different for -+ each manufacture and eeprom size) -+ */ -+ Addr += sizeof(u16) + 1; -+ for (i = 0; i < Length; i++, Addr++) { -+ status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); -+ -+ if (status) -+ break; -+ -+ /* Poll for finishing write cycle */ -+ retry = 10; -+ while (retry) { -+ u8 Tmp; -+ -+ msleep(50); -+ status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); -+ if (status) -+ break; -+ if (Tmp != data[i]) -+ printk(KERN_ERR DEVICE_NAME -+ "eeprom write error\n"); -+ retry -= 1; -+ } -+ if (status) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Timeout polling eeprom\n"); -+ break; -+ } -+ } -+ return status; -+} -+ -+static void i2c_init_eeprom(struct i2c_adapter *adapter) -+{ -+ u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, -+ 0x10, 0x01, 0x02, 0x00, 0x00, -+ 0x00, 0x00, 0x00}; -+ -+ int i; -+ -+ for (i = 0; i < sizeof(tags); i++) -+ i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); -+} -+ -+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) -+{ -+ int stat; -+ u8 buf[2]; -+ u32 len = 0; -+ -+ stat = ReadEEProm(adapter, tag, 2, buf, &len); -+ if (stat) -+ return stat; -+ if (len != 2) -+ return -EINVAL; -+ -+ *data = (buf[0] << 8) | buf[1]; -+ return 0; -+} -+ -+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) -+{ -+ int stat; -+ u8 buf[2]; -+ -+ buf[0] = data >> 8; -+ buf[1] = data & 0xff; -+ stat = WriteEEProm(adapter, tag, 2, buf); -+ if (stat) -+ return stat; -+ return 0; -+} -+ -+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) -+{ -+ u8 buf[64]; -+ int i; -+ -+ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ for (i = 0; i < sizeof(buf); i++) { -+ if (!(i & 15)) -+ printk(KERN_DEBUG "\n"); -+ printk(KERN_DEBUG "%02x ", buf[i]); -+ } -+ printk("\n"); -+ -+ return 0; -+} -+ -+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) -+{ -+ u8 buf[64]; -+ int i; -+ -+ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ buf[36] = 0xc3; -+ buf[39] = 0xab; -+ for (i = 0; i < sizeof(buf); i++) { -+ i2c_write_eeprom(adapter, adr2, i, buf[i]); -+ msleep(10); -+ } -+ return 0; -+} -+ -+int i2c_check_eeprom(struct i2c_adapter *adapter) -+{ -+ u8 buf[13]; -+ -+ i2c_dump_eeprom(adapter); -+ -+ if (i2c_read_eeprom(adapter, 0x50, 0x0100, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ if (buf[0] != 0x10 || buf[1] != 0x00) { -+ printk(KERN_INFO DEVICE_NAME -+ ": Initializing EEPROM TAG area\n"); -+ i2c_init_eeprom(adapter); -+ } -+ return 0; -+} -+ -+#endif -diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c -index d28554f..601bea4 100644 ---- a/drivers/media/pci/ngene/ngene-i2c.c -+++ b/drivers/media/pci/ngene/ngene-i2c.c -@@ -77,6 +77,11 @@ static int ngene_command_i2c_write(struct ngene *dev, u8 adr, - { - struct ngene_command com; - -+#if 0 -+ /* Probing by writing 0 bytes does not work */ -+ if (!outlen) -+ outlen++; -+#endif - - com.cmd.hdr.Opcode = CMD_I2C_WRITE; - com.cmd.hdr.Length = outlen + 1; -@@ -148,6 +153,39 @@ done: - return num; - } - -+#if 0 -+static int ngene_i2c_algo_control(struct i2c_adapter *adap, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct ngene_channel *chan = -+ (struct ngene_channel *)i2c_get_adapdata(adap); -+ -+ switch (cmd) { -+ case IOCTL_MIC_TUN_RDY: -+ chan->tun_rdy = 1; -+ if (chan->dec_rdy == 1) -+ chan->tun_dec_rdy = 1; -+ break; -+ -+ case IOCTL_MIC_DEC_RDY: -+ chan->dec_rdy = 1; -+ if (chan->tun_rdy == 1) -+ chan->tun_dec_rdy = 1; -+ break; -+ -+ case IOCTL_MIC_TUN_DETECT: -+ { -+ int *palorbtsc = (int *)arg; -+ *palorbtsc = chan->dev->card_info->ntsc; -+ break; -+ } -+ -+ default: -+ break; -+ } -+ return 0; -+} -+#endif - - static u32 ngene_i2c_functionality(struct i2c_adapter *adap) - { -@@ -174,3 +212,78 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr) - return i2c_add_adapter(adap); - } - -+#if 0 -+int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) -+{ -+ u8 m[1] = {data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C adr %02x!\n", adr); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write_register(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 data) -+{ -+ u8 m[2] = {reg, data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C register %02x@%02x!\n", -+ reg, adr); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write_read(struct i2c_adapter *adapter, -+ u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = w, .len = wlen}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = r, .len = rlen} }; -+ -+ if (i2c_transfer(adapter, msgs, 2) != 2) { -+ printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int test_dec_i2c(struct i2c_adapter *adapter, int reg) -+{ -+ u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; -+ u8 data2[256]; -+ int i; -+ -+ memset(data2, 0, 256); -+ i2c_write_read(adapter, 0x66, data, 2, data2, 4); -+ for (i = 0; i < 4; i++) -+ printk(KERN_DEBUG "%02x ", data2[i]); -+ printk(KERN_DEBUG "\n"); -+ -+ return 0; -+} -+ -+static int i2c_write_msp_register(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u16 data) -+{ -+ u8 m[3] = {reg, (data >> 8) & 0xff, data & 0xff}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 3 }; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C register %02x@%02x!\n", -+ reg, adr); -+ return -1; -+ } -+ return 0; -+} -+ -+#endif -diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h -index 51e2fbd..e3ae00c 100644 ---- a/drivers/media/pci/ngene/ngene.h -+++ b/drivers/media/pci/ngene/ngene.h -@@ -653,6 +653,11 @@ struct ngene_channel { - struct dmx_frontend mem_frontend; - int users; - struct video_device *v4l_dev; -+#if 0 -+ struct dvb_device *command_dev; -+ struct dvb_device *audio_dev; -+ struct dvb_device *video_dev; -+#endif - struct dvb_device *ci_dev; - struct tasklet_struct demux_tasklet; - -@@ -691,6 +696,9 @@ struct ngene_channel { - struct mychip *mychip; - struct snd_card *soundcard; - u8 *evenbuffer; -+#if 0 -+ u8 *soundbuffer; -+#endif - u8 dma_on; - int soundstreamon; - int audiomute; -@@ -737,7 +745,7 @@ typedef void (tx_cb_t)(struct ngene *, u32); - struct ngene { - int nr; - struct pci_dev *pci_dev; -- unsigned char __iomem *iomem; -+ unsigned char *iomem; - - /*struct i2c_adapter i2c_adapter;*/ - -@@ -849,6 +857,10 @@ struct ngene_info { - u8 lnb[4]; - int i2c_access; - u8 ntsc; -+#if 0 -+ u8 exp; -+ u8 exp_init; -+#endif - u8 tsf[4]; - u8 i2s[4]; - -@@ -885,6 +897,25 @@ struct ngene_buffer { - }; - #endif - -+#if 0 -+int ngene_command_stream_control(struct ngene *dev, -+ u8 stream, u8 control, u8 mode, u8 flags); -+int ngene_command_nop(struct ngene *dev); -+int ngene_command_i2c_read(struct ngene *dev, u8 adr, -+ u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); -+int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); -+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); -+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); -+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, -+ u16 lines, u16 bpl, u16 vblines, u16 vbibpl); -+ -+int ngene_v4l2_init(struct ngene_channel *chan); -+void ngene_v4l2_remove(struct ngene_channel *chan); -+int ngene_snd_exit(struct ngene_channel *chan); -+int ngene_snd_init(struct ngene_channel *chan); -+ -+struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); -+#endif - - /* Provided by ngene-core.c */ - int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); -@@ -914,6 +945,15 @@ int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, - struct dmx_frontend *mem_frontend, - struct dvb_adapter *dvb_adapter); - -+/* Provided by ngene-eeprom.c */ -+#if 0 -+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2); -+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr); -+int i2c_check_eeprom(struct i2c_adapter *adapter); -+int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data); -+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data); -+#endif -+ - #endif - - /* LocalWords: Endif -diff --git a/include/uapi/linux/dvb/mod.h b/include/uapi/linux/dvb/mod.h -new file mode 100644 -index 0000000..c733a39 ---- /dev/null -+++ b/include/uapi/linux/dvb/mod.h -@@ -0,0 +1,22 @@ -+#ifndef _UAPI_DVBMOD_H_ -+#define _UAPI_DVBMOD_H_ -+ -+#include -+#include "frontend.h" -+ -+struct dvb_mod_params { -+ __u32 base_frequency; -+ __u32 attenuator; -+}; -+ -+struct dvb_mod_channel_params { -+ enum fe_modulation modulation; -+ __u64 input_bitrate; /* 2^-32 Hz */ -+ int pcr_correction; -+}; -+ -+ -+#define DVB_MOD_SET _IOW('o', 208, struct dvb_mod_params) -+#define DVB_MOD_CHANNEL_SET _IOW('o', 209, struct dvb_mod_channel_params) -+ -+#endif /*_UAPI_DVBMOD_H_*/ -diff --git a/include/uapi/linux/dvb/ns.h b/include/uapi/linux/dvb/ns.h -new file mode 100644 -index 0000000..691c65d ---- /dev/null -+++ b/include/uapi/linux/dvb/ns.h -@@ -0,0 +1,68 @@ -+#ifndef _UAPI_DVBNS_H_ -+#define _UAPI_DVBNS_H_ -+ -+#include -+ -+struct dvb_ns_params { -+ __u8 smac[6]; -+ __u8 dmac[6]; -+ __u8 sip[16]; -+ __u8 dip[16]; -+ __u16 sport; -+ __u16 dport; -+ __u16 sport2; -+ __u16 dport2; -+ __u8 ssrc[8]; -+ __u8 flags; -+ __u8 qos; -+ __u16 vlan; -+ __u8 ttl; -+}; -+ -+#define DVB_NS_IPV6 1 -+#define DVB_NS_RTP 2 -+#define DVB_NS_RTCP 4 -+#define DVB_NS_RTP_TO 8 -+ -+struct dvb_ns_rtcp { -+ __u8 *msg; -+ __u16 len; -+}; -+ -+struct dvb_ns_packet { -+ __u8 *buf; -+ __u8 count; -+}; -+ -+struct dvb_nsd_ts { -+ __u16 pid; -+ __u16 num; -+ __u16 input; -+ __u16 timeout; -+ __u16 len; -+ __u8 *ts; -+ __u8 mode; -+ __u8 table; -+ -+ __u8 filter_mask; -+ __u8 section; -+ __u16 section_id; -+}; -+ -+#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params) -+#define NS_START _IO('o', 193) -+#define NS_STOP _IO('o', 194) -+#define NS_SET_PID _IOW('o', 195, __u16) -+#define NS_SET_PIDS _IOW('o', 196, __u8 *) -+#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp) -+ -+#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts) -+#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts) -+#define NSD_CANCEL_GET_TS _IO('o', 200) -+#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts) -+ -+#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet) -+#define NS_INSERT_PACKETS _IOW('o', 203, __u8) -+#define NS_SET_CI _IOW('o', 204, __u8) -+ -+#endif /*_UAPI_DVBNS_H_*/ --- -2.1.0 - diff --git a/packages/linux/patches/4.0.5/linux-222-stb0899_signal_quality.patch b/packages/linux/patches/4.0.5/linux-222-stb0899_signal_quality.patch deleted file mode 100644 index fd6539d2bf..0000000000 --- a/packages/linux/patches/4.0.5/linux-222-stb0899_signal_quality.patch +++ /dev/null @@ -1,62 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:33:10.323380937 +0100 -@@ -971,6 +971,16 @@ - - *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val); - *strength += 750; -+ -+ const int MIN_STRENGTH_DVBS = 0; -+ const int MAX_STRENGTH_DVBS = 680; -+ if (*strength < MIN_STRENGTH_DVBS) -+ *strength = 0; -+ else if(*strength > MAX_STRENGTH_DVBS) -+ *strength = 0xFFFF; -+ else -+ *strength = (*strength - MIN_STRENGTH_DVBS) * 0xFFFF / (MAX_STRENGTH_DVBS - MIN_STRENGTH_DVBS); -+ - dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm", - val & 0xff, *strength); - } -@@ -983,6 +993,7 @@ - - *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); - *strength += 950; -+ *strength = *strength << 4; - dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", - val & 0x3fff, *strength); - } -@@ -1016,6 +1027,16 @@ - val = MAKEWORD16(buf[0], buf[1]); - - *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val); -+ -+ const int MIN_SNR_DVBS = 0; -+ const int MAX_SNR_DVBS = 200; -+ if (*snr < MIN_SNR_DVBS) -+ *snr = 0; -+ else if(*snr > MAX_SNR_DVBS) -+ *snr = 0xFFFF; -+ else -+ *snr = (*snr - MIN_SNR_DVBS) * 0xFFFF / (MAX_SNR_DVBS - MIN_SNR_DVBS); -+ - dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n", - buf[0], buf[1], val, *snr); - } -@@ -1040,6 +1061,16 @@ - val = (quantn - estn) / 10; - } - *snr = val; -+ -+ const int MIN_SNR_DVBS2 = 10; -+ const int MAX_SNR_DVBS2 = 70; -+ if (*snr < MIN_SNR_DVBS2) -+ *snr = 0; -+ else if(*snr > MAX_SNR_DVBS2) -+ *snr = 0xFFFF; -+ else -+ *snr = (*snr - MIN_SNR_DVBS2) * 0xFFFF / (MAX_SNR_DVBS2 - MIN_SNR_DVBS2); -+ - dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm", - quant, quantn, est, estn, val); - } diff --git a/packages/linux/patches/4.0.5/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch b/packages/linux/patches/4.0.5/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch deleted file mode 100644 index 7aaabc48c0..0000000000 --- a/packages/linux/patches/4.0.5/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -Naur linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c ---- linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-16 10:35:01.131342123 +0100 -@@ -995,11 +995,11 @@ - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_ISOC, -- .count = 7, -+ .count = 4, - .endpoint = 0x02, - .u = { - .isoc = { -- .framesperurb = 4, -+ .framesperurb = 64, - .framesize = 940, - .interval = 1 - } diff --git a/packages/linux/patches/4.0.5/linux-224-STK1160-addFramescaling.patch b/packages/linux/patches/4.0.5/linux-224-STK1160-addFramescaling.patch deleted file mode 100644 index 2b6f59c9a0..0000000000 --- a/packages/linux/patches/4.0.5/linux-224-STK1160-addFramescaling.patch +++ /dev/null @@ -1,284 +0,0 @@ -From edf8977b62ae86859cccf3d0ea4883333ea4d138 Mon Sep 17 00:00:00 2001 -From: Dale Hamel -Date: Tue, 24 Feb 2015 10:31:04 -0500 -Subject: [PATCH] Add framescaling support to stk1160 - -Implements frame scaling support for stk1160 to support format changes instead of a static frame size. - -This is effectively a dumb sampling, and could perhaps benefit from being an averaging instead. - -This was a requested "TO DO" for this driver, and allows support for userspace programs like Hyperion and Boblight. - -Submitted on behalf of the original author, Michael Stegemann ---- - drivers/media/usb/stk1160/stk1160-core.c | 1 + - drivers/media/usb/stk1160/stk1160-reg.h | 26 +++++++ - drivers/media/usb/stk1160/stk1160-v4l.c | 112 +++++++++++++++++++++++------- - drivers/media/usb/stk1160/stk1160-video.c | 17 ++++- - drivers/media/usb/stk1160/stk1160.h | 1 + - 5 files changed, 130 insertions(+), 27 deletions(-) - -diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c -index 03504dc..1881770 100644 ---- a/drivers/media/usb/stk1160/stk1160-core.c -+++ b/drivers/media/usb/stk1160/stk1160-core.c -@@ -418,6 +418,7 @@ static void stk1160_disconnect(struct usb_interface *interface) - stk1160_ac97_unregister(dev); - - stk1160_clear_queue(dev); -+ vb2_queue_release(&dev->vb_vidq); - - video_unregister_device(&dev->vdev); - v4l2_device_disconnect(&dev->v4l2_dev); -diff --git a/drivers/media/usb/stk1160/stk1160-reg.h b/drivers/media/usb/stk1160/stk1160-reg.h -index 3e49da6..b1fa11d 100644 ---- a/drivers/media/usb/stk1160/stk1160-reg.h -+++ b/drivers/media/usb/stk1160/stk1160-reg.h -@@ -33,6 +33,32 @@ - */ - #define STK1160_DCTRL 0x100 - -+/* -+ * Decimation Control Register: -+ * Byte 104: -+ * Horizontal Decimation Line Unit Count -+ * Byte 105: -+ * Vertical Decimation Line Unit Count -+ * Byte 106: -+ * Bit 0 - Horizontal Decimation Control -+ * 0 Horizontal decimation is disabled. -+ * 1 Horizontal decimation is enabled. -+ * Bit 1 - Decimates Half or More Column -+ * 0 Decimates less than half from original column, -+ * -> send count unit (0x105) before each unit skipped. -+ * 1 Decimates half or more from original column, -+ * -> skip count unit (0x105) before each unit sent. -+ * Bit 2 - Vertical Decimation Control -+ * see Bit 0, only vertical -+ * Bit 3 - Vertical Greater or Equal to Half -+ * see Bit 1, only vertical -+ * Bit 4 - Decimation Unit -+ * 0 Decimation will work with 2 rows or columns per unit. -+ * 1 Decimation will work with 4 rows or columns per unit. -+ */ -+#define STK1160_DMCTRL 0x104 -+ -+ - /* Capture Frame Start Position */ - #define STK116_CFSPO 0x110 - #define STK116_CFSPO_STX_L 0x110 -diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c -index 65a326c..94dafeb 100644 ---- a/drivers/media/usb/stk1160/stk1160-v4l.c -+++ b/drivers/media/usb/stk1160/stk1160-v4l.c -@@ -106,6 +106,76 @@ static void stk1160_set_std(struct stk1160 *dev) - - } - -+static void stk1160_try_fmt(struct stk1160 *dev, struct v4l2_format *f, bool try) -+{ -+ int base_width, base_height; -+ -+ if (dev->norm & V4L2_STD_525_60){ -+ base_width = 720; -+ base_height = 480; -+ } else { -+ base_width = 720; -+ base_height = 576; -+ } -+ -+ if (f->fmt.pix.width <= (base_width / 3) -+ || f->fmt.pix.height <= (base_height / 3)){ -+ f->fmt.pix.width = base_width / 3; -+ f->fmt.pix.height = base_height / 3; -+ if (!try){ -+ dev->decimate = 3; -+ } -+ } else if ((f->fmt.pix.width >= base_width >> 1 -+ && f->fmt.pix.width < base_width) -+ ||((f->fmt.pix.height >= base_height >> 1 -+ && f->fmt.pix.height < base_height))){ -+ f->fmt.pix.width = base_width >> 1; -+ f->fmt.pix.height = base_height >> 1; -+ if (!try){ -+ dev->decimate = 2; -+ } -+ } else { -+ f->fmt.pix.width = base_width; -+ f->fmt.pix.height = base_height; -+ if (!try){ -+ dev->decimate = 0; -+ } -+ } -+} -+ -+static void stk1160_set_fmt(struct stk1160 *dev) -+{ -+ if (dev->norm & V4L2_STD_525_60){ -+ dev->width = 720; -+ dev->height = 480; -+ } else { -+ dev->width = 720; -+ dev->height = 576; -+ } -+ -+ switch (dev->decimate){ -+ case 0: -+ stk1160_write_reg(dev, STK1160_DMCTRL, 0x00); -+ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x00); -+ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x00); -+ break; -+ case 2: -+ stk1160_write_reg(dev, STK1160_DMCTRL, 0x01); -+ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x01); -+ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x1f); -+ dev->width = dev->width >> 1; -+ dev->height = dev->height >> 1; -+ break; -+ case 3: -+ stk1160_write_reg(dev, STK1160_DMCTRL, 0x02); -+ stk1160_write_reg(dev, STK1160_DMCTRL+1, 0x02); -+ stk1160_write_reg(dev, STK1160_DMCTRL+2, 0x1f); -+ dev->width = dev->width / 3; -+ dev->height = dev->height / 3; -+ break; -+ } -+} -+ - /* - * Set a new alternate setting. - * Returns true is dev->max_pkt_size has changed, false otherwise. -@@ -321,17 +391,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - { - struct stk1160 *dev = video_drvdata(file); - -- /* -- * User can't choose size at his own will, -- * so we just return him the current size chosen -- * at standard selection. -- * TODO: Implement frame scaling? -- */ -+ stk1160_try_fmt(dev, f, true); - -- f->fmt.pix.pixelformat = dev->fmt->fourcc; -- f->fmt.pix.width = dev->width; -- f->fmt.pix.height = dev->height; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; -+ f->fmt.pix.pixelformat = dev->fmt->fourcc; - f->fmt.pix.bytesperline = dev->width * 2; - f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; -@@ -348,9 +411,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - if (vb2_is_busy(q)) - return -EBUSY; - -- vidioc_try_fmt_vid_cap(file, priv, f); -+ stk1160_try_fmt(dev, f, false); -+ stk1160_set_fmt(dev); - -- /* We don't support any format changes */ -+ f->fmt.pix.field = V4L2_FIELD_INTERLACED; -+ f->fmt.pix.pixelformat = dev->fmt->fourcc; -+ f->fmt.pix.bytesperline = dev->width * 2; -+ f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; - } -@@ -389,23 +457,18 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) - dev->norm = norm; - - /* This is taken from saa7115 video decoder */ -- if (dev->norm & V4L2_STD_525_60) { -- dev->width = 720; -- dev->height = 480; -- } else if (dev->norm & V4L2_STD_625_50) { -- dev->width = 720; -- dev->height = 576; -+ if (dev->norm & V4L2_STD_525_60 || dev->norm & V4L2_STD_625_50) { -+ stk1160_set_std(dev); -+ stk1160_set_fmt(dev); -+ -+ v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, -+ dev->norm); -+ -+ return 0; - } else { - stk1160_err("invalid standard\n"); - return -EINVAL; - } -- -- stk1160_set_std(dev); -- -- v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, -- dev->norm); -- -- return 0; - } - - -@@ -671,6 +734,7 @@ int stk1160_video_register(struct stk1160 *dev) - dev->norm = V4L2_STD_NTSC_M; - dev->width = 720; - dev->height = 480; -+ dev->decimate = 0; - - /* set default format */ - dev->fmt = &format[0]; -diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c -index 39f1aae..5a55028 100644 ---- a/drivers/media/usb/stk1160/stk1160-video.c -+++ b/drivers/media/usb/stk1160/stk1160-video.c -@@ -84,7 +84,6 @@ struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) - if (!list_empty(&dev->avail_bufs)) { - buf = list_first_entry(&dev->avail_bufs, - struct stk1160_buffer, list); -- list_del(&buf->list); - } - spin_unlock_irqrestore(&dev->buf_lock, flags); - -@@ -95,7 +94,7 @@ static inline - void stk1160_buffer_done(struct stk1160 *dev) - { - struct stk1160_buffer *buf = dev->isoc_ctl.buf; -- -+ unsigned long flags = 0; - dev->field_count++; - - buf->vb.v4l2_buf.sequence = dev->field_count >> 1; -@@ -104,7 +103,19 @@ void stk1160_buffer_done(struct stk1160 *dev) - v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); - - vb2_set_plane_payload(&buf->vb, 0, buf->bytesused); -- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); -+ -+ spin_lock_irqsave(&dev->buf_lock, flags); -+ if (buf->bytesused == vb2_plane_size(&buf->vb, 0)) -+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); -+ else -+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); -+ -+ if (!list_empty(&dev->avail_bufs)) { -+ list_del(&buf->list); -+ } -+ -+ spin_unlock_irqrestore(&dev->buf_lock, flags); -+ - - dev->isoc_ctl.buf = NULL; - } -diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h -index abdea48..895ed35 100644 ---- a/drivers/media/usb/stk1160/stk1160.h -+++ b/drivers/media/usb/stk1160/stk1160.h -@@ -150,6 +150,7 @@ struct stk1160 { - unsigned int ctl_input; /* selected input */ - v4l2_std_id norm; /* current norm */ - struct stk1160_fmt *fmt; /* selected format */ -+ int decimate; - - unsigned int field_count; /* not sure ??? */ - enum v4l2_field field; /* also not sure :/ */ --- -2.1.1 - diff --git a/packages/linux/patches/4.0.5/linux-227-ds3000-invalid-symbol-rate.patch b/packages/linux/patches/4.0.5/linux-227-ds3000-invalid-symbol-rate.patch deleted file mode 100644 index 79e04f2f82..0000000000 --- a/packages/linux/patches/4.0.5/linux-227-ds3000-invalid-symbol-rate.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -rupN a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c ---- a/drivers/media/dvb-frontends/ds3000.c 2015-01-28 23:24:59.000000000 +0100 -+++ b/drivers/media/dvb-frontends/ds3000.c 2015-01-29 21:57:56.000000000 +0100 -@@ -958,6 +958,14 @@ static int ds3000_set_frontend(struct dv - /* enable ac coupling */ - ds3000_writereg(state, 0x25, 0x8a); - -+ dprintk("%s() frequency:%u symbol_rate:%u\n", __func__, c->frequency, c->symbol_rate); -+ -+ if (c->symbol_rate < ds3000_ops.info.symbol_rate_min || c->symbol_rate > ds3000_ops.info.symbol_rate_max ) { -+ dprintk("%s() symbol_rate %u out of range (%u ... %u)\n", __func__, c->symbol_rate, -+ ds3000_ops.info.symbol_rate_min, ds3000_ops.info.symbol_rate_max); -+ return 1; -+ } -+ - /* enhance symbol rate performance */ - if ((c->symbol_rate / 1000) <= 5000) { - value = 29777 / (c->symbol_rate / 1000) + 1; \ No newline at end of file diff --git a/packages/linux/patches/4.0.5/linux-228-technotrend-s2-4600.patch b/packages/linux/patches/4.0.5/linux-228-technotrend-s2-4600.patch deleted file mode 100644 index 0c1c9ae7f9..0000000000 --- a/packages/linux/patches/4.0.5/linux-228-technotrend-s2-4600.patch +++ /dev/null @@ -1,382 +0,0 @@ -diff -urN a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h ---- a/drivers/media/dvb-core/dvb-usb-ids.h 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/dvb-core/dvb-usb-ids.h 2015-05-05 20:35:29.392417272 +0300 -@@ -245,6 +245,7 @@ - #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 - #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009 - #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d -+#define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011 - #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012 - #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014 - #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a -diff -urN a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c ---- a/drivers/media/usb/dvb-usb/dw2102.c 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/dvb-usb/dw2102.c 2015-05-05 20:37:20.376421156 +0300 -@@ -2,7 +2,8 @@ - * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, - * TeVii S600, S630, S650, S660, S480, S421, S632 - * Prof 1100, 7500, -- * Geniatech SU3000, T220 Cards -+ * Geniatech SU3000, T220, -+ * TechnoTrend S2-4600 Cards - * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) - * - * This program is free software; you can redistribute it and/or modify it -@@ -31,6 +32,8 @@ - #include "m88rs2000.h" - #include "tda18271.h" - #include "cxd2820r.h" -+#include "m88ds3103.h" -+#include "m88ts2022.h" - - /* Max transfer size done by I2C transfer functions */ - #define MAX_XFER_SIZE 64 -@@ -112,12 +115,15 @@ - "Please see linux/Documentation/dvb/ for more details " \ - "on firmware-problems." - --struct su3000_state { -+struct dw2102_state { - u8 initialized; --}; -+ u8 last_lock; -+ struct i2c_client *i2c_client_tuner; - --struct s6x0_state { -+ /* fe hook functions*/ - int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v); -+ int (*fe_read_status)(struct dvb_frontend *fe, -+ fe_status_t *status); - }; - - /* debug */ -@@ -887,7 +893,7 @@ - - static int su3000_power_ctrl(struct dvb_usb_device *d, int i) - { -- struct su3000_state *state = (struct su3000_state *)d->priv; -+ struct dw2102_state *state = (struct dw2102_state *)d->priv; - u8 obuf[] = {0xde, 0}; - - info("%s: %d, initialized %d\n", __func__, i, state->initialized); -@@ -973,7 +979,7 @@ - { - struct dvb_usb_adapter *d = - (struct dvb_usb_adapter *)(fe->dvb->priv); -- struct s6x0_state *st = (struct s6x0_state *)d->dev->priv; -+ struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; - - dw210x_set_voltage(fe, voltage); - if (st->old_set_voltage) -@@ -1000,6 +1006,23 @@ - i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); - } - -+static int tt_s2_4600_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct dvb_usb_adapter *d = -+ (struct dvb_usb_adapter *)(fe->dvb->priv); -+ struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; -+ int ret; -+ -+ ret = st->fe_read_status(fe, status); -+ -+ /* resync slave fifo when signal change from unlock to lock */ -+ if ((*status & FE_HAS_LOCK) && (!st->last_lock)) -+ su3000_streaming_ctrl(d, 1); -+ -+ st->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; -+ return ret; -+} -+ - static struct stv0299_config sharp_z0194a_config = { - .demod_address = 0x68, - .inittab = sharp_z0194a_inittab, -@@ -1117,6 +1140,22 @@ - .gate = TDA18271_GATE_DIGITAL, - }; - -+static const struct m88ds3103_config tt_s2_4600_m88ds3103_config = { -+ .i2c_addr = 0x68, -+ .clock = 27000000, -+ .i2c_wr_max = 33, -+ .ts_mode = M88DS3103_TS_CI, -+ .ts_clk = 16000, -+ .ts_clk_pol = 0, -+ .spec_inv = 0, -+ .agc_inv = 0, -+ .clock_out = M88DS3103_CLOCK_OUT_ENABLED, -+ .envelope_mode = 0, -+ .agc = 0x99, -+ .lnb_hv_pol = 1, -+ .lnb_en_pol = 0, -+}; -+ - static u8 m88rs2000_inittab[] = { - DEMOD_WRITE, 0x9a, 0x30, - DEMOD_WRITE, 0x00, 0x01, -@@ -1295,7 +1334,7 @@ - - static int ds3000_frontend_attach(struct dvb_usb_adapter *d) - { -- struct s6x0_state *st = (struct s6x0_state *)d->dev->priv; -+ struct dw2102_state *st = d->dev->priv; - u8 obuf[] = {7, 1}; - - d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config, -@@ -1461,6 +1500,92 @@ - return -EIO; - } - -+static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ struct dvb_usb_device *d = adap->dev; -+ struct dw2102_state *state = d->priv; -+ u8 obuf[3] = { 0xe, 0x80, 0 }; -+ u8 ibuf[] = { 0 }; -+ struct i2c_adapter *i2c_adapter; -+ struct i2c_client *client; -+ struct i2c_board_info info; -+ struct m88ts2022_config m88ts2022_config = { -+ .clock = 27000000, -+ }; -+ -+ if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0) -+ err("command 0x0e transfer failed."); -+ -+ obuf[0] = 0xe; -+ obuf[1] = 0x02; -+ obuf[2] = 1; -+ -+ if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0) -+ err("command 0x0e transfer failed."); -+ msleep(300); -+ -+ obuf[0] = 0xe; -+ obuf[1] = 0x83; -+ obuf[2] = 0; -+ -+ if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0) -+ err("command 0x0e transfer failed."); -+ -+ obuf[0] = 0xe; -+ obuf[1] = 0x83; -+ obuf[2] = 1; -+ -+ if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0) -+ err("command 0x0e transfer failed."); -+ -+ obuf[0] = 0x51; -+ -+ if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 1, 0) < 0) -+ err("command 0x51 transfer failed."); -+ -+ memset(&info, 0, sizeof(struct i2c_board_info)); -+ -+ adap->fe_adap[0].fe = dvb_attach(m88ds3103_attach, -+ &tt_s2_4600_m88ds3103_config, -+ &d->i2c_adap, -+ &i2c_adapter); -+ if (adap->fe_adap[0].fe == NULL) -+ return -ENODEV; -+ -+ /* attach tuner */ -+ m88ts2022_config.fe = adap->fe_adap[0].fe; -+ strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE); -+ info.addr = 0x60; -+ info.platform_data = &m88ts2022_config; -+ request_module("m88ts2022"); -+ client = i2c_new_device(i2c_adapter, &info); -+ -+ if (client == NULL || client->dev.driver == NULL) { -+ dvb_frontend_detach(adap->fe_adap[0].fe); -+ return -ENODEV; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ dvb_frontend_detach(adap->fe_adap[0].fe); -+ return -ENODEV; -+ } -+ -+ /* delegate signal strength measurement to tuner */ -+ adap->fe_adap[0].fe->ops.read_signal_strength = -+ adap->fe_adap[0].fe->ops.tuner_ops.get_rf_strength; -+ -+ state->i2c_client_tuner = client; -+ -+ /* hook fe: need to resync the slave fifo when signal locks */ -+ state->fe_read_status = adap->fe_adap[0].fe->ops.read_status; -+ adap->fe_adap[0].fe->ops.read_status = tt_s2_4600_read_status; -+ -+ state->last_lock = 0; -+ -+ return 0; -+} -+ - static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) - { - dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, -@@ -1561,6 +1686,7 @@ - TERRATEC_CINERGY_S2_R2, - GOTVIEW_SAT_HD, - GENIATECH_T220, -+ TECHNOTREND_S2_4600, - }; - - static struct usb_device_id dw2102_table[] = { -@@ -1584,6 +1710,8 @@ - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, - [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, - [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, -+ [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, -+ USB_PID_TECHNOTREND_CONNECT_S2_4600)}, - { } - }; - -@@ -1857,7 +1985,7 @@ - static struct dvb_usb_device_properties s6x0_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = DEVICE_SPECIFIC, -- .size_of_priv = sizeof(struct s6x0_state), -+ .size_of_priv = sizeof(struct dw2102_state), - .firmware = S630_FIRMWARE, - .no_reconnect = 1, - -@@ -1950,7 +2078,7 @@ - static struct dvb_usb_device_properties su3000_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = DEVICE_SPECIFIC, -- .size_of_priv = sizeof(struct su3000_state), -+ .size_of_priv = sizeof(struct dw2102_state), - .power_ctrl = su3000_power_ctrl, - .num_adapters = 1, - .identify_state = su3000_identify_state, -@@ -2015,7 +2143,7 @@ - static struct dvb_usb_device_properties t220_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = DEVICE_SPECIFIC, -- .size_of_priv = sizeof(struct su3000_state), -+ .size_of_priv = sizeof(struct dw2102_state), - .power_ctrl = su3000_power_ctrl, - .num_adapters = 1, - .identify_state = su3000_identify_state, -@@ -2061,6 +2189,55 @@ - } - }; - -+static struct dvb_usb_device_properties tt_s2_4600_properties = { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ .usb_ctrl = DEVICE_SPECIFIC, -+ .size_of_priv = sizeof(struct dw2102_state), -+ .power_ctrl = su3000_power_ctrl, -+ .num_adapters = 1, -+ .identify_state = su3000_identify_state, -+ .i2c_algo = &su3000_i2c_algo, -+ -+ .rc.core = { -+ .rc_interval = 250, -+ .rc_codes = RC_MAP_TT_1500, -+ .module_name = "dw2102", -+ .allowed_protos = RC_BIT_RC5, -+ .rc_query = su3000_rc_query, -+ }, -+ -+ .read_mac_address = su3000_read_mac_address, -+ -+ .generic_bulk_ctrl_endpoint = 0x01, -+ -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = {{ -+ .streaming_ctrl = su3000_streaming_ctrl, -+ .frontend_attach = tt_s2_4600_frontend_attach, -+ .stream = { -+ .type = USB_BULK, -+ .count = 8, -+ .endpoint = 0x82, -+ .u = { -+ .bulk = { -+ .buffersize = 4096, -+ } -+ } -+ } -+ } }, -+ } -+ }, -+ .num_device_descs = 1, -+ .devices = { -+ { "TechnoTrend TT-connect S2-4600", -+ { &dw2102_table[TECHNOTREND_S2_4600], NULL }, -+ { NULL }, -+ }, -+ } -+}; -+ - static int dw2102_probe(struct usb_interface *intf, - const struct usb_device_id *id) - { -@@ -2135,16 +2312,34 @@ - 0 == dvb_usb_device_init(intf, &su3000_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &t220_properties, -+ THIS_MODULE, NULL, adapter_nr) || -+ 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, - THIS_MODULE, NULL, adapter_nr)) - return 0; - - return -ENODEV; - } - -+static void dw2102_disconnect(struct usb_interface *intf) -+{ -+ struct dvb_usb_device *d = usb_get_intfdata(intf); -+ struct dw2102_state *st = (struct dw2102_state *)d->priv; -+ struct i2c_client *client; -+ -+ /* remove I2C client for tuner */ -+ client = st->i2c_client_tuner; -+ if (client) { -+ module_put(client->dev.driver->owner); -+ i2c_unregister_device(client); -+ } -+ -+ dvb_usb_device_exit(intf); -+} -+ - static struct usb_driver dw2102_driver = { - .name = "dw2102", - .probe = dw2102_probe, -- .disconnect = dvb_usb_device_exit, -+ .disconnect = dw2102_disconnect, - .id_table = dw2102_table, - }; - -@@ -2155,7 +2350,8 @@ - " DVB-C 3101 USB2.0," - " TeVii S600, S630, S650, S660, S480, S421, S632" - " Prof 1100, 7500 USB2.0," -- " Geniatech SU3000, T220 devices"); -+ " Geniatech SU3000, T220," -+ " TechnoTrend S2-4600 devices"); - MODULE_VERSION("0.1"); - MODULE_LICENSE("GPL"); - MODULE_FIRMWARE(DW2101_FIRMWARE); -diff -urN a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig ---- a/drivers/media/usb/dvb-usb/Kconfig 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/dvb-usb/Kconfig 2015-05-05 20:35:29.392417272 +0300 -@@ -278,9 +278,11 @@ - select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT - select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT -+ select MEDIA_TUNER_TS2022 if MEDIA_SUBDRV_AUTOSELECT - help -- Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0 -- receivers. -+ Say Y here to support the DvbWorld, TeVii, Prof, TechnoTrend -+ DVB-S/S2 USB2.0 receivers. - - config DVB_USB_CINERGY_T2 - tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" diff --git a/packages/linux/patches/4.0.5/linux-229-hauppauge-hvr-955q.patch b/packages/linux/patches/4.0.5/linux-229-hauppauge-hvr-955q.patch deleted file mode 100644 index d9312c76be..0000000000 --- a/packages/linux/patches/4.0.5/linux-229-hauppauge-hvr-955q.patch +++ /dev/null @@ -1,2706 +0,0 @@ -diff -urN a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig ---- a/drivers/media/dvb-frontends/Kconfig 2015-05-05 20:31:16.696408429 +0300 -+++ b/drivers/media/dvb-frontends/Kconfig 2015-05-05 21:24:21.988519906 +0300 -@@ -604,6 +604,14 @@ - An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want - to support this frontend. - -+config DVB_LGDT3306A -+ tristate "LG Electronics LGDT3306A based" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ An ATSC 8VSB and QAM-B 64/256 demodulator module. Say Y when you want -+ to support this frontend. -+ - config DVB_LG2160 - tristate "LG Electronics LG216x based" - depends on DVB_CORE && I2C -diff -urN a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c ---- a/drivers/media/dvb-frontends/lgdt3306a.c 1970-01-01 02:00:00.000000000 +0200 -+++ b/drivers/media/dvb-frontends/lgdt3306a.c 2015-05-05 21:22:52.244516766 +0300 -@@ -0,0 +1,2144 @@ -+/* -+ * Support for LGDT3306A - 8VSB/QAM-B -+ * -+ * Copyright (C) 2013 Fred Richter -+ * - driver structure based on lgdt3305.[ch] by Michael Krufky -+ * - code based on LG3306_V0.35 API by LG Electronics Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include "dvb_math.h" -+#include "lgdt3306a.h" -+ -+ -+static int debug; -+module_param(debug, int, 0644); -+MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); -+ -+#define DBG_INFO 1 -+#define DBG_REG 2 -+#define DBG_DUMP 4 /* FGR - comment out to remove dump code */ -+ -+#define lg_debug(fmt, arg...) \ -+ printk(KERN_DEBUG pr_fmt(fmt), ## arg) -+ -+#define dbg_info(fmt, arg...) \ -+ do { \ -+ if (debug & DBG_INFO) \ -+ lg_debug(fmt, ## arg); \ -+ } while (0) -+ -+#define dbg_reg(fmt, arg...) \ -+ do { \ -+ if (debug & DBG_REG) \ -+ lg_debug(fmt, ## arg); \ -+ } while (0) -+ -+#define lg_chkerr(ret) \ -+({ \ -+ int __ret; \ -+ __ret = (ret < 0); \ -+ if (__ret) \ -+ pr_err("error %d on line %d\n", ret, __LINE__); \ -+ __ret; \ -+}) -+ -+struct lgdt3306a_state { -+ struct i2c_adapter *i2c_adap; -+ const struct lgdt3306a_config *cfg; -+ -+ struct dvb_frontend frontend; -+ -+ fe_modulation_t current_modulation; -+ u32 current_frequency; -+ u32 snr; -+}; -+ -+/* -+ * LG3306A Register Usage -+ * (LG does not really name the registers, so this code does not either) -+ * -+ * 0000 -> 00FF Common control and status -+ * 1000 -> 10FF Synchronizer control and status -+ * 1F00 -> 1FFF Smart Antenna control and status -+ * 2100 -> 21FF VSB Equalizer control and status -+ * 2800 -> 28FF QAM Equalizer control and status -+ * 3000 -> 30FF FEC control and status -+ */ -+ -+enum lgdt3306a_lock_status { -+ LG3306_UNLOCK = 0x00, -+ LG3306_LOCK = 0x01, -+ LG3306_UNKNOWN_LOCK = 0xff -+}; -+ -+enum lgdt3306a_neverlock_status { -+ LG3306_NL_INIT = 0x00, -+ LG3306_NL_PROCESS = 0x01, -+ LG3306_NL_LOCK = 0x02, -+ LG3306_NL_FAIL = 0x03, -+ LG3306_NL_UNKNOWN = 0xff -+}; -+ -+enum lgdt3306a_modulation { -+ LG3306_VSB = 0x00, -+ LG3306_QAM64 = 0x01, -+ LG3306_QAM256 = 0x02, -+ LG3306_UNKNOWN_MODE = 0xff -+}; -+ -+enum lgdt3306a_lock_check { -+ LG3306_SYNC_LOCK, -+ LG3306_FEC_LOCK, -+ LG3306_TR_LOCK, -+ LG3306_AGC_LOCK, -+}; -+ -+ -+#ifdef DBG_DUMP -+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state); -+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state); -+#endif -+ -+ -+static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val) -+{ -+ int ret; -+ u8 buf[] = { reg >> 8, reg & 0xff, val }; -+ struct i2c_msg msg = { -+ .addr = state->cfg->i2c_addr, .flags = 0, -+ .buf = buf, .len = 3, -+ }; -+ -+ dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); -+ -+ ret = i2c_transfer(state->i2c_adap, &msg, 1); -+ -+ if (ret != 1) { -+ pr_err("error (addr %02x %02x <- %02x, err = %i)\n", -+ msg.buf[0], msg.buf[1], msg.buf[2], ret); -+ if (ret < 0) -+ return ret; -+ else -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val) -+{ -+ int ret; -+ u8 reg_buf[] = { reg >> 8, reg & 0xff }; -+ struct i2c_msg msg[] = { -+ { .addr = state->cfg->i2c_addr, -+ .flags = 0, .buf = reg_buf, .len = 2 }, -+ { .addr = state->cfg->i2c_addr, -+ .flags = I2C_M_RD, .buf = val, .len = 1 }, -+ }; -+ -+ ret = i2c_transfer(state->i2c_adap, msg, 2); -+ -+ if (ret != 2) { -+ pr_err("error (addr %02x reg %04x error (ret == %i)\n", -+ state->cfg->i2c_addr, reg, ret); -+ if (ret < 0) -+ return ret; -+ else -+ return -EREMOTEIO; -+ } -+ dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val); -+ -+ return 0; -+} -+ -+#define read_reg(state, reg) \ -+({ \ -+ u8 __val; \ -+ int ret = lgdt3306a_read_reg(state, reg, &__val); \ -+ if (lg_chkerr(ret)) \ -+ __val = 0; \ -+ __val; \ -+}) -+ -+static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state, -+ u16 reg, int bit, int onoff) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); -+ -+ ret = lgdt3306a_read_reg(state, reg, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ val &= ~(1 << bit); -+ val |= (onoff & 1) << bit; -+ -+ ret = lgdt3306a_write_reg(state, reg, val); -+ lg_chkerr(ret); -+fail: -+ return ret; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int lgdt3306a_soft_reset(struct lgdt3306a_state *state) -+{ -+ int ret; -+ -+ dbg_info("\n"); -+ -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ msleep(20); -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); -+ lg_chkerr(ret); -+ -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state, -+ enum lgdt3306a_mpeg_mode mode) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_info("(%d)\n", mode); -+ /* transport packet format - TPSENB=0x80 */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, -+ mode == LGDT3306A_MPEG_PARALLEL ? 1 : 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* -+ * start of packet signal duration -+ * TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration -+ */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_read_reg(state, 0x0070, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ val |= 0x10; /* TPCLKSUPB=0x10 */ -+ -+ if (mode == LGDT3306A_MPEG_PARALLEL) -+ val &= ~0x10; -+ -+ ret = lgdt3306a_write_reg(state, 0x0070, val); -+ lg_chkerr(ret); -+ -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state, -+ enum lgdt3306a_tp_clock_edge edge, -+ enum lgdt3306a_tp_valid_polarity valid) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_info("edge=%d, valid=%d\n", edge, valid); -+ -+ ret = lgdt3306a_read_reg(state, 0x0070, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */ -+ -+ if (edge == LGDT3306A_TPCLK_RISING_EDGE) -+ val |= 0x04; -+ if (valid == LGDT3306A_TP_VALID_HIGH) -+ val |= 0x02; -+ -+ ret = lgdt3306a_write_reg(state, 0x0070, val); -+ lg_chkerr(ret); -+ -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state, -+ int mode) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_info("(%d)\n", mode); -+ -+ if (mode) { -+ ret = lgdt3306a_read_reg(state, 0x0070, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ /* -+ * Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, -+ * TPDATAOUTEN=0x08 -+ */ -+ val &= ~0xa8; -+ ret = lgdt3306a_write_reg(state, 0x0070, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ } else { -+ /* enable IFAGC pin */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_read_reg(state, 0x0070, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ val |= 0xa8; /* enable bus */ -+ ret = lgdt3306a_write_reg(state, 0x0070, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ } -+ -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ dbg_info("acquire=%d\n", acquire); -+ -+ return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1); -+ -+} -+ -+static int lgdt3306a_power(struct lgdt3306a_state *state, -+ int mode) -+{ -+ int ret; -+ -+ dbg_info("(%d)\n", mode); -+ -+ if (mode == 0) { -+ /* into reset */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* power down */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ } else { -+ /* out of reset */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* power up */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); -+ if (lg_chkerr(ret)) -+ goto fail; -+ } -+ -+#ifdef DBG_DUMP -+ lgdt3306a_DumpAllRegs(state); -+#endif -+fail: -+ return ret; -+} -+ -+ -+static int lgdt3306a_set_vsb(struct lgdt3306a_state *state) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_info("\n"); -+ -+ /* 0. Spectrum inversion detection manual; spectrum inverted */ -+ ret = lgdt3306a_read_reg(state, 0x0002, &val); -+ val &= 0xf7; /* SPECINVAUTO Off */ -+ val |= 0x04; /* SPECINV On */ -+ ret = lgdt3306a_write_reg(state, 0x0002, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ -+ ret = lgdt3306a_write_reg(state, 0x0008, 0x80); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 2. Bandwidth mode for VSB(6MHz) */ -+ ret = lgdt3306a_read_reg(state, 0x0009, &val); -+ val &= 0xe3; -+ val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */ -+ ret = lgdt3306a_write_reg(state, 0x0009, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 3. QAM mode detection mode(None) */ -+ ret = lgdt3306a_read_reg(state, 0x0009, &val); -+ val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */ -+ ret = lgdt3306a_write_reg(state, 0x0009, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 4. ADC sampling frequency rate(2x sampling) */ -+ ret = lgdt3306a_read_reg(state, 0x000d, &val); -+ val &= 0xbf; /* SAMPLING4XFEN=0 */ -+ ret = lgdt3306a_write_reg(state, 0x000d, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+#if 0 -+ /* FGR - disable any AICC filtering, testing only */ -+ -+ ret = lgdt3306a_write_reg(state, 0x0024, 0x00); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* AICCFIXFREQ0 NT N-1(Video rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x002e, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002f, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0030, 0x00); -+ -+ /* AICCFIXFREQ1 NT N-1(Audio rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x002b, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002c, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002d, 0x00); -+ -+ /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x0028, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0029, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002a, 0x00); -+ -+ /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x0025, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0026, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0027, 0x00); -+ -+#else -+ /* FGR - this works well for HVR-1955,1975 */ -+ -+ /* 5. AICCOPMODE NT N-1 Adj. */ -+ ret = lgdt3306a_write_reg(state, 0x0024, 0x5A); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* AICCFIXFREQ0 NT N-1(Video rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x002e, 0x5A); -+ ret = lgdt3306a_write_reg(state, 0x002f, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0030, 0x00); -+ -+ /* AICCFIXFREQ1 NT N-1(Audio rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x002b, 0x36); -+ ret = lgdt3306a_write_reg(state, 0x002c, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002d, 0x00); -+ -+ /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x0028, 0x2A); -+ ret = lgdt3306a_write_reg(state, 0x0029, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x002a, 0x00); -+ -+ /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ -+ ret = lgdt3306a_write_reg(state, 0x0025, 0x06); -+ ret = lgdt3306a_write_reg(state, 0x0026, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x0027, 0x00); -+#endif -+ -+ ret = lgdt3306a_read_reg(state, 0x001e, &val); -+ val &= 0x0f; -+ val |= 0xa0; -+ ret = lgdt3306a_write_reg(state, 0x001e, val); -+ -+ ret = lgdt3306a_write_reg(state, 0x0022, 0x08); -+ -+ ret = lgdt3306a_write_reg(state, 0x0023, 0xFF); -+ -+ ret = lgdt3306a_read_reg(state, 0x211f, &val); -+ val &= 0xef; -+ ret = lgdt3306a_write_reg(state, 0x211f, val); -+ -+ ret = lgdt3306a_write_reg(state, 0x2173, 0x01); -+ -+ ret = lgdt3306a_read_reg(state, 0x1061, &val); -+ val &= 0xf8; -+ val |= 0x04; -+ ret = lgdt3306a_write_reg(state, 0x1061, val); -+ -+ ret = lgdt3306a_read_reg(state, 0x103d, &val); -+ val &= 0xcf; -+ ret = lgdt3306a_write_reg(state, 0x103d, val); -+ -+ ret = lgdt3306a_write_reg(state, 0x2122, 0x40); -+ -+ ret = lgdt3306a_read_reg(state, 0x2141, &val); -+ val &= 0x3f; -+ ret = lgdt3306a_write_reg(state, 0x2141, val); -+ -+ ret = lgdt3306a_read_reg(state, 0x2135, &val); -+ val &= 0x0f; -+ val |= 0x70; -+ ret = lgdt3306a_write_reg(state, 0x2135, val); -+ -+ ret = lgdt3306a_read_reg(state, 0x0003, &val); -+ val &= 0xf7; -+ ret = lgdt3306a_write_reg(state, 0x0003, val); -+ -+ ret = lgdt3306a_read_reg(state, 0x001c, &val); -+ val &= 0x7f; -+ ret = lgdt3306a_write_reg(state, 0x001c, val); -+ -+ /* 6. EQ step size */ -+ ret = lgdt3306a_read_reg(state, 0x2179, &val); -+ val &= 0xf8; -+ ret = lgdt3306a_write_reg(state, 0x2179, val); -+ -+ ret = lgdt3306a_read_reg(state, 0x217a, &val); -+ val &= 0xf8; -+ ret = lgdt3306a_write_reg(state, 0x217a, val); -+ -+ /* 7. Reset */ -+ ret = lgdt3306a_soft_reset(state); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ dbg_info("complete\n"); -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) -+{ -+ u8 val; -+ int ret; -+ -+ dbg_info("modulation=%d\n", modulation); -+ -+ /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ -+ ret = lgdt3306a_write_reg(state, 0x0008, 0x08); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 1a. Spectrum inversion detection to Auto */ -+ ret = lgdt3306a_read_reg(state, 0x0002, &val); -+ val &= 0xfb; /* SPECINV Off */ -+ val |= 0x08; /* SPECINVAUTO On */ -+ ret = lgdt3306a_write_reg(state, 0x0002, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 2. Bandwidth mode for QAM */ -+ ret = lgdt3306a_read_reg(state, 0x0009, &val); -+ val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */ -+ ret = lgdt3306a_write_reg(state, 0x0009, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 3. : 64QAM/256QAM detection(manual, auto) */ -+ ret = lgdt3306a_read_reg(state, 0x0009, &val); -+ val &= 0xfc; -+ val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */ -+ ret = lgdt3306a_write_reg(state, 0x0009, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 3a. : 64QAM/256QAM selection for manual */ -+ ret = lgdt3306a_read_reg(state, 0x101a, &val); -+ val &= 0xf8; -+ if (modulation == QAM_64) -+ val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */ -+ else -+ val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */ -+ -+ ret = lgdt3306a_write_reg(state, 0x101a, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 4. ADC sampling frequency rate(4x sampling) */ -+ ret = lgdt3306a_read_reg(state, 0x000d, &val); -+ val &= 0xbf; -+ val |= 0x40; /* SAMPLING4XFEN=1 */ -+ ret = lgdt3306a_write_reg(state, 0x000d, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 5. No AICC operation in QAM mode */ -+ ret = lgdt3306a_read_reg(state, 0x0024, &val); -+ val &= 0x00; -+ ret = lgdt3306a_write_reg(state, 0x0024, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 6. Reset */ -+ ret = lgdt3306a_soft_reset(state); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ dbg_info("complete\n"); -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_set_modulation(struct lgdt3306a_state *state, -+ struct dtv_frontend_properties *p) -+{ -+ int ret; -+ -+ dbg_info("\n"); -+ -+ switch (p->modulation) { -+ case VSB_8: -+ ret = lgdt3306a_set_vsb(state); -+ break; -+ case QAM_64: -+ ret = lgdt3306a_set_qam(state, QAM_64); -+ break; -+ case QAM_256: -+ ret = lgdt3306a_set_qam(state, QAM_256); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ state->current_modulation = p->modulation; -+ -+fail: -+ return ret; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int lgdt3306a_agc_setup(struct lgdt3306a_state *state, -+ struct dtv_frontend_properties *p) -+{ -+ /* TODO: anything we want to do here??? */ -+ dbg_info("\n"); -+ -+ switch (p->modulation) { -+ case VSB_8: -+ break; -+ case QAM_64: -+ case QAM_256: -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int lgdt3306a_set_inversion(struct lgdt3306a_state *state, -+ int inversion) -+{ -+ int ret; -+ -+ dbg_info("(%d)\n", inversion); -+ -+ ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0); -+ return ret; -+} -+ -+static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state, -+ int enabled) -+{ -+ int ret; -+ -+ dbg_info("(%d)\n", enabled); -+ -+ /* 0=Manual 1=Auto(QAM only) - SPECINVAUTO=0x04 */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled); -+ return ret; -+} -+ -+static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state, -+ struct dtv_frontend_properties *p, -+ int inversion) -+{ -+ int ret = 0; -+ -+ dbg_info("(%d)\n", inversion); -+#if 0 -+ /* -+ * FGR - spectral_inversion defaults already set for VSB and QAM; -+ * can enable later if desired -+ */ -+ -+ ret = lgdt3306a_set_inversion(state, inversion); -+ -+ switch (p->modulation) { -+ case VSB_8: -+ /* Manual only for VSB */ -+ ret = lgdt3306a_set_inversion_auto(state, 0); -+ break; -+ case QAM_64: -+ case QAM_256: -+ /* Auto ok for QAM */ -+ ret = lgdt3306a_set_inversion_auto(state, 1); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+#endif -+ return ret; -+} -+ -+static int lgdt3306a_set_if(struct lgdt3306a_state *state, -+ struct dtv_frontend_properties *p) -+{ -+ int ret; -+ u16 if_freq_khz; -+ u8 nco1, nco2; -+ -+ switch (p->modulation) { -+ case VSB_8: -+ if_freq_khz = state->cfg->vsb_if_khz; -+ break; -+ case QAM_64: -+ case QAM_256: -+ if_freq_khz = state->cfg->qam_if_khz; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (if_freq_khz) { -+ default: -+ pr_warn("IF=%d KHz is not supportted, 3250 assumed\n", -+ if_freq_khz); -+ /* fallthrough */ -+ case 3250: /* 3.25Mhz */ -+ nco1 = 0x34; -+ nco2 = 0x00; -+ break; -+ case 3500: /* 3.50Mhz */ -+ nco1 = 0x38; -+ nco2 = 0x00; -+ break; -+ case 4000: /* 4.00Mhz */ -+ nco1 = 0x40; -+ nco2 = 0x00; -+ break; -+ case 5000: /* 5.00Mhz */ -+ nco1 = 0x50; -+ nco2 = 0x00; -+ break; -+ case 5380: /* 5.38Mhz */ -+ nco1 = 0x56; -+ nco2 = 0x14; -+ break; -+ } -+ ret = lgdt3306a_write_reg(state, 0x0010, nco1); -+ if (ret) -+ return ret; -+ ret = lgdt3306a_write_reg(state, 0x0011, nco2); -+ if (ret) -+ return ret; -+ -+ dbg_info("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2); -+ -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ if (state->cfg->deny_i2c_rptr) { -+ dbg_info("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr); -+ return 0; -+ } -+ dbg_info("(%d)\n", enable); -+ -+ /* NI2CRPTEN=0x80 */ -+ return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); -+} -+ -+static int lgdt3306a_sleep(struct lgdt3306a_state *state) -+{ -+ int ret; -+ -+ dbg_info("\n"); -+ state->current_frequency = -1; /* force re-tune, when we wake */ -+ -+ ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */ -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_power(state, 0); /* power down */ -+ lg_chkerr(ret); -+ -+fail: -+ return 0; -+} -+ -+static int lgdt3306a_fe_sleep(struct dvb_frontend *fe) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ return lgdt3306a_sleep(state); -+} -+ -+static int lgdt3306a_init(struct dvb_frontend *fe) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ u8 val; -+ int ret; -+ -+ dbg_info("\n"); -+ -+ /* 1. Normal operation mode */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */ -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 2. Spectrum inversion auto detection (Not valid for VSB) */ -+ ret = lgdt3306a_set_inversion_auto(state, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 3. Spectrum inversion(According to the tuner configuration) */ -+ ret = lgdt3306a_set_inversion(state, 1); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 4. Peak-to-peak voltage of ADC input signal */ -+ -+ /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 5. ADC output data capture clock phase */ -+ -+ /* 0=same phase as ADC clock */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 5a. ADC sampling clock source */ -+ -+ /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 6. Automatic PLL set */ -+ -+ /* PLLSETAUTO=0x40; 0=off */ -+ ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ if (state->cfg->xtalMHz == 24) { /* 24MHz */ -+ /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */ -+ ret = lgdt3306a_read_reg(state, 0x0005, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ val &= 0xc0; -+ val |= 0x25; -+ ret = lgdt3306a_write_reg(state, 0x0005, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ ret = lgdt3306a_write_reg(state, 0x0006, 0x64); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */ -+ ret = lgdt3306a_read_reg(state, 0x000d, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ val &= 0xc0; -+ val |= 0x18; -+ ret = lgdt3306a_write_reg(state, 0x000d, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ } else if (state->cfg->xtalMHz == 25) { /* 25MHz */ -+ /* 7. Frequency for PLL output */ -+ ret = lgdt3306a_read_reg(state, 0x0005, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ val &= 0xc0; -+ val |= 0x25; -+ ret = lgdt3306a_write_reg(state, 0x0005, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ ret = lgdt3306a_write_reg(state, 0x0006, 0x64); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */ -+ ret = lgdt3306a_read_reg(state, 0x000d, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ val &= 0xc0; -+ val |= 0x19; -+ ret = lgdt3306a_write_reg(state, 0x000d, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ } else { -+ pr_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz); -+ } -+#if 0 -+ ret = lgdt3306a_write_reg(state, 0x000e, 0x00); -+ ret = lgdt3306a_write_reg(state, 0x000f, 0x00); -+#endif -+ -+ /* 9. Center frequency of input signal of ADC */ -+ ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */ -+ ret = lgdt3306a_write_reg(state, 0x0011, 0x00); -+ -+ /* 10. Fixed gain error value */ -+ ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */ -+ -+ /* 10a. VSB TR BW gear shift initial step */ -+ ret = lgdt3306a_read_reg(state, 0x103c, &val); -+ val &= 0x0f; -+ val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */ -+ ret = lgdt3306a_write_reg(state, 0x103c, val); -+ -+ /* 10b. Timing offset calibration in low temperature for VSB */ -+ ret = lgdt3306a_read_reg(state, 0x103d, &val); -+ val &= 0xfc; -+ val |= 0x03; -+ ret = lgdt3306a_write_reg(state, 0x103d, val); -+ -+ /* 10c. Timing offset calibration in low temperature for QAM */ -+ ret = lgdt3306a_read_reg(state, 0x1036, &val); -+ val &= 0xf0; -+ val |= 0x0c; -+ ret = lgdt3306a_write_reg(state, 0x1036, val); -+ -+ /* 11. Using the imaginary part of CIR in CIR loading */ -+ ret = lgdt3306a_read_reg(state, 0x211f, &val); -+ val &= 0xef; /* do not use imaginary of CIR */ -+ ret = lgdt3306a_write_reg(state, 0x211f, val); -+ -+ /* 12. Control of no signal detector function */ -+ ret = lgdt3306a_read_reg(state, 0x2849, &val); -+ val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */ -+ ret = lgdt3306a_write_reg(state, 0x2849, val); -+ -+ /* FGR - put demod in some known mode */ -+ ret = lgdt3306a_set_vsb(state); -+ -+ /* 13. TP stream format */ -+ ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); -+ -+ /* 14. disable output buses */ -+ ret = lgdt3306a_mpeg_tristate(state, 1); -+ -+ /* 15. Sleep (in reset) */ -+ ret = lgdt3306a_sleep(state); -+ lg_chkerr(ret); -+ -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_set_parameters(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ int ret; -+ -+ dbg_info("(%d, %d)\n", p->frequency, p->modulation); -+ -+ if (state->current_frequency == p->frequency && -+ state->current_modulation == p->modulation) { -+ dbg_info(" (already set, skipping ...)\n"); -+ return 0; -+ } -+ state->current_frequency = -1; -+ state->current_modulation = -1; -+ -+ ret = lgdt3306a_power(state, 1); /* power up */ -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ if (fe->ops.tuner_ops.set_params) { -+ ret = fe->ops.tuner_ops.set_params(fe); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+#if 0 -+ if (lg_chkerr(ret)) -+ goto fail; -+ state->current_frequency = p->frequency; -+#endif -+ } -+ -+ ret = lgdt3306a_set_modulation(state, p); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_agc_setup(state, p); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_set_if(state, p); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_spectral_inversion(state, p, -+ state->cfg->spectral_inversion ? 1 : 0); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_mpeg_mode_polarity(state, -+ state->cfg->tpclk_edge, -+ state->cfg->tpvalid_polarity); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */ -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ ret = lgdt3306a_soft_reset(state); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+#ifdef DBG_DUMP -+ lgdt3306a_DumpAllRegs(state); -+#endif -+ state->current_frequency = p->frequency; -+fail: -+ return ret; -+} -+ -+static int lgdt3306a_get_frontend(struct dvb_frontend *fe) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ -+ dbg_info("(%u, %d)\n", -+ state->current_frequency, state->current_modulation); -+ -+ p->modulation = state->current_modulation; -+ p->frequency = state->current_frequency; -+ return 0; -+} -+ -+static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe) -+{ -+#if 1 -+ return DVBFE_ALGO_CUSTOM; -+#else -+ return DVBFE_ALGO_HW; -+#endif -+} -+ -+/* ------------------------------------------------------------------------ */ -+static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state) -+{ -+ u8 val; -+ int ret; -+ u8 snrRef, maxPowerMan, nCombDet; -+ u16 fbDlyCir; -+ -+ ret = lgdt3306a_read_reg(state, 0x21a1, &val); -+ if (ret) -+ return ret; -+ snrRef = val & 0x3f; -+ -+ ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan); -+ if (ret) -+ return ret; -+ -+ ret = lgdt3306a_read_reg(state, 0x2191, &val); -+ if (ret) -+ return ret; -+ nCombDet = (val & 0x80) >> 7; -+ -+ ret = lgdt3306a_read_reg(state, 0x2180, &val); -+ if (ret) -+ return ret; -+ fbDlyCir = (val & 0x03) << 8; -+ -+ ret = lgdt3306a_read_reg(state, 0x2181, &val); -+ if (ret) -+ return ret; -+ fbDlyCir |= val; -+ -+ dbg_info("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n", -+ snrRef, maxPowerMan, nCombDet, fbDlyCir); -+ -+ /* Carrier offset sub loop bandwidth */ -+ ret = lgdt3306a_read_reg(state, 0x1061, &val); -+ if (ret) -+ return ret; -+ val &= 0xf8; -+ if ((snrRef > 18) && (maxPowerMan > 0x68) -+ && (nCombDet == 0x01) -+ && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) { -+ /* SNR is over 18dB and no ghosting */ -+ val |= 0x00; /* final bandwidth = 0 */ -+ } else { -+ val |= 0x04; /* final bandwidth = 4 */ -+ } -+ ret = lgdt3306a_write_reg(state, 0x1061, val); -+ if (ret) -+ return ret; -+ -+ /* Adjust Notch Filter */ -+ ret = lgdt3306a_read_reg(state, 0x0024, &val); -+ if (ret) -+ return ret; -+ val &= 0x0f; -+ if (nCombDet == 0) { /* Turn on the Notch Filter */ -+ val |= 0x50; -+ } -+ ret = lgdt3306a_write_reg(state, 0x0024, val); -+ if (ret) -+ return ret; -+ -+ /* VSB Timing Recovery output normalization */ -+ ret = lgdt3306a_read_reg(state, 0x103d, &val); -+ if (ret) -+ return ret; -+ val &= 0xcf; -+ val |= 0x20; -+ ret = lgdt3306a_write_reg(state, 0x103d, val); -+ -+ return ret; -+} -+ -+static enum lgdt3306a_modulation -+lgdt3306a_check_oper_mode(struct lgdt3306a_state *state) -+{ -+ u8 val = 0; -+ int ret; -+ -+ ret = lgdt3306a_read_reg(state, 0x0081, &val); -+ if (ret) -+ goto err; -+ -+ if (val & 0x80) { -+ dbg_info("VSB\n"); -+ return LG3306_VSB; -+ } -+ if (val & 0x08) { -+ ret = lgdt3306a_read_reg(state, 0x00a6, &val); -+ if (ret) -+ goto err; -+ val = val >> 2; -+ if (val & 0x01) { -+ dbg_info("QAM256\n"); -+ return LG3306_QAM256; -+ } -+ dbg_info("QAM64\n"); -+ return LG3306_QAM64; -+ } -+err: -+ pr_warn("UNKNOWN\n"); -+ return LG3306_UNKNOWN_MODE; -+} -+ -+static enum lgdt3306a_lock_status -+lgdt3306a_check_lock_status(struct lgdt3306a_state *state, -+ enum lgdt3306a_lock_check whatLock) -+{ -+ u8 val = 0; -+ int ret; -+ enum lgdt3306a_modulation modeOper; -+ enum lgdt3306a_lock_status lockStatus; -+ -+ modeOper = LG3306_UNKNOWN_MODE; -+ -+ switch (whatLock) { -+ case LG3306_SYNC_LOCK: -+ { -+ ret = lgdt3306a_read_reg(state, 0x00a6, &val); -+ if (ret) -+ return ret; -+ -+ if ((val & 0x80) == 0x80) -+ lockStatus = LG3306_LOCK; -+ else -+ lockStatus = LG3306_UNLOCK; -+ -+ dbg_info("SYNC_LOCK=%x\n", lockStatus); -+ break; -+ } -+ case LG3306_AGC_LOCK: -+ { -+ ret = lgdt3306a_read_reg(state, 0x0080, &val); -+ if (ret) -+ return ret; -+ -+ if ((val & 0x40) == 0x40) -+ lockStatus = LG3306_LOCK; -+ else -+ lockStatus = LG3306_UNLOCK; -+ -+ dbg_info("AGC_LOCK=%x\n", lockStatus); -+ break; -+ } -+ case LG3306_TR_LOCK: -+ { -+ modeOper = lgdt3306a_check_oper_mode(state); -+ if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { -+ ret = lgdt3306a_read_reg(state, 0x1094, &val); -+ if (ret) -+ return ret; -+ -+ if ((val & 0x80) == 0x80) -+ lockStatus = LG3306_LOCK; -+ else -+ lockStatus = LG3306_UNLOCK; -+ } else -+ lockStatus = LG3306_UNKNOWN_LOCK; -+ -+ dbg_info("TR_LOCK=%x\n", lockStatus); -+ break; -+ } -+ case LG3306_FEC_LOCK: -+ { -+ modeOper = lgdt3306a_check_oper_mode(state); -+ if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { -+ ret = lgdt3306a_read_reg(state, 0x0080, &val); -+ if (ret) -+ return ret; -+ -+ if ((val & 0x10) == 0x10) -+ lockStatus = LG3306_LOCK; -+ else -+ lockStatus = LG3306_UNLOCK; -+ } else -+ lockStatus = LG3306_UNKNOWN_LOCK; -+ -+ dbg_info("FEC_LOCK=%x\n", lockStatus); -+ break; -+ } -+ -+ default: -+ lockStatus = LG3306_UNKNOWN_LOCK; -+ pr_warn("UNKNOWN whatLock=%d\n", whatLock); -+ break; -+ } -+ -+ return lockStatus; -+} -+ -+static enum lgdt3306a_neverlock_status -+lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state) -+{ -+ u8 val = 0; -+ int ret; -+ enum lgdt3306a_neverlock_status lockStatus; -+ -+ ret = lgdt3306a_read_reg(state, 0x0080, &val); -+ if (ret) -+ return ret; -+ lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03); -+ -+ dbg_info("NeverLock=%d", lockStatus); -+ -+ return lockStatus; -+} -+ -+static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state) -+{ -+ u8 val = 0; -+ int ret; -+ u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus; -+ -+ /* Channel variation */ -+ ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ); -+ if (ret) -+ return ret; -+ -+ /* SNR of Frame sync */ -+ ret = lgdt3306a_read_reg(state, 0x21a1, &val); -+ if (ret) -+ return ret; -+ snrRef = val & 0x3f; -+ -+ /* Strong Main CIR */ -+ ret = lgdt3306a_read_reg(state, 0x2199, &val); -+ if (ret) -+ return ret; -+ mainStrong = (val & 0x40) >> 6; -+ -+ ret = lgdt3306a_read_reg(state, 0x0090, &val); -+ if (ret) -+ return ret; -+ aiccrejStatus = (val & 0xf0) >> 4; -+ -+ dbg_info("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n", -+ snrRef, mainStrong, aiccrejStatus, currChDiffACQ); -+ -+#if 0 -+ /* Dynamic ghost exists */ -+ if ((mainStrong == 0) && (currChDiffACQ > 0x70)) -+#endif -+ if (mainStrong == 0) { -+ ret = lgdt3306a_read_reg(state, 0x2135, &val); -+ if (ret) -+ return ret; -+ val &= 0x0f; -+ val |= 0xa0; -+ ret = lgdt3306a_write_reg(state, 0x2135, val); -+ if (ret) -+ return ret; -+ -+ ret = lgdt3306a_read_reg(state, 0x2141, &val); -+ if (ret) -+ return ret; -+ val &= 0x3f; -+ val |= 0x80; -+ ret = lgdt3306a_write_reg(state, 0x2141, val); -+ if (ret) -+ return ret; -+ -+ ret = lgdt3306a_write_reg(state, 0x2122, 0x70); -+ if (ret) -+ return ret; -+ } else { /* Weak ghost or static channel */ -+ ret = lgdt3306a_read_reg(state, 0x2135, &val); -+ if (ret) -+ return ret; -+ val &= 0x0f; -+ val |= 0x70; -+ ret = lgdt3306a_write_reg(state, 0x2135, val); -+ if (ret) -+ return ret; -+ -+ ret = lgdt3306a_read_reg(state, 0x2141, &val); -+ if (ret) -+ return ret; -+ val &= 0x3f; -+ val |= 0x40; -+ ret = lgdt3306a_write_reg(state, 0x2141, val); -+ if (ret) -+ return ret; -+ -+ ret = lgdt3306a_write_reg(state, 0x2122, 0x40); -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ -+static enum lgdt3306a_lock_status -+lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state) -+{ -+ enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK; -+ int i; -+ -+ for (i = 0; i < 2; i++) { -+ msleep(30); -+ -+ syncLockStatus = lgdt3306a_check_lock_status(state, -+ LG3306_SYNC_LOCK); -+ -+ if (syncLockStatus == LG3306_LOCK) { -+ dbg_info("locked(%d)\n", i); -+ return LG3306_LOCK; -+ } -+ } -+ dbg_info("not locked\n"); -+ return LG3306_UNLOCK; -+} -+ -+static enum lgdt3306a_lock_status -+lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state) -+{ -+ enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK; -+ int i; -+ -+ for (i = 0; i < 2; i++) { -+ msleep(30); -+ -+ FECLockStatus = lgdt3306a_check_lock_status(state, -+ LG3306_FEC_LOCK); -+ -+ if (FECLockStatus == LG3306_LOCK) { -+ dbg_info("locked(%d)\n", i); -+ return FECLockStatus; -+ } -+ } -+ dbg_info("not locked\n"); -+ return FECLockStatus; -+} -+ -+static enum lgdt3306a_neverlock_status -+lgdt3306a_neverlock_poll(struct lgdt3306a_state *state) -+{ -+ enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL; -+ int i; -+ -+ for (i = 0; i < 5; i++) { -+ msleep(30); -+ -+ NLLockStatus = lgdt3306a_check_neverlock_status(state); -+ -+ if (NLLockStatus == LG3306_NL_LOCK) { -+ dbg_info("NL_LOCK(%d)\n", i); -+ return NLLockStatus; -+ } -+ } -+ dbg_info("NLLockStatus=%d\n", NLLockStatus); -+ return NLLockStatus; -+} -+ -+static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state) -+{ -+ u8 val; -+ int ret; -+ -+ ret = lgdt3306a_read_reg(state, 0x00fa, &val); -+ if (ret) -+ return ret; -+ -+ return val; -+} -+ -+static const u32 valx_x10[] = { -+ 10, 11, 13, 15, 17, 20, 25, 33, 41, 50, 59, 73, 87, 100 -+}; -+static const u32 log10x_x1000[] = { -+ 0, 41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 -+}; -+ -+static u32 log10_x1000(u32 x) -+{ -+ u32 diff_val, step_val, step_log10; -+ u32 log_val = 0; -+ u32 i; -+ -+ if (x <= 0) -+ return -1000000; /* signal error */ -+ -+ if (x == 10) -+ return 0; /* log(1)=0 */ -+ -+ if (x < 10) { -+ while (x < 10) { -+ x = x * 10; -+ log_val--; -+ } -+ } else { /* x > 10 */ -+ while (x >= 100) { -+ x = x / 10; -+ log_val++; -+ } -+ } -+ log_val *= 1000; -+ -+ if (x == 10) /* was our input an exact multiple of 10 */ -+ return log_val; /* don't need to interpolate */ -+ -+ /* find our place on the log curve */ -+ for (i = 1; i < ARRAY_SIZE(valx_x10); i++) { -+ if (valx_x10[i] >= x) -+ break; -+ } -+ if (i == ARRAY_SIZE(valx_x10)) -+ return log_val + log10x_x1000[i - 1]; -+ -+ diff_val = x - valx_x10[i-1]; -+ step_val = valx_x10[i] - valx_x10[i - 1]; -+ step_log10 = log10x_x1000[i] - log10x_x1000[i - 1]; -+ -+ /* do a linear interpolation to get in-between values */ -+ return log_val + log10x_x1000[i - 1] + -+ ((diff_val*step_log10) / step_val); -+} -+ -+static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state) -+{ -+ u32 mse; /* Mean-Square Error */ -+ u32 pwr; /* Constelation power */ -+ u32 snr_x100; -+ -+ mse = (read_reg(state, 0x00ec) << 8) | -+ (read_reg(state, 0x00ed)); -+ pwr = (read_reg(state, 0x00e8) << 8) | -+ (read_reg(state, 0x00e9)); -+ -+ if (mse == 0) /* no signal */ -+ return 0; -+ -+ snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000; -+ dbg_info("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100); -+ -+ return snr_x100; -+} -+ -+static enum lgdt3306a_lock_status -+lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state) -+{ -+ int ret; -+ u8 cnt = 0; -+ u8 packet_error; -+ u32 snr; -+ -+ for (cnt = 0; cnt < 10; cnt++) { -+ if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) { -+ dbg_info("no sync lock!\n"); -+ return LG3306_UNLOCK; -+ } -+ -+ msleep(20); -+ ret = lgdt3306a_pre_monitoring(state); -+ if (ret) -+ break; -+ -+ packet_error = lgdt3306a_get_packet_error(state); -+ snr = lgdt3306a_calculate_snr_x100(state); -+ dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); -+ -+ if ((snr >= 1500) && (packet_error < 0xff)) -+ return LG3306_LOCK; -+ } -+ -+ dbg_info("not locked!\n"); -+ return LG3306_UNLOCK; -+} -+ -+static enum lgdt3306a_lock_status -+lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state) -+{ -+ u8 cnt; -+ u8 packet_error; -+ u32 snr; -+ -+ for (cnt = 0; cnt < 10; cnt++) { -+ if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) { -+ dbg_info("no fec lock!\n"); -+ return LG3306_UNLOCK; -+ } -+ -+ msleep(20); -+ -+ packet_error = lgdt3306a_get_packet_error(state); -+ snr = lgdt3306a_calculate_snr_x100(state); -+ dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); -+ -+ if ((snr >= 1500) && (packet_error < 0xff)) -+ return LG3306_LOCK; -+ } -+ -+ dbg_info("not locked!\n"); -+ return LG3306_UNLOCK; -+} -+ -+static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ u16 strength = 0; -+ int ret = 0; -+ -+ if (fe->ops.tuner_ops.get_rf_strength) { -+ ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength); -+ if (ret == 0) -+ dbg_info("strength=%d\n", strength); -+ else -+ dbg_info("fe->ops.tuner_ops.get_rf_strength() failed\n"); -+ } -+ -+ *status = 0; -+ if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) { -+ *status |= FE_HAS_SIGNAL; -+ *status |= FE_HAS_CARRIER; -+ -+ switch (state->current_modulation) { -+ case QAM_256: -+ case QAM_64: -+ if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { -+ *status |= FE_HAS_VITERBI; -+ *status |= FE_HAS_SYNC; -+ -+ *status |= FE_HAS_LOCK; -+ } -+ break; -+ case VSB_8: -+ if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) { -+ *status |= FE_HAS_VITERBI; -+ *status |= FE_HAS_SYNC; -+ -+ *status |= FE_HAS_LOCK; -+ -+ ret = lgdt3306a_monitor_vsb(state); -+ } -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ } -+ return ret; -+} -+ -+ -+static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ state->snr = lgdt3306a_calculate_snr_x100(state); -+ /* report SNR in dB * 10 */ -+ *snr = state->snr/10; -+ -+ return 0; -+} -+ -+static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, -+ u16 *strength) -+{ -+ /* -+ * Calculate some sort of "strength" from SNR -+ */ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ u16 snr; /* snr_x10 */ -+ int ret; -+ u32 ref_snr; /* snr*100 */ -+ u32 str; -+ -+ *strength = 0; -+ -+ switch (state->current_modulation) { -+ case VSB_8: -+ ref_snr = 1600; /* 16dB */ -+ break; -+ case QAM_64: -+ ref_snr = 2200; /* 22dB */ -+ break; -+ case QAM_256: -+ ref_snr = 2800; /* 28dB */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ret = fe->ops.read_snr(fe, &snr); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ if (state->snr <= (ref_snr - 100)) -+ str = 0; -+ else if (state->snr <= ref_snr) -+ str = (0xffff * 65) / 100; /* 65% */ -+ else { -+ str = state->snr - ref_snr; -+ str /= 50; -+ str += 78; /* 78%-100% */ -+ if (str > 100) -+ str = 100; -+ str = (0xffff * str) / 100; -+ } -+ *strength = (u16)str; -+ dbg_info("strength=%u\n", *strength); -+ -+fail: -+ return ret; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ u32 tmp; -+ -+ *ber = 0; -+#if 1 -+ /* FGR - FIXME - I don't know what value is expected by dvb_core -+ * what is the scale of the value?? */ -+ tmp = read_reg(state, 0x00fc); /* NBERVALUE[24-31] */ -+ tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */ -+ tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */ -+ tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */ -+ *ber = tmp; -+ dbg_info("ber=%u\n", tmp); -+#endif -+ return 0; -+} -+ -+static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ *ucblocks = 0; -+#if 1 -+ /* FGR - FIXME - I don't know what value is expected by dvb_core -+ * what happens when value wraps? */ -+ *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */ -+ dbg_info("ucblocks=%u\n", *ucblocks); -+#endif -+ -+ return 0; -+} -+ -+static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, unsigned int *delay, -+ fe_status_t *status) -+{ -+ int ret = 0; -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ dbg_info("re_tune=%u\n", re_tune); -+ -+ if (re_tune) { -+ state->current_frequency = -1; /* force re-tune */ -+ ret = lgdt3306a_set_parameters(fe); -+ if (ret != 0) -+ return ret; -+ } -+ *delay = 125; -+ ret = lgdt3306a_read_status(fe, status); -+ -+ return ret; -+} -+ -+static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings -+ *fe_tune_settings) -+{ -+ fe_tune_settings->min_delay_ms = 100; -+ dbg_info("\n"); -+ return 0; -+} -+ -+static int lgdt3306a_search(struct dvb_frontend *fe) -+{ -+ fe_status_t status = 0; -+ int i, ret; -+ -+ /* set frontend */ -+ ret = lgdt3306a_set_parameters(fe); -+ if (ret) -+ goto error; -+ -+ /* wait frontend lock */ -+ for (i = 20; i > 0; i--) { -+ dbg_info(": loop=%d\n", i); -+ msleep(50); -+ ret = lgdt3306a_read_status(fe, &status); -+ if (ret) -+ goto error; -+ -+ if (status & FE_HAS_LOCK) -+ break; -+ } -+ -+ /* check if we have a valid signal */ -+ if (status & FE_HAS_LOCK) -+ return DVBFE_ALGO_SEARCH_SUCCESS; -+ else -+ return DVBFE_ALGO_SEARCH_AGAIN; -+ -+error: -+ dbg_info("failed (%d)\n", ret); -+ return DVBFE_ALGO_SEARCH_ERROR; -+} -+ -+static void lgdt3306a_release(struct dvb_frontend *fe) -+{ -+ struct lgdt3306a_state *state = fe->demodulator_priv; -+ -+ dbg_info("\n"); -+ kfree(state); -+} -+ -+static struct dvb_frontend_ops lgdt3306a_ops; -+ -+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, -+ struct i2c_adapter *i2c_adap) -+{ -+ struct lgdt3306a_state *state = NULL; -+ int ret; -+ u8 val; -+ -+ dbg_info("(%d-%04x)\n", -+ i2c_adap ? i2c_adapter_id(i2c_adap) : 0, -+ config ? config->i2c_addr : 0); -+ -+ state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL); -+ if (state == NULL) -+ goto fail; -+ -+ state->cfg = config; -+ state->i2c_adap = i2c_adap; -+ -+ memcpy(&state->frontend.ops, &lgdt3306a_ops, -+ sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ -+ /* verify that we're talking to a lg3306a */ -+ /* FGR - NOTE - there is no obvious ChipId to check; we check -+ * some "known" bits after reset, but it's still just a guess */ -+ ret = lgdt3306a_read_reg(state, 0x0000, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ if ((val & 0x74) != 0x74) { -+ pr_warn("expected 0x74, got 0x%x\n", (val & 0x74)); -+#if 0 -+ /* FIXME - re-enable when we know this is right */ -+ goto fail; -+#endif -+ } -+ ret = lgdt3306a_read_reg(state, 0x0001, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ if ((val & 0xf6) != 0xc6) { -+ pr_warn("expected 0xc6, got 0x%x\n", (val & 0xf6)); -+#if 0 -+ /* FIXME - re-enable when we know this is right */ -+ goto fail; -+#endif -+ } -+ ret = lgdt3306a_read_reg(state, 0x0002, &val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ if ((val & 0x73) != 0x03) { -+ pr_warn("expected 0x03, got 0x%x\n", (val & 0x73)); -+#if 0 -+ /* FIXME - re-enable when we know this is right */ -+ goto fail; -+#endif -+ } -+ -+ state->current_frequency = -1; -+ state->current_modulation = -1; -+ -+ lgdt3306a_sleep(state); -+ -+ return &state->frontend; -+ -+fail: -+ pr_warn("unable to detect LGDT3306A hardware\n"); -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(lgdt3306a_attach); -+ -+#ifdef DBG_DUMP -+ -+static const short regtab[] = { -+ 0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */ -+ 0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */ -+ 0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */ -+ 0x0003, /* AGCRFOUT */ -+ 0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */ -+ 0x0005, /* PLLINDIVSE */ -+ 0x0006, /* PLLCTRL[7:0] 11100001 */ -+ 0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */ -+ 0x0008, /* STDOPMODE[7:0] 10000000 */ -+ 0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */ -+ 0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */ -+ 0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */ -+ 0x000d, /* x SAMPLING4 */ -+ 0x000e, /* SAMFREQ[15:8] 00000000 */ -+ 0x000f, /* SAMFREQ[7:0] 00000000 */ -+ 0x0010, /* IFFREQ[15:8] 01100000 */ -+ 0x0011, /* IFFREQ[7:0] 00000000 */ -+ 0x0012, /* AGCEN AGCREFMO */ -+ 0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */ -+ 0x0014, /* AGCFIXVALUE[7:0] 01111111 */ -+ 0x0015, /* AGCREF[15:8] 00001010 */ -+ 0x0016, /* AGCREF[7:0] 11100100 */ -+ 0x0017, /* AGCDELAY[7:0] 00100000 */ -+ 0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */ -+ 0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */ -+ 0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */ -+ 0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */ -+ 0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */ -+ 0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */ -+ 0x0020, /* AICCDETTH[15:8] 01111100 */ -+ 0x0021, /* AICCDETTH[7:0] 00000000 */ -+ 0x0022, /* AICCOFFTH[15:8] 00000101 */ -+ 0x0023, /* AICCOFFTH[7:0] 11100000 */ -+ 0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */ -+ 0x0025, /* AICCFIXFREQ3[23:16] 00000000 */ -+ 0x0026, /* AICCFIXFREQ3[15:8] 00000000 */ -+ 0x0027, /* AICCFIXFREQ3[7:0] 00000000 */ -+ 0x0028, /* AICCFIXFREQ2[23:16] 00000000 */ -+ 0x0029, /* AICCFIXFREQ2[15:8] 00000000 */ -+ 0x002a, /* AICCFIXFREQ2[7:0] 00000000 */ -+ 0x002b, /* AICCFIXFREQ1[23:16] 00000000 */ -+ 0x002c, /* AICCFIXFREQ1[15:8] 00000000 */ -+ 0x002d, /* AICCFIXFREQ1[7:0] 00000000 */ -+ 0x002e, /* AICCFIXFREQ0[23:16] 00000000 */ -+ 0x002f, /* AICCFIXFREQ0[15:8] 00000000 */ -+ 0x0030, /* AICCFIXFREQ0[7:0] 00000000 */ -+ 0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */ -+ 0x0032, /* DAGC1STEN DAGC1STER */ -+ 0x0033, /* DAGC1STREF[15:8] 00001010 */ -+ 0x0034, /* DAGC1STREF[7:0] 11100100 */ -+ 0x0035, /* DAGC2NDE */ -+ 0x0036, /* DAGC2NDREF[15:8] 00001010 */ -+ 0x0037, /* DAGC2NDREF[7:0] 10000000 */ -+ 0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */ -+ 0x003d, /* 1'b1 SAMGEARS */ -+ 0x0040, /* SAMLFGMA */ -+ 0x0041, /* SAMLFBWM */ -+ 0x0044, /* 1'b1 CRGEARSHE */ -+ 0x0045, /* CRLFGMAN */ -+ 0x0046, /* CFLFBWMA */ -+ 0x0047, /* CRLFGMAN */ -+ 0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */ -+ 0x0049, /* CRLFBWMA */ -+ 0x004a, /* CRLFBWMA */ -+ 0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */ -+ 0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */ -+ 0x0071, /* TPSENB TPSSOPBITE */ -+ 0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */ -+ 0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */ -+ 0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */ -+ 0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */ -+ 0x0078, /* NBERPOLY[31:24] 00000000 */ -+ 0x0079, /* NBERPOLY[23:16] 00000000 */ -+ 0x007a, /* NBERPOLY[15:8] 00000000 */ -+ 0x007b, /* NBERPOLY[7:0] 00000000 */ -+ 0x007c, /* NBERPED[31:24] 00000000 */ -+ 0x007d, /* NBERPED[23:16] 00000000 */ -+ 0x007e, /* NBERPED[15:8] 00000000 */ -+ 0x007f, /* NBERPED[7:0] 00000000 */ -+ 0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */ -+ 0x0085, /* SPECINVST */ -+ 0x0088, /* SYSLOCKTIME[15:8] */ -+ 0x0089, /* SYSLOCKTIME[7:0] */ -+ 0x008c, /* FECLOCKTIME[15:8] */ -+ 0x008d, /* FECLOCKTIME[7:0] */ -+ 0x008e, /* AGCACCOUT[15:8] */ -+ 0x008f, /* AGCACCOUT[7:0] */ -+ 0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */ -+ 0x0091, /* AICCVSYNC */ -+ 0x009c, /* CARRFREQOFFSET[15:8] */ -+ 0x009d, /* CARRFREQOFFSET[7:0] */ -+ 0x00a1, /* SAMFREQOFFSET[23:16] */ -+ 0x00a2, /* SAMFREQOFFSET[15:8] */ -+ 0x00a3, /* SAMFREQOFFSET[7:0] */ -+ 0x00a6, /* SYNCLOCK SYNCLOCKH */ -+#if 0 /* covered elsewhere */ -+ 0x00e8, /* CONSTPWR[15:8] */ -+ 0x00e9, /* CONSTPWR[7:0] */ -+ 0x00ea, /* BMSE[15:8] */ -+ 0x00eb, /* BMSE[7:0] */ -+ 0x00ec, /* MSE[15:8] */ -+ 0x00ed, /* MSE[7:0] */ -+ 0x00ee, /* CONSTI[7:0] */ -+ 0x00ef, /* CONSTQ[7:0] */ -+#endif -+ 0x00f4, /* TPIFTPERRCNT[7:0] */ -+ 0x00f5, /* TPCORREC */ -+ 0x00f6, /* VBBER[15:8] */ -+ 0x00f7, /* VBBER[7:0] */ -+ 0x00f8, /* VABER[15:8] */ -+ 0x00f9, /* VABER[7:0] */ -+ 0x00fa, /* TPERRCNT[7:0] */ -+ 0x00fb, /* NBERLOCK x x x x x x x */ -+ 0x00fc, /* NBERVALUE[31:24] */ -+ 0x00fd, /* NBERVALUE[23:16] */ -+ 0x00fe, /* NBERVALUE[15:8] */ -+ 0x00ff, /* NBERVALUE[7:0] */ -+ 0x1000, /* 1'b0 WODAGCOU */ -+ 0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */ -+ 0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */ -+ 0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */ -+ 0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */ -+ 0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */ -+ 0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */ -+ 0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */ -+ 0x103f, /* SAMZTEDSE */ -+ 0x105d, /* EQSTATUSE */ -+ 0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */ -+ 0x1060, /* 1'b1 EQSTATUSE */ -+ 0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */ -+ 0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */ -+ 0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */ -+ 0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */ -+ 0x106e, /* x x x x x CREPHNEN_ */ -+ 0x106f, /* CREPHNTH_V[7:0] 00010101 */ -+ 0x1072, /* CRSWEEPN */ -+ 0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */ -+ 0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */ -+ 0x1080, /* DAFTSTATUS[1:0] x x x x x x */ -+ 0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */ -+ 0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */ -+ 0x10b7, /* EQSTATUS_V[1:0] x x x x x x */ -+#if 0 /* SMART_ANT */ -+ 0x1f00, /* MODEDETE */ -+ 0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */ -+ 0x1f03, /* NUMOFANT[7:0] 10000000 */ -+ 0x1f04, /* x SELMASK[6:0] x0000000 */ -+ 0x1f05, /* x SETMASK[6:0] x0000000 */ -+ 0x1f06, /* x TXDATA[6:0] x0000000 */ -+ 0x1f07, /* x CHNUMBER[6:0] x0000000 */ -+ 0x1f09, /* AGCTIME[23:16] 10011000 */ -+ 0x1f0a, /* AGCTIME[15:8] 10010110 */ -+ 0x1f0b, /* AGCTIME[7:0] 10000000 */ -+ 0x1f0c, /* ANTTIME[31:24] 00000000 */ -+ 0x1f0d, /* ANTTIME[23:16] 00000011 */ -+ 0x1f0e, /* ANTTIME[15:8] 10010000 */ -+ 0x1f0f, /* ANTTIME[7:0] 10010000 */ -+ 0x1f11, /* SYNCTIME[23:16] 10011000 */ -+ 0x1f12, /* SYNCTIME[15:8] 10010110 */ -+ 0x1f13, /* SYNCTIME[7:0] 10000000 */ -+ 0x1f14, /* SNRTIME[31:24] 00000001 */ -+ 0x1f15, /* SNRTIME[23:16] 01111101 */ -+ 0x1f16, /* SNRTIME[15:8] 01111000 */ -+ 0x1f17, /* SNRTIME[7:0] 01000000 */ -+ 0x1f19, /* FECTIME[23:16] 00000000 */ -+ 0x1f1a, /* FECTIME[15:8] 01110010 */ -+ 0x1f1b, /* FECTIME[7:0] 01110000 */ -+ 0x1f1d, /* FECTHD[7:0] 00000011 */ -+ 0x1f1f, /* SNRTHD[23:16] 00001000 */ -+ 0x1f20, /* SNRTHD[15:8] 01111111 */ -+ 0x1f21, /* SNRTHD[7:0] 10000101 */ -+ 0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */ -+ 0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */ -+ 0x1f82, /* x x x SCANOPCD[4:0] */ -+ 0x1f83, /* x x x x MAINOPCD[3:0] */ -+ 0x1f84, /* x x RXDATA[13:8] */ -+ 0x1f85, /* RXDATA[7:0] */ -+ 0x1f86, /* x x SDTDATA[13:8] */ -+ 0x1f87, /* SDTDATA[7:0] */ -+ 0x1f89, /* ANTSNR[23:16] */ -+ 0x1f8a, /* ANTSNR[15:8] */ -+ 0x1f8b, /* ANTSNR[7:0] */ -+ 0x1f8c, /* x x x x ANTFEC[13:8] */ -+ 0x1f8d, /* ANTFEC[7:0] */ -+ 0x1f8e, /* MAXCNT[7:0] */ -+ 0x1f8f, /* SCANCNT[7:0] */ -+ 0x1f91, /* MAXPW[23:16] */ -+ 0x1f92, /* MAXPW[15:8] */ -+ 0x1f93, /* MAXPW[7:0] */ -+ 0x1f95, /* CURPWMSE[23:16] */ -+ 0x1f96, /* CURPWMSE[15:8] */ -+ 0x1f97, /* CURPWMSE[7:0] */ -+#endif /* SMART_ANT */ -+ 0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */ -+ 0x212a, /* EQAUTOST */ -+ 0x2122, /* CHFAST[7:0] 01100000 */ -+ 0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */ -+ 0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */ -+ 0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */ -+ 0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */ -+ 0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */ -+ 0x2162, /* AICCCTRLE */ -+ 0x2173, /* PHNCNFCNT[7:0] 00000100 */ -+ 0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */ -+ 0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */ -+ 0x217e, /* CNFCNTTPIF[7:0] 00001000 */ -+ 0x217f, /* TPERRCNTTPIF[7:0] 00000001 */ -+ 0x2180, /* x x x x x x FBDLYCIR[9:8] */ -+ 0x2181, /* FBDLYCIR[7:0] */ -+ 0x2185, /* MAXPWRMAIN[7:0] */ -+ 0x2191, /* NCOMBDET x x x x x x x */ -+ 0x2199, /* x MAINSTRON */ -+ 0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */ -+ 0x21a1, /* x x SNRREF[5:0] */ -+ 0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */ -+ 0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */ -+ 0x2847, /* ENNOSIGDE */ -+ 0x2849, /* 1'b1 1'b1 NOUSENOSI */ -+ 0x284a, /* EQINITWAITTIME[7:0] 01100100 */ -+ 0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */ -+ 0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */ -+ 0x3031, /* FRAMELOC */ -+ 0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */ -+ 0x30a9, /* VDLOCK_Q FRAMELOCK */ -+ 0x30aa, /* MPEGLOCK */ -+}; -+ -+#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0])) -+static u8 regval1[numDumpRegs] = {0, }; -+static u8 regval2[numDumpRegs] = {0, }; -+ -+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state) -+{ -+ memset(regval2, 0xff, sizeof(regval2)); -+ lgdt3306a_DumpRegs(state); -+} -+ -+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state) -+{ -+ int i; -+ int sav_debug = debug; -+ -+ if ((debug & DBG_DUMP) == 0) -+ return; -+ debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */ -+ -+ lg_debug("\n"); -+ -+ for (i = 0; i < numDumpRegs; i++) { -+ lgdt3306a_read_reg(state, regtab[i], ®val1[i]); -+ if (regval1[i] != regval2[i]) { -+ lg_debug(" %04X = %02X\n", regtab[i], regval1[i]); -+ regval2[i] = regval1[i]; -+ } -+ } -+ debug = sav_debug; -+} -+#endif /* DBG_DUMP */ -+ -+ -+ -+static struct dvb_frontend_ops lgdt3306a_ops = { -+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, -+ .info = { -+ .name = "LG Electronics LGDT3306A VSB/QAM Frontend", -+ .frequency_min = 54000000, -+ .frequency_max = 858000000, -+ .frequency_stepsize = 62500, -+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB -+ }, -+ .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, -+ .init = lgdt3306a_init, -+ .sleep = lgdt3306a_fe_sleep, -+ /* if this is set, it overrides the default swzigzag */ -+ .tune = lgdt3306a_tune, -+ .set_frontend = lgdt3306a_set_parameters, -+ .get_frontend = lgdt3306a_get_frontend, -+ .get_frontend_algo = lgdt3306a_get_frontend_algo, -+ .get_tune_settings = lgdt3306a_get_tune_settings, -+ .read_status = lgdt3306a_read_status, -+ .read_ber = lgdt3306a_read_ber, -+ .read_signal_strength = lgdt3306a_read_signal_strength, -+ .read_snr = lgdt3306a_read_snr, -+ .read_ucblocks = lgdt3306a_read_ucblocks, -+ .release = lgdt3306a_release, -+ .ts_bus_ctrl = lgdt3306a_ts_bus_ctrl, -+ .search = lgdt3306a_search, -+}; -+ -+MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver"); -+MODULE_AUTHOR("Fred Richter "); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("0.2"); -diff -urN a/drivers/media/dvb-frontends/lgdt3306a.h b/drivers/media/dvb-frontends/lgdt3306a.h ---- a/drivers/media/dvb-frontends/lgdt3306a.h 1970-01-01 02:00:00.000000000 +0200 -+++ b/drivers/media/dvb-frontends/lgdt3306a.h 2015-05-05 21:22:52.244516766 +0300 -@@ -0,0 +1,74 @@ -+/* -+ * Support for LGDT3306A - 8VSB/QAM-B -+ * -+ * Copyright (C) 2013,2014 Fred Richter -+ * based on lgdt3305.[ch] by Michael Krufky -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef _LGDT3306A_H_ -+#define _LGDT3306A_H_ -+ -+#include -+#include "dvb_frontend.h" -+ -+ -+enum lgdt3306a_mpeg_mode { -+ LGDT3306A_MPEG_PARALLEL = 0, -+ LGDT3306A_MPEG_SERIAL = 1, -+}; -+ -+enum lgdt3306a_tp_clock_edge { -+ LGDT3306A_TPCLK_RISING_EDGE = 0, -+ LGDT3306A_TPCLK_FALLING_EDGE = 1, -+}; -+ -+enum lgdt3306a_tp_valid_polarity { -+ LGDT3306A_TP_VALID_LOW = 0, -+ LGDT3306A_TP_VALID_HIGH = 1, -+}; -+ -+struct lgdt3306a_config { -+ u8 i2c_addr; -+ -+ /* user defined IF frequency in KHz */ -+ u16 qam_if_khz; -+ u16 vsb_if_khz; -+ -+ /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ -+ unsigned int deny_i2c_rptr:1; -+ -+ /* spectral inversion - 0:disabled 1:enabled */ -+ unsigned int spectral_inversion:1; -+ -+ enum lgdt3306a_mpeg_mode mpeg_mode; -+ enum lgdt3306a_tp_clock_edge tpclk_edge; -+ enum lgdt3306a_tp_valid_polarity tpvalid_polarity; -+ -+ /* demod clock freq in MHz; 24 or 25 supported */ -+ int xtalMHz; -+}; -+ -+#if IS_ENABLED(CONFIG_DVB_LGDT3306A) -+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, -+ struct i2c_adapter *i2c_adap); -+#else -+static inline -+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, -+ struct i2c_adapter *i2c_adap) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_LGDT3306A */ -+ -+#endif /* _LGDT3306A_H_ */ -diff -urN a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile ---- a/drivers/media/dvb-frontends/Makefile 2015-05-05 20:31:16.696408429 +0300 -+++ b/drivers/media/dvb-frontends/Makefile 2015-05-05 21:23:28.524518035 +0300 -@@ -54,6 +54,7 @@ - obj-$(CONFIG_DVB_S5H1420) += s5h1420.o - obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o - obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o -+obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o - obj-$(CONFIG_DVB_LG2160) += lg2160.o - obj-$(CONFIG_DVB_CX24123) += cx24123.o - obj-$(CONFIG_DVB_LNBP21) += lnbp21.o -diff -urN a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c ---- a/drivers/media/tuners/si2157.c 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/tuners/si2157.c 2015-05-05 21:27:01.580525492 +0300 -@@ -244,6 +244,7 @@ - int ret; - struct si2157_cmd cmd; - u8 bandwidth, delivery_system; -+ u32 if_frequency = 5000000; - - dev_dbg(&client->dev, - "delivery_system=%d frequency=%u bandwidth_hz=%u\n", -@@ -266,9 +267,11 @@ - switch (c->delivery_system) { - case SYS_ATSC: - delivery_system = 0x00; -+ if_frequency = 3250000; - break; - case SYS_DVBC_ANNEX_B: - delivery_system = 0x10; -+ if_frequency = 4000000; - break; - case SYS_DVBT: - case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */ -@@ -302,6 +305,20 @@ - if (ret) - goto err; - -+ /* set if frequency if needed */ -+ if (if_frequency != dev->if_frequency) { -+ memcpy(cmd.args, "\x14\x00\x06\x07", 4); -+ cmd.args[4] = (if_frequency / 1000) & 0xff; -+ cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; -+ cmd.wlen = 6; -+ cmd.rlen = 4; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ dev->if_frequency = if_frequency; -+ } -+ - /* set frequency */ - memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8); - cmd.args[4] = (c->frequency >> 0) & 0xff; -@@ -322,14 +339,17 @@ - - static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) - { -- *frequency = 5000000; /* default value of property 0x0706 */ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = i2c_get_clientdata(client); -+ -+ *frequency = dev->if_frequency; - return 0; - } - - static const struct dvb_tuner_ops si2157_ops = { - .info = { - .name = "Silicon Labs Si2146/2147/2148/2157/2158", -- .frequency_min = 110000000, -+ .frequency_min = 55000000, - .frequency_max = 862000000, - }, - -@@ -360,6 +380,7 @@ - dev->inversion = cfg->inversion; - dev->fw_loaded = false; - dev->chiptype = (u8)id->driver_data; -+ dev->if_frequency = 5000000; /* default value of property 0x0706 */ - mutex_init(&dev->i2c_mutex); - - /* check if the tuner is there */ -diff -urN a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h ---- a/drivers/media/tuners/si2157_priv.h 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/tuners/si2157_priv.h 2015-05-05 21:26:34.268524536 +0300 -@@ -28,6 +28,7 @@ - bool fw_loaded; - bool inversion; - u8 chiptype; -+ u32 if_frequency; - }; - - #define SI2157_CHIPTYPE_SI2157 0 -diff -urN a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c ---- a/drivers/media/usb/cx231xx/cx231xx-cards.c 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c 2015-05-05 21:27:25.452526327 +0300 -@@ -776,6 +776,45 @@ - .gpio = NULL, - } }, - }, -+ [CX231XX_BOARD_HAUPPAUGE_955Q] = { -+ .name = "Hauppauge WinTV-HVR-955Q (111401)", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_addr = 0x60, -+ .tuner_gpio = RDE250_XCV_TUNER, -+ .tuner_sif_gpio = 0x05, -+ .tuner_scl_gpio = 0x1a, -+ .tuner_sda_gpio = 0x1b, -+ .decoder = CX231XX_AVDECODER, -+ .output_mode = OUT_MODE_VIP11, -+ .demod_xfer_mode = 0, -+ .ctl_pin_status_mask = 0xFFFFFFC4, -+ .agc_analog_digital_select_gpio = 0x0c, -+ .gpio_pin_status_mask = 0x4001000, -+ .tuner_i2c_master = I2C_1_MUX_3, -+ .demod_i2c_master = I2C_2, -+ .has_dvb = 1, -+ .demod_addr = 0x0e, -+ .norm = V4L2_STD_NTSC, -+ -+ .input = {{ -+ .type = CX231XX_VMUX_TELEVISION, -+ .vmux = CX231XX_VIN_3_1, -+ .amux = CX231XX_AMUX_VIDEO, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_COMPOSITE1, -+ .vmux = CX231XX_VIN_2_1, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_SVIDEO, -+ .vmux = CX231XX_VIN_1_1 | -+ (CX231XX_VIN_1_2 << 8) | -+ CX25840_SVIDEO_ON, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ } }, -+ }, - }; - const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); - -@@ -805,6 +844,8 @@ - .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, - {USB_DEVICE(0x2040, 0xb120), - .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, -+ {USB_DEVICE(0x2040, 0xb123), -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q}, - {USB_DEVICE(0x2040, 0xb130), - .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, - {USB_DEVICE(0x2040, 0xb131), -@@ -1052,6 +1093,7 @@ - switch (dev->model) { - case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: - case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: -+ case CX231XX_BOARD_HAUPPAUGE_955Q: - { - struct tveeprom tvee; - static u8 eeprom[256]; -diff -urN a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c ---- a/drivers/media/usb/cx231xx/cx231xx-dvb.c 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c 2015-05-05 21:27:25.452526327 +0300 -@@ -34,6 +34,7 @@ - #include "si2165.h" - #include "mb86a20s.h" - #include "si2157.h" -+#include "lgdt3306a.h" - - MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); - MODULE_AUTHOR("Srinivasa Deevi "); -@@ -160,6 +161,18 @@ - .ref_freq_Hz = 24000000, - }; - -+static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { -+ .i2c_addr = 0x59, -+ .qam_if_khz = 4000, -+ .vsb_if_khz = 3250, -+ .deny_i2c_rptr = 1, -+ .spectral_inversion = 1, -+ .mpeg_mode = LGDT3306A_MPEG_SERIAL, -+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, -+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, -+ .xtalMHz = 25, -+}; -+ - static inline void print_err_status(struct cx231xx *dev, int packet, int status) - { - char *errmsg = "Unknown"; -@@ -807,7 +820,61 @@ - dev->dvb->i2c_client_tuner = client; - break; - } -+ case CX231XX_BOARD_HAUPPAUGE_955Q: -+ { -+ struct i2c_client *client; -+ struct i2c_board_info info; -+ struct si2157_config si2157_config; -+ -+ memset(&info, 0, sizeof(struct i2c_board_info)); -+ -+ dev->dvb->frontend = dvb_attach(lgdt3306a_attach, -+ &hauppauge_955q_lgdt3306a_config, -+ tuner_i2c -+ ); -+ -+ if (dev->dvb->frontend == NULL) { -+ dev_err(dev->dev, -+ "Failed to attach LGDT3306A frontend.\n"); -+ result = -EINVAL; -+ goto out_free; -+ } -+ -+ dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; -+ -+ /* define general-purpose callback pointer */ -+ dvb->frontend->callback = cx231xx_tuner_callback; -+ -+ /* attach tuner */ -+ memset(&si2157_config, 0, sizeof(si2157_config)); -+ si2157_config.fe = dev->dvb->frontend; -+ si2157_config.inversion = true; -+ strlcpy(info.type, "si2157", I2C_NAME_SIZE); -+ info.addr = 0x60; -+ info.platform_data = &si2157_config; -+ request_module("si2157"); -+ -+ client = i2c_new_device( -+ tuner_i2c, -+ &info); -+ if (client == NULL || client->dev.driver == NULL) { -+ dvb_frontend_detach(dev->dvb->frontend); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ dvb_frontend_detach(dev->dvb->frontend); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ dev->cx231xx_reset_analog_tuner = NULL; - -+ dev->dvb->i2c_client_tuner = client; -+ break; -+ } - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: - -diff -urN a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h ---- a/drivers/media/usb/cx231xx/cx231xx.h 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/cx231xx/cx231xx.h 2015-05-05 21:27:25.452526327 +0300 -@@ -76,6 +76,7 @@ - #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 - #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19 - #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 -+#define CX231XX_BOARD_HAUPPAUGE_955Q 21 - - /* Limits minimum and default number of buffers */ - #define CX231XX_MIN_BUF 4 -diff -urN a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig ---- a/drivers/media/usb/cx231xx/Kconfig 2015-04-29 11:22:30.000000000 +0300 -+++ b/drivers/media/usb/cx231xx/Kconfig 2015-05-05 21:27:25.452526327 +0300 -@@ -47,6 +47,7 @@ - select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT - select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT - select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT - select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT - select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT - select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT -diff -urN a/index.html b/index.html ---- a/index.html 1970-01-01 02:00:00.000000000 +0200 -+++ b/index.html 2015-05-05 21:27:21.300526182 +0300 -@@ -0,0 +1,184 @@ -+diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig -+index 173c0e2..0cced3e 100644 -+--- a/drivers/media/usb/cx231xx/Kconfig -++++ b/drivers/media/usb/cx231xx/Kconfig -+@@ -47,6 +47,7 @@ config VIDEO_CX231XX_DVB -+ select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT -++ select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT -+ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT -+diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c -+index dfc7010c..39004a1 100644 -+--- a/drivers/media/usb/cx231xx/cx231xx-cards.c -++++ b/drivers/media/usb/cx231xx/cx231xx-cards.c -+@@ -776,6 +776,45 @@ struct cx231xx_board cx231xx_boards[] = { -+ .gpio = NULL, -+ } }, -+ }, -++ [CX231XX_BOARD_HAUPPAUGE_955Q] = { -++ .name = "Hauppauge WinTV-HVR-955Q (111401)", -++ .tuner_type = TUNER_ABSENT, -++ .tuner_addr = 0x60, -++ .tuner_gpio = RDE250_XCV_TUNER, -++ .tuner_sif_gpio = 0x05, -++ .tuner_scl_gpio = 0x1a, -++ .tuner_sda_gpio = 0x1b, -++ .decoder = CX231XX_AVDECODER, -++ .output_mode = OUT_MODE_VIP11, -++ .demod_xfer_mode = 0, -++ .ctl_pin_status_mask = 0xFFFFFFC4, -++ .agc_analog_digital_select_gpio = 0x0c, -++ .gpio_pin_status_mask = 0x4001000, -++ .tuner_i2c_master = I2C_1_MUX_3, -++ .demod_i2c_master = I2C_2, -++ .has_dvb = 1, -++ .demod_addr = 0x0e, -++ .norm = V4L2_STD_NTSC, -++ -++ .input = {{ -++ .type = CX231XX_VMUX_TELEVISION, -++ .vmux = CX231XX_VIN_3_1, -++ .amux = CX231XX_AMUX_VIDEO, -++ .gpio = NULL, -++ }, { -++ .type = CX231XX_VMUX_COMPOSITE1, -++ .vmux = CX231XX_VIN_2_1, -++ .amux = CX231XX_AMUX_LINE_IN, -++ .gpio = NULL, -++ }, { -++ .type = CX231XX_VMUX_SVIDEO, -++ .vmux = CX231XX_VIN_1_1 | -++ (CX231XX_VIN_1_2 << 8) | -++ CX25840_SVIDEO_ON, -++ .amux = CX231XX_AMUX_LINE_IN, -++ .gpio = NULL, -++ } }, -++ }, -+ }; -+ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); -+ -+@@ -805,6 +844,8 @@ struct usb_device_id cx231xx_id_table[] = { -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, -+ {USB_DEVICE(0x2040, 0xb120), -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, -++ {USB_DEVICE(0x2040, 0xb123), -++ .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q}, -+ {USB_DEVICE(0x2040, 0xb130), -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, -+ {USB_DEVICE(0x2040, 0xb131), -+@@ -1049,6 +1090,7 @@ void cx231xx_card_setup(struct cx231xx *dev) -+ switch (dev->model) { -+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: -+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: -++ case CX231XX_BOARD_HAUPPAUGE_955Q: -+ { -+ struct tveeprom tvee; -+ static u8 eeprom[256]; -+diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c -+index e8c054c..140c997 100644 -+--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c -++++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c -+@@ -34,6 +34,7 @@ -+ #include "si2165.h" -+ #include "mb86a20s.h" -+ #include "si2157.h" -++#include "lgdt3306a.h" -+ -+ MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); -+ MODULE_AUTHOR("Srinivasa Deevi "); -+@@ -160,6 +161,18 @@ static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { -+ .ref_freq_Hz = 24000000, -+ }; -+ -++static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { -++ .i2c_addr = 0x59, -++ .qam_if_khz = 4000, -++ .vsb_if_khz = 3250, -++ .deny_i2c_rptr = 1, -++ .spectral_inversion = 1, -++ .mpeg_mode = LGDT3306A_MPEG_SERIAL, -++ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, -++ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, -++ .xtalMHz = 25, -++}; -++ -+ static inline void print_err_status(struct cx231xx *dev, int packet, int status) -+ { -+ char *errmsg = "Unknown"; -+@@ -812,7 +825,61 @@ static int dvb_init(struct cx231xx *dev) -+ dev->dvb->i2c_client_tuner = client; -+ break; -+ } -++ case CX231XX_BOARD_HAUPPAUGE_955Q: -++ { -++ struct i2c_client *client; -++ struct i2c_board_info info; -++ struct si2157_config si2157_config; -++ -++ memset(&info, 0, sizeof(struct i2c_board_info)); -++ -++ dev->dvb->frontend = dvb_attach(lgdt3306a_attach, -++ &hauppauge_955q_lgdt3306a_config, -++ tuner_i2c -++ ); -++ -++ if (dev->dvb->frontend == NULL) { -++ dev_err(dev->dev, -++ "Failed to attach LGDT3306A frontend.\n"); -++ result = -EINVAL; -++ goto out_free; -++ } -++ -++ dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; -++ -++ /* define general-purpose callback pointer */ -++ dvb->frontend->callback = cx231xx_tuner_callback; -++ -++ /* attach tuner */ -++ memset(&si2157_config, 0, sizeof(si2157_config)); -++ si2157_config.fe = dev->dvb->frontend; -++ si2157_config.inversion = true; -++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); -++ info.addr = 0x60; -++ info.platform_data = &si2157_config; -++ request_module("si2157"); -++ -++ client = i2c_new_device( -++ tuner_i2c, -++ &info); -++ if (client == NULL || client->dev.driver == NULL) { -++ dvb_frontend_detach(dev->dvb->frontend); -++ result = -ENODEV; -++ goto out_free; -++ } -++ -++ if (!try_module_get(client->dev.driver->owner)) { -++ i2c_unregister_device(client); -++ dvb_frontend_detach(dev->dvb->frontend); -++ result = -ENODEV; -++ goto out_free; -++ } -++ -++ dev->cx231xx_reset_analog_tuner = NULL; -+ -++ dev->dvb->i2c_client_tuner = client; -++ break; -++ } -+ case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: -+ case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: -+ -+diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h -+index e0d3106..573b3c0 100644 -+--- a/drivers/media/usb/cx231xx/cx231xx.h -++++ b/drivers/media/usb/cx231xx/cx231xx.h -+@@ -76,6 +76,7 @@ -+ #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 -+ #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19 -+ #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 -++#define CX231XX_BOARD_HAUPPAUGE_955Q 21 -+ -+ /* Limits minimum and default number of buffers */ -+ #define CX231XX_MIN_BUF 4 diff --git a/packages/linux/patches/4.0.5/linux-706-Sitecom-N300.patch b/packages/linux/patches/4.0.5/linux-706-Sitecom-N300.patch deleted file mode 100644 index 9f52eeb2d5..0000000000 --- a/packages/linux/patches/4.0.5/linux-706-Sitecom-N300.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -Naur linux-3.10.16/drivers/staging/rtl8712/usb_intf.c linux-3.10.16.patch/drivers/staging/rtl8712/usb_intf.c ---- linux-3.10.16/drivers/staging/rtl8712/usb_intf.c 2013-10-14 01:08:56.000000000 +0200 -+++ linux-3.10.16.patch/drivers/staging/rtl8712/usb_intf.c 2013-10-16 13:27:44.032951265 +0200 -@@ -92,6 +92,7 @@ - {USB_DEVICE(0x0DF6, 0x005B)}, - {USB_DEVICE(0x0DF6, 0x005D)}, - {USB_DEVICE(0x0DF6, 0x0063)}, -+ {USB_DEVICE(0x0DF6, 0x006C)}, - /* Sweex */ - {USB_DEVICE(0x177F, 0x0154)}, - /* Thinkware */ diff --git a/packages/linux/patches/4.0.5/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/4.0.5/linux-950-saa716x_PCIe_interface_chipset.patch deleted file mode 100644 index 71cac81ac0..0000000000 --- a/packages/linux/patches/4.0.5/linux-950-saa716x_PCIe_interface_chipset.patch +++ /dev/null @@ -1,13031 +0,0 @@ -diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig -index b85f88c..238b2ed 100644 ---- a/drivers/media/common/Kconfig -+++ b/drivers/media/common/Kconfig -@@ -22,4 +22,5 @@ config CYPRESS_FIRMWARE - - source "drivers/media/common/b2c2/Kconfig" - source "drivers/media/common/saa7146/Kconfig" -+source "drivers/media/common/saa716x/Kconfig" - source "drivers/media/common/siano/Kconfig" -diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile -index d208de3..b3c373d 100644 ---- a/drivers/media/common/Makefile -+++ b/drivers/media/common/Makefile -@@ -1,4 +1,4 @@ --obj-y += b2c2/ saa7146/ siano/ -+obj-y += b2c2/ saa7146/ saa716x/ siano/ - obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o - obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o - obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o -diff --git a/drivers/media/common/saa716x/Kconfig b/drivers/media/common/saa716x/Kconfig -new file mode 100644 -index 0000000..e667a58 ---- /dev/null -+++ b/drivers/media/common/saa716x/Kconfig -@@ -0,0 +1,67 @@ -+menuconfig SAA716X_SUPPORT -+ bool "Support for SAA716x family from NXP/Philips" -+ depends on PCI && I2C -+ help -+ support for saa716x -+ -+if SAA716X_SUPPORT -+config SAA716X_CORE -+ tristate "SAA7160/1/2 PCI Express bridge based devices" -+ depends on PCI && I2C -+ -+ help -+ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_BUDGET -+ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" -+ depends on SAA716X_CORE && DVB_CORE -+ select DVB_DS3000 if !DVB_FE_CUSTOMISE -+ select DVB_DS3103 if !DVB_FE_CUSTOMISE -+ select DVB_TS2022 if !DVB_FE_CUSTOMISE -+ -+ help -+ Support for the SAA7160/1/2 based Budget PCIe DVB cards -+ Currently supported devices are: -+ -+ * KNC1 Dual S2 (DVB-S, DVB-S/S2) -+ * Twinhan/Azurewave VP-1028 (DVB-S) -+ * Twinhan/Azurewave VP-3071 (DVB-T x2) -+ * Twinhan/Azurewave VP-6002 (DVB-S) -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_HYBRID -+ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" -+ depends on SAA716X_CORE && DVB_CORE -+ -+ help -+ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards -+ Currently supported devices are: -+ -+ * Avermedia H-788 (DVB-T) -+ * Avermedia HC-82 (DVB-T) -+ * NXP Reference (Atlantis) (DVB-T x2) -+ * NXP Reference (Nemo) (DVB-T) -+ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) -+ -+ Say Y if you own such a device and want to use it. -+ -+#config DVB_SAA716X_FF -+# tristate "SAA7160/1/2 based Full Fledged PCIe cards" -+# depends on SAA716X_CORE && DVB_CORE -+# depends on INPUT # IR -+# default n -+ -+# help -+# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards -+# These cards do feature a hardware MPEG decoder and other -+# peripherals. Also known as Premium cards. -+# Currently supported devices are: -+ -+# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) -+ -+# Say Y if you own such a device and want to use it. -+ -+endif # SAA716X_SUPPORT -diff --git a/drivers/media/common/saa716x/Makefile b/drivers/media/common/saa716x/Makefile -new file mode 100644 -index 0000000..c86f224 ---- /dev/null -+++ b/drivers/media/common/saa716x/Makefile -@@ -0,0 +1,26 @@ -+saa716x_core-objs := saa716x_pci.o \ -+ saa716x_i2c.o \ -+ saa716x_cgu.o \ -+ saa716x_msi.o \ -+ saa716x_dma.o \ -+ saa716x_vip.o \ -+ saa716x_aip.o \ -+ saa716x_phi.o \ -+ saa716x_boot.o \ -+ saa716x_fgpi.o \ -+ saa716x_adap.o \ -+ saa716x_gpio.o \ -+ saa716x_greg.o \ -+ saa716x_rom.o \ -+ saa716x_spi.o -+ -+#saa716x_ff-objs := saa716x_ff_main.o \ -+# saa716x_ff_cmd.o \ -+# saa716x_ff_ir.o -+ -+obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o -+obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o -+obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o -+#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o -+ -+EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ -diff --git a/drivers/media/common/saa716x/saa716x_adap.c b/drivers/media/common/saa716x/saa716x_adap.c -new file mode 100644 -index 0000000..6d7346c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_adap.c -@@ -0,0 +1,274 @@ -+#include -+ -+#include "dmxdev.h" -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dvb_frontend.h" -+ -+#include "saa716x_mod.h" -+#include "saa716x_spi.h" -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_gpio.h" -+#include "saa716x_priv.h" -+#include "saa716x_budget.h" -+ -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+ -+void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ struct fgpi_stream_params params; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); -+ -+ params.bits = 8; -+ params.samples = 188; -+ params.lines = 348; -+ params.pitch = 188; -+ params.offset = 0; -+ params.page_tables = 0; -+ params.stream_type = FGPI_TRANSPORT_STREAM; -+ params.stream_flags = 0; -+ -+ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); -+} -+ -+void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); -+ -+ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); -+} -+ -+static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds++; -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", -+ saa716x_adap->feeds); -+ -+ if (saa716x_adap->feeds == 1) { -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); -+ saa716x_dma_start(saa716x, saa716x_adap->count); -+ } -+ -+ return saa716x_adap->feeds; -+} -+ -+static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds--; -+ if (saa716x_adap->feeds == 0) { -+ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); -+ saa716x_dma_stop(saa716x, saa716x_adap->count); -+ } -+ -+ return 0; -+} -+ -+int saa716x_dvb_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct saa716x_config *config = saa716x->config; -+ int result, i; -+ -+ mutex_init(&saa716x->adap_lock); -+ -+ for (i = 0; i < config->adapters; i++) { -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); -+ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, -+ "SAA716x dvb adapter", -+ THIS_MODULE, -+ &saa716x->pdev->dev, -+ adapter_nr) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); -+ return -ENODEV; -+ } -+ -+ saa716x_adap->count = i; -+ -+ saa716x_adap->dvb_adapter.priv = saa716x_adap; -+ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | -+ DMX_SECTION_FILTERING | -+ DMX_MEMORY_BASED_FILTERING; -+ -+ saa716x_adap->demux.priv = saa716x_adap; -+ saa716x_adap->demux.filternum = 256; -+ saa716x_adap->demux.feednum = 256; -+ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; -+ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; -+ saa716x_adap->demux.write_to_decoder = NULL; -+ switch (saa716x->pdev->subsystem_device) { -+ case TEVII_S472: { -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ u8 mac[6]; -+ u8 b0[] = { 0, 9 }; -+ struct i2c_msg msg[] = { -+ { -+ .addr = 0x50, -+ .flags = 0, -+ .buf = b0, -+ .len = 2 -+ }, { -+ .addr = 0x50, -+ .flags = I2C_M_RD, -+ .buf = mac, -+ .len = 6 -+ } -+ }; -+ -+ i2c_transfer(adapter, msg, 2); -+ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); -+ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); -+ } -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); -+ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err0; -+ } -+ -+ saa716x_adap->dmxdev.filternum = 256; -+ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; -+ saa716x_adap->dmxdev.capabilities = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); -+ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, -+ &saa716x_adap->dvb_adapter)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); -+ goto err1; -+ } -+ -+ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err2; -+ } -+ -+ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_mem)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err3; -+ } -+ -+ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err4; -+ } -+ -+ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); -+// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); -+ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); -+ saa716x_adap->saa716x = saa716x; -+ -+ if (config->frontend_attach) { -+ result = config->frontend_attach(saa716x_adap, i); -+ if (result < 0) -+ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); -+ -+ if (saa716x_adap->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", -+ saa716x->pdev->vendor, -+ saa716x->pdev->device, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ } else { -+ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); -+ if (result < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); -+ goto err6; -+ } -+ } -+ -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); -+ } -+ -+ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, -+ config->adap_config[i].worker); -+ -+ saa716x_adap++; -+ } -+ -+ -+ return 0; -+ -+ /* Error conditions */ -+err6: -+ dvb_frontend_detach(saa716x_adap->fe); -+err4: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+err3: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+err2: -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+err1: -+ dvb_dmx_release(&saa716x_adap->demux); -+err0: -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ return result; -+} -+EXPORT_SYMBOL(saa716x_dvb_init); -+ -+void saa716x_dvb_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ int i; -+ -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ -+ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); -+ -+ if (saa716x_adap->fe) { -+ dvb_unregister_frontend(saa716x_adap->fe); -+ dvb_frontend_detach(saa716x_adap->fe); -+ } -+ -+// tasklet_kill(&saa716x->tasklet); -+ dvb_net_release(&saa716x_adap->dvb_net); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+ dvb_dmx_release(&saa716x_adap->demux); -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ saa716x_adap++; -+ } -+ -+ return; -+} -+EXPORT_SYMBOL(saa716x_dvb_exit); -diff --git a/drivers/media/common/saa716x/saa716x_adap.h b/drivers/media/common/saa716x/saa716x_adap.h -new file mode 100644 -index 0000000..7822e36 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_adap.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_ADAP_H -+#define __SAA716x_ADAP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_dvb_init(struct saa716x_dev *saa716x); -+extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ADAP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_aip.c b/drivers/media/common/saa716x/saa716x_aip.c -new file mode 100644 -index 0000000..3bdb265 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip.c -@@ -0,0 +1,20 @@ -+#include -+ -+#include "saa716x_mod.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_aip.h" -+#include "saa716x_priv.h" -+ -+int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) -+{ -+ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_status); -+ -+void saa716x_aip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(AI0, AI_CTL, 0x00); -+ SAA716x_EPWR(AI1, AI_CTL, 0x00); -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_disable); -diff --git a/drivers/media/common/saa716x/saa716x_aip.h b/drivers/media/common/saa716x/saa716x_aip.h -new file mode 100644 -index 0000000..36277b7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_AIP_H -+#define __SAA716x_AIP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); -+extern void saa716x_aip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_AIP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_aip_reg.h b/drivers/media/common/saa716x/saa716x_aip_reg.h -new file mode 100644 -index 0000000..3e0893a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_aip_reg.h -@@ -0,0 +1,62 @@ -+#ifndef __SAA716x_AIP_REG_H -+#define __SAA716x_AIP_REG_H -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+#endif /* __SAA716x_AIP_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_boot.c b/drivers/media/common/saa716x/saa716x_boot.c -new file mode 100644 -index 0000000..21e59d0 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_boot.c -@@ -0,0 +1,319 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_cgu_reg.h" -+#include "saa716x_vip_reg.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_gpio_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dcs_reg.h" -+ -+#include "saa716x_boot.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static int saa716x_ext_boot(struct saa716x_dev *saa716x) -+{ -+ /* Write GREG boot_ready to 0 -+ * DW_0 = 0x0001_2018 -+ * DW_1 = 0x0000_0000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); -+ -+ /* Clear VI0 interrupt -+ * DW_2 = 0x0000_0fe8 -+ * DW_3 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); -+ -+ /* Clear VI1 interrupt -+ * DW_4 = 0x0000_1fe8 -+ * DW_5 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); -+ -+ /* CLear FGPI0 interrupt -+ * DW_6 = 0x0000_2fe8 -+ * DW_7 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI1 interrupt -+ * DW_8 = 0x0000_3fe8 -+ * DW_9 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI2 interrupt -+ * DW_10 = 0x0000_4fe8 -+ * DW_11 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI3 interrupt -+ * DW_12 = 0x0000_5fe8 -+ * DW_13 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear AI0 interrupt -+ * DW_14 = 0x0000_6020 -+ * DW_15 = 0x0000_000f -+ */ -+ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); -+ -+ /* Clear AI1 interrupt -+ * DW_16 = 0x0000_7020 -+ * DW_17 = 0x0000_200f -+ */ -+ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); -+ -+ /* Set GREG boot_ready bit to 1 -+ * DW_18 = 0x0001_2018 -+ * DW_19 = 0x0000_2000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+#if 0 -+ /* End of Boot script command -+ * DW_20 = 0x0000_0006 -+ * Where to write this value ?? -+ * This seems very odd an address to trigger the -+ * Boot Control State Machine ! -+ */ -+ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); -+#endif -+ return 0; -+} -+ -+/* Internal Bootscript configuration */ -+static void saa716x_int_boot(struct saa716x_dev *saa716x) -+{ -+ /* #1 Configure PCI COnfig space -+ * GREG_JETSTR_CONFIG_0 -+ */ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); -+ -+ /* GREG_JETSTR_CONFIG_1 -+ * pmcsr_scale:7 = 0x00 -+ * pmcsr_scale:6 = 0x00 -+ * pmcsr_scale:5 = 0x00 -+ * pmcsr_scale:4 = 0x00 -+ * pmcsr_scale:3 = 0x00 -+ * pmcsr_scale:2 = 0x00 -+ * pmcsr_scale:1 = 0x00 -+ * pmcsr_scale:0 = 0x00 -+ * BAR mask = 20 bit -+ * BAR prefetch = no -+ * MSI capable = 32 messages -+ */ -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); -+ -+ /* GREG_JETSTR_CONFIG_2 -+ * pmcsr_data:3 = 0x0 -+ * pmcsr_data:2 = 0x0 -+ * pmcsr_data:1 = 0x0 -+ * pmcsr_data:0 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); -+ -+ /* GREG_JETSTR_CONFIG_3 -+ * pmcsr_data:7 = 0x0 -+ * pmcsr_data:6 = 0x0 -+ * pmcsr_data:5 = 0x0 -+ * pmcsr_data:4 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); -+ -+ /* #2 Release GREG resets -+ * ip_rst_an -+ * dpa1_rst_an -+ * jetsream_reset_an -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); -+ -+ /* #3 GPIO Setup -+ * GPIO 25:24 = Output -+ * GPIO Output "0" after Reset -+ */ -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ -+ /* #4 Custom stuff goes in here */ -+ -+ /* #5 Disable CGU Clocks -+ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG -+ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 -+ */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); -+ -+ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); -+ -+ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); -+ -+ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); -+ -+ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); -+ -+ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); -+ -+ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); -+ -+ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); -+ -+ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); -+ -+ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); -+ -+ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); -+ -+ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); -+ -+ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); -+ -+ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); -+ -+ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); -+ -+ /* #6 Set GREG boot_ready = 0x1 */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+ -+ /* #7 Disable GREG CGU Clock */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); -+ -+ /* End of Bootscript command ?? */ -+} -+ -+int saa716x_core_boot(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_config *config = saa716x->config; -+ -+ switch (config->boot_mode) { -+ case SAA716x_EXT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); -+ saa716x_ext_boot(saa716x); -+ break; -+ case SAA716x_INT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); -+ saa716x_int_boot(saa716x); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); -+ break; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_core_boot); -+ -+static void saa716x_bus_report(struct pci_dev *pdev, int enable) -+{ -+ u32 reg; -+ -+ pci_read_config_dword(pdev, 0x04, ®); -+ if (enable) -+ reg |= 0x00000100; /* enable SERR */ -+ else -+ reg &= 0xfffffeff; /* disable SERR */ -+ pci_write_config_dword(pdev, 0x04, reg); -+ -+ pci_read_config_dword(pdev, 0x58, ®); -+ reg &= 0xfffffffd; -+ pci_write_config_dword(pdev, 0x58, reg); -+} -+ -+int saa716x_jetpack_init(struct saa716x_dev *saa716x) -+{ -+ /* -+ * configure PHY through config space not to report -+ * non-fatal error messages to avoid problems with -+ * quirky BIOS'es -+ */ -+ saa716x_bus_report(saa716x->pdev, 0); -+ -+ /* -+ * create time out for blocks that have no clock -+ * helps with lower bitrates on FGPI -+ */ -+ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); -+ -+ /* Reset all blocks */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ switch (saa716x->pdev->device) { -+ case SAA7162: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ -+ break; -+ case SAA7161: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ -+ break; -+ case SAA7160: -+ saa716x->i2c_rate = SAA716x_I2C_RATE_100; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); -+ return -ENODEV; -+ } -+ -+ /* General setup for MMU */ -+ SAA716x_EPWR(MMU, MMU_MODE, 0x14); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_jetpack_init); -+ -+void saa716x_core_reset(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); -+ -+ /* VIP */ -+ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); -+ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); -+ -+ /* FGPI */ -+ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* AIP */ -+ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); -+ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); -+ -+ /* BAM */ -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ /* MMU */ -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ -+ /* MSI */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+} -+EXPORT_SYMBOL_GPL(saa716x_core_reset); -diff --git a/drivers/media/common/saa716x/saa716x_boot.h b/drivers/media/common/saa716x/saa716x_boot.h -new file mode 100644 -index 0000000..8102853 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_boot.h -@@ -0,0 +1,18 @@ -+#ifndef __SAA716x_BOOT_H -+#define __SAA716x_BOOT_H -+ -+#define DISABLE_TIMEOUT 0x17 -+#define ENABLE_TIMEOUT 0x16 -+ -+enum saa716x_boot_mode { -+ SAA716x_EXT_BOOT = 1, -+ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+extern void saa716x_core_reset(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_BOOT_H */ -diff --git a/drivers/media/common/saa716x/saa716x_budget.c b/drivers/media/common/saa716x/saa716x_budget.c -new file mode 100644 -index 0000000..6b52fc1 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_budget.c -@@ -0,0 +1,717 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_budget.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "mb86a16.h" -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "ds3103.h" -+#include "ts2022.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Budget" -+ -+static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); -+ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_budget_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" -+#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" -+ -+static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp3071_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP3071, -+ .dev_type = SAA716x_DEV_TWINHAN_VP3071, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_vp3071_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" -+#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" -+ -+static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp1028_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp1028_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count == 0) { -+ -+ mutex_lock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); -+ saa716x_gpio_set_output(saa716x, 10); -+ msleep(1); -+ -+ /* VP-1028 has inverted power supply control */ -+ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ -+ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ -+ msleep(100); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); -+ saa716x_gpio_set_output(saa716x, 12); -+ msleep(1); -+ -+ /* reset demodulator (Active LOW) */ -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 0); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ -+ mutex_unlock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp1028_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp1028_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP1028, -+ .dev_type = SAA716x_DEV_TWINHAN_VP1028, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp1028_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" -+#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" -+ -+static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp6002_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6002, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6002, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6002_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" -+#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" -+ -+static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_knc1_duals2_config = { -+ .model_name = SAA716x_MODEL_KNC1_DUALS2, -+ .dev_type = SAA716x_DEV_KNC1_DUALS2, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_knc1_duals2_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" -+#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" -+ -+static struct stv090x_config skystar2_stv090x_config = { -+ .device = STV0903, -+ .demod_mode = STV090x_SINGLE, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 8000000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_DVBCI, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_sleep = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static int skystar2_set_voltage(struct dvb_frontend *fe, -+ enum fe_sec_voltage voltage) -+{ -+ int err; -+ u8 en = 0; -+ u8 sel = 0; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ en = 0; -+ break; -+ -+ case SEC_VOLTAGE_13: -+ en = 1; -+ sel = 0; -+ break; -+ -+ case SEC_VOLTAGE_18: -+ en = 1; -+ sel = 1; -+ break; -+ -+ default: -+ break; -+ } -+ -+ err = skystar2_stv090x_config.set_gpio(fe, 2, 0, en, 0); -+ if (err < 0) -+ goto exit; -+ err = skystar2_stv090x_config.set_gpio(fe, 3, 0, sel, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) -+{ -+ int err; -+ u8 value; -+ -+ if (arg) -+ value = 1; -+ else -+ value = 0; -+ -+ err = skystar2_stv090x_config.set_gpio(fe, 4, 0, value, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static struct stv6110x_config skystar2_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 16000000, -+ .clk_div = 2, -+}; -+ -+static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct stv6110x_devctl *ctl; -+ -+ if (count < saa716x->config->adapters) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ saa716x_gpio_set_output(saa716x, 26); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ -+ adapter->fe = dvb_attach(stv090x_attach, -+ &skystar2_stv090x_config, -+ &i2c->i2c_adapter, -+ STV090x_DEMODULATOR_0); -+ -+ if (adapter->fe) { -+ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", -+ skystar2_stv090x_config.address); -+ } else { -+ goto exit; -+ } -+ -+ adapter->fe->ops.set_voltage = skystar2_set_voltage; -+ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; -+ -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &skystar2_stv6110x_config, -+ &i2c->i2c_adapter); -+ -+ if (ctl) { -+ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", -+ skystar2_stv6110x_config.addr); -+ -+ skystar2_stv090x_config.tuner_init = ctl->tuner_init; -+ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config skystar2_express_hd_config = { -+ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, -+ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = skystar2_express_hd_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct ds3103_config s472_ds3103_config = { -+ .demod_address = 0x68, -+ .ci_mode = 1, -+}; -+ -+static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count != 0) -+ return 0; -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); -+ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, -+ &i2c->i2c_adapter); -+ -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", -+ s472_ds3103_config.demod_address); -+ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) -+ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); -+ else -+ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ -+} -+ -+static struct saa716x_config tevii_s472_config = { -+ .model_name = "TeVii S472 DVB-S2", -+ .dev_type = "DVB-S/S2", -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_s472_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct pci_device_id saa716x_budget_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ -+ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), -+ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), -+ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); -+ -+static struct pci_driver saa716x_budget_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_budget_pci_table, -+ .probe = saa716x_budget_pci_probe, -+ .remove = saa716x_budget_pci_remove, -+}; -+ -+static int saa716x_budget_init(void) -+{ -+ return pci_register_driver(&saa716x_budget_pci_driver); -+} -+ -+static void saa716x_budget_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_budget_pci_driver); -+} -+ -+module_init(saa716x_budget_init); -+module_exit(saa716x_budget_exit); -+ -+MODULE_DESCRIPTION("SAA716x Budget driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_budget.h b/drivers/media/common/saa716x/saa716x_budget.h -new file mode 100644 -index 0000000..d6b8c46 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_budget.h -@@ -0,0 +1,17 @@ -+#ifndef __SAA716x_BUDGET_H -+#define __SAA716x_BUDGET_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define TWINHAN_VP_3071 0x0039 -+#define TWINHAN_VP_1028 0x0044 -+#define TWINHAN_VP_6002 0x0047 -+ -+#define KNC_One 0x1894 -+#define KNC_Dual_S2 0x0110 -+ -+#define TECHNISAT 0x1AE4 -+#define SKYSTAR2_EXPRESS_HD 0x0700 -+#define TEVII 0x9022 -+#define TEVII_S472 0xd472 -+ -+#endif /* __SAA716x_BUDGET_H */ -diff --git a/drivers/media/common/saa716x/saa716x_cgu.c b/drivers/media/common/saa716x/saa716x_cgu.c -new file mode 100644 -index 0000000..a0ffb04 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu.c -@@ -0,0 +1,539 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_cgu_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+u32 cgu_clk[14] = { -+ CGU_FDC_0, -+ CGU_FDC_1, -+ CGU_FDC_2, -+ CGU_FDC_3, -+ CGU_FDC_4, -+ CGU_FDC_5, -+ CGU_FDC_6, -+ CGU_FDC_7, -+ CGU_FDC_8, -+ CGU_FDC_9, -+ CGU_FDC_10, -+ CGU_FDC_11, -+ CGU_FDC_12, -+ CGU_FDC_13 -+}; -+ -+char *clk_desc[14] = { -+ "Clk PSS", -+ "Clk DCS", -+ "Clk SPI", -+ "Clk I2C/Boot", -+ "Clk PHI", -+ "Clk VI0", -+ "Clk VI1", -+ "Clk FGPI0", -+ "Clk FGPI1", -+ "Clk FGPI2", -+ "Clk FGPI3", -+ "Clk AI0", -+ "Clk AI1", -+ "Clk Phy" -+}; -+ -+int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 i; -+ s8 N = 0; -+ s16 M = 0; -+ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ -+ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ -+ -+ /* get all dividers */ -+ for (i = 0; i < CGU_CLKS; i++) { -+ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); -+ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; -+ -+ N = (cgu->clk_boot_div[i] >> 11) & 0xff; -+ N *= -1; -+ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; -+ -+ if (M) -+ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; -+ else -+ cgu->clk_freq[i] = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", -+ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); -+ } -+ /* store clock settings */ -+ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ -+ return 0; -+} -+ -+int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ SAA716x_CGU_CLKRUN(7); -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ SAA716x_CGU_CLKRUN(8); -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ SAA716x_CGU_CLKRUN(9); -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ SAA716x_CGU_CLKRUN(10); -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ SAA716x_CGU_CLKRUN(11); -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ SAA716x_CGU_CLKRUN(12); -+ break; -+ -+ case PORT_ALL: -+ SAA716x_CGU_CLKRUN(5); -+ SAA716x_CGU_CLKRUN(6); -+ SAA716x_CGU_CLKRUN(7); -+ SAA716x_CGU_CLKRUN(8); -+ SAA716x_CGU_CLKRUN(9); -+ SAA716x_CGU_CLKRUN(10); -+ SAA716x_CGU_CLKRUN(11); -+ SAA716x_CGU_CLKRUN(12); -+ -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ cgu->clk_int_port[PORT_AI0] = 1; -+ cgu->clk_int_port[PORT_AI1] = 1; -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ } -+ -+ /* wait for PLL */ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ -+ } -+ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_get_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 *frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_VI0: -+ case CLK_DOMAIN_VI1: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ *frequency = cgu->clk_freq[domain]; -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_set_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u32 M = 1, N = 1, reset, i; -+ s8 N_tmp, M_tmp, sub, add, lsb; -+ -+ -+ if (cgu->clk_freq_min > frequency) -+ frequency = cgu->clk_freq_min; -+ -+ if (cgu->clk_freq_max < frequency) -+ frequency = cgu->clk_freq_max; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ -+ if (frequency == cgu->clk_freq[domain]) -+ return 0; /* same frequency */ -+ break; -+ -+ case CLK_DOMAIN_VI0: -+ -+ if (frequency == cgu->clk_vi_0[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_0[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI1: -+ if (frequency == cgu->clk_vi_1[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_1[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ if (frequency == cgu->clk_vi_0[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_0[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI0; /* change domain */ -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ if (frequency == cgu->clk_vi_1[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_1[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI1; /* change domain */ -+ break; -+ } -+ -+ /* calculate divider */ -+ do { -+ M = (N * PLL_FREQ) / frequency; -+ if (M == 0) -+ N++; -+ -+ } while (M == 0); -+ -+ /* calculate frequency */ -+ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; -+ -+ N_tmp = N & 0xff; -+ M_tmp = M & 0xff; -+ sub = -N_tmp; -+ add = M_tmp - N_tmp; -+ lsb = 4; /* run */ -+ -+ if (((10 * N) / M) < 5) -+ lsb |= 1; /* stretch */ -+ -+ /* store new divider */ -+ cgu->clk_curr_div[domain] = sub & 0xff; -+ cgu->clk_curr_div[domain] <<= 8; -+ cgu->clk_curr_div[domain] = add & 0xff; -+ cgu->clk_curr_div[domain] <<= 3; -+ cgu->clk_curr_div[domain] |= lsb; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", -+ domain, -+ frequency, -+ cgu->clk_freq[domain], -+ N, -+ M, -+ cgu->clk_curr_div[domain]); -+ -+ reset = 0; -+ -+ /* Reset */ -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); -+ -+ /* Reset disable */ -+ for (i = 0; i < 1000; i++) { -+ msleep(10); -+ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); -+ -+ if (cgu->clk_curr_div[domain == reset]) -+ break; -+ } -+ -+ if (cgu->clk_curr_div[domain] != reset) -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); -+ -+ return 0; -+} -+ -+int saa716x_cgu_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ cgu->clk_freq_min = PLL_FREQ / 255; -+ if (PLL_FREQ > (cgu->clk_freq_min * 255)) -+ cgu->clk_freq_min++; -+ -+ cgu->clk_freq_max = PLL_FREQ; -+ -+ saa716x_getbootscript_setup(saa716x); -+ saa716x_set_clk_internal(saa716x, PORT_ALL); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_cgu_init); -diff --git a/drivers/media/common/saa716x/saa716x_cgu.h b/drivers/media/common/saa716x/saa716x_cgu.h -new file mode 100644 -index 0000000..5353cf2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu.h -@@ -0,0 +1,61 @@ -+#ifndef __SAA716x_CGU_H -+#define __SAA716x_CGU_H -+ -+#define PLL_FREQ 2500 -+ -+#define SAA716x_CGU_CLKRUN(__reg) do { \ -+ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ -+ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ -+ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ -+ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ -+} while (0) -+ -+enum saa716x_clk_domain { -+ CLK_DOMAIN_PSS = 0, -+ CLK_DOMAIN_DCS = 1, -+ CLK_DOMAIN_SPI = 2, -+ CLK_DOMAIN_I2C = 3, -+ CLK_DOMAIN_PHI = 4, -+ CLK_DOMAIN_VI0 = 5, -+ CLK_DOMAIN_VI1 = 6, -+ CLK_DOMAIN_FGPI0 = 7, -+ CLK_DOMAIN_FGPI1 = 8, -+ CLK_DOMAIN_FGPI2 = 9, -+ CLK_DOMAIN_FGPI3 = 10, -+ CLK_DOMAIN_AI0 = 11, -+ CLK_DOMAIN_AI1 = 12, -+ CLK_DOMAIN_PHY = 13, -+ CLK_DOMAIN_VI0VBI = 14, -+ CLK_DOMAIN_VI1VBI = 15 -+}; -+ -+#define PORT_VI0_VIDEO 0 -+#define PORT_VI0_VBI 2 -+#define PORT_VI1_VIDEO 3 -+#define PORT_VI1_VBI 5 -+#define PORT_FGPI0 6 -+#define PORT_FGPI1 7 -+#define PORT_FGPI2 8 -+#define PORT_FGPI3 9 -+#define PORT_AI0 10 -+#define PORT_AI1 11 -+#define PORT_ALL 12 -+ -+#define CGU_CLKS 14 -+ -+struct saa716x_cgu { -+ u8 clk_int_port[12]; -+ u32 clk_vi_0[3]; -+ u32 clk_vi_1[3]; -+ u32 clk_boot_div[CGU_CLKS]; -+ u32 clk_curr_div[CGU_CLKS]; -+ u32 clk_freq[CGU_CLKS]; -+ u32 clk_freq_min; -+ u32 clk_freq_max; -+}; -+ -+extern int saa716x_cgu_init(struct saa716x_dev *saa716x); -+extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); -+extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); -+ -+#endif /* __SAA716x_CGU_H */ -diff --git a/drivers/media/common/saa716x/saa716x_cgu_reg.h b/drivers/media/common/saa716x/saa716x_cgu_reg.h -new file mode 100644 -index 0000000..f7d82ae ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_cgu_reg.h -@@ -0,0 +1,178 @@ -+#ifndef __SAA716x_CGU_REG_H -+#define __SAA716x_CGU_REG_H -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+#endif /* __SAA716x_CGU_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dcs_reg.h b/drivers/media/common/saa716x/saa716x_dcs_reg.h -new file mode 100644 -index 0000000..26dba68 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dcs_reg.h -@@ -0,0 +1,56 @@ -+#ifndef __SAA716x_DCS_REG_H -+#define __SAA716x_DCS_REG_H -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_DCS_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dma.c b/drivers/media/common/saa716x/saa716x_dma.c -new file mode 100644 -index 0000000..21d1dd8 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma.c -@@ -0,0 +1,306 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include "saa716x_dma.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+/* Allocates one page of memory, which is stores the data of one -+ * 716x page table. The result gets stored in the passed DMA buffer -+ * structure. -+ */ -+static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); -+ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); -+ -+ if (dmabuf->mem_ptab_virt == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); -+ return -ENOMEM; -+ } -+ -+ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, -+ dmabuf->mem_ptab_virt, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ if (dmabuf->mem_ptab_phys == 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); -+ return -ENOMEM; -+ } -+ -+ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); -+ -+ return 0; -+} -+ -+static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); -+ -+ /* free physical PCI memory */ -+ if (dmabuf->mem_ptab_phys != 0) { -+ dma_unmap_single(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ dmabuf->mem_ptab_phys = 0; -+ } -+ -+ /* free kernel memory */ -+ if (dmabuf->mem_ptab_virt != NULL) { -+ free_page((unsigned long) dmabuf->mem_ptab_virt); -+ dmabuf->mem_ptab_virt = NULL; -+ } -+} -+ -+static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG free"); -+ -+ dmabuf->mem_virt = NULL; -+ if (dmabuf->mem_virt_noalign != NULL) { -+ if (dmabuf->dma_type == SAA716x_DMABUF_INT) -+ vfree(dmabuf->mem_virt_noalign); -+ -+ dmabuf->mem_virt_noalign = NULL; -+ } -+ -+ if (dmabuf->sg_list != NULL) { -+ kfree(dmabuf->sg_list); -+ dmabuf->sg_list = NULL; -+ } -+} -+ -+/* -+ * Create a SG, when an allocated buffer is passed to it, -+ * otherwise the needed memory gets allocated by itself -+ */ -+static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct scatterlist *list; -+ struct page *pg; -+ -+ int i, pages; -+ -+ BUG_ON(!(size > 0)); -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG allocate"); -+ -+ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ -+ pages = size / SAA716x_PAGE_SIZE + 1; -+ else -+ pages = size / SAA716x_PAGE_SIZE; -+ -+ /* Allocate memory for SG list */ -+ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); -+ if (dmabuf->sg_list == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); -+ return -ENOMEM; -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); -+ sg_init_table(dmabuf->sg_list, pages); -+ -+ if (buf == NULL) { -+ -+ /* allocate memory, unaligned */ -+ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); -+ if (dmabuf->mem_virt_noalign == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); -+ return -ENOMEM; -+ } -+ -+ /* align memory to page */ -+ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); -+ -+ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); -+ } else { -+ dmabuf->mem_virt = buf; -+ } -+ -+ dmabuf->list_len = pages; /* scatterlist length */ -+ list = dmabuf->sg_list; -+ -+ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); -+ for (i = 0; i < pages; i++) { -+ if (buf == NULL) -+ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ else -+ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ -+ BUG_ON(pg == NULL); -+ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Done!"); -+ return 0; -+} -+ -+/* Fill the "page table" page with the pointers to the specified SG buffer */ -+static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ struct scatterlist *sg_cur; -+ -+ u32 *page; -+ int i, j, k = 0; -+ dma_addr_t addr = 0; -+ -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(sg_list == NULL); -+ BUG_ON(pages == 0); -+ dprintk(SAA716x_DEBUG, 1, "SG page fill"); -+ -+ /* make page writable for the PC */ -+ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); -+ page = dmabuf->mem_ptab_virt; -+ -+ /* create page table */ -+ for (i = 0; i < pages; i++) { -+ sg_cur = &sg_list[i]; -+ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); -+ -+ if (i == 0) -+ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; -+ else -+ BUG_ON(sg_cur->offset != 0); -+ -+ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { -+ -+ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { -+ offset -= SAA716x_PAGE_SIZE; -+ continue; -+ } -+ -+ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; -+ -+ BUG_ON(addr == 0); -+ page[k * 2] = (u32 )addr; /* Low */ -+ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ -+ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); -+ k++; -+ } -+ } -+ -+ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { -+ page[k * 2] = (u32 ) addr; -+ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); -+ } -+ -+ /* make "page table" page writable for the PC */ -+ dma_sync_single_for_device(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_device(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_cpu(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+} -+ -+/* Allocates a DMA buffer for the specified external linear buffer. */ -+int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ int ret; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(! (size > 0)); -+ -+ dmabuf->dma_type = SAA716x_DMABUF_INT; -+ -+ dmabuf->mem_virt_noalign = NULL; -+ dmabuf->mem_virt = NULL; -+ dmabuf->mem_ptab_phys = 0; -+ dmabuf->mem_ptab_virt = NULL; -+ -+ dmabuf->list_len = 0; -+ dmabuf->saa716x = saa716x; -+ -+ /* Allocate page table */ -+ ret = saa716x_allocate_ptable(dmabuf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); -+ goto err1; -+ } -+ -+ /* Allocate buffer as SG */ -+ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); -+ goto err2; -+ } -+ -+ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG map failed"); -+ goto err3; -+ } -+ -+ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); -+ -+ return 0; -+err3: -+ saa716x_dmabuf_sgfree(dmabuf); -+err2: -+ saa716x_free_ptable(dmabuf); -+err1: -+ return ret; -+} -+ -+void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ -+ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ saa716x_dmabuf_sgfree(dmabuf); -+ saa716x_free_ptable(dmabuf); -+} -diff --git a/drivers/media/common/saa716x/saa716x_dma.h b/drivers/media/common/saa716x/saa716x_dma.h -new file mode 100644 -index 0000000..f92d667 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma.h -@@ -0,0 +1,38 @@ -+#ifndef __SAA716x_DMA_H -+#define __SAA716x_DMA_H -+ -+#define SAA716x_PAGE_SIZE 4096 -+ -+enum saa716x_dma_type { -+ SAA716x_DMABUF_EXT_LIN, /* Linear external */ -+ SAA716x_DMABUF_EXT_SG, /* SG external */ -+ SAA716x_DMABUF_INT /* Linear internal */ -+}; -+ -+struct saa716x_dev; -+ -+struct saa716x_dmabuf { -+ enum saa716x_dma_type dma_type; -+ -+ void *mem_virt_noalign; -+ void *mem_virt; /* page aligned */ -+ dma_addr_t mem_ptab_phys; -+ void *mem_ptab_virt; -+ void *sg_list; /* SG list */ -+ -+ struct saa716x_dev *saa716x; -+ -+ int list_len; /* buffer len */ -+ int offset; /* page offset */ -+}; -+ -+extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf, -+ int size); -+extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf); -+ -+extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); -+extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); -+ -+#endif /* __SAA716x_DMA_H */ -diff --git a/drivers/media/common/saa716x/saa716x_dma_reg.h b/drivers/media/common/saa716x/saa716x_dma_reg.h -new file mode 100644 -index 0000000..6037ca9 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_dma_reg.h -@@ -0,0 +1,200 @@ -+#ifndef __SAA716x_DMA_REG_H -+#define __SAA716x_DMA_REG_H -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+#endif /* __SAA716x_DMA_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff.h b/drivers/media/common/saa716x/saa716x_ff.h -new file mode 100644 -index 0000000..cb65929 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff.h -@@ -0,0 +1,158 @@ -+#ifndef __SAA716x_FF_H -+#define __SAA716x_FF_H -+ -+#include "dvb_filter.h" -+#include "dvb_ringbuffer.h" -+ -+#define TECHNOTREND 0x13c2 -+#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 -+#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A -+ -+#define TT_PREMIUM_GPIO_POWER_ENABLE 27 -+#define TT_PREMIUM_GPIO_RESET_BACKEND 26 -+#define TT_PREMIUM_GPIO_FPGA_CS1 17 -+#define TT_PREMIUM_GPIO_FPGA_CS0 16 -+#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 -+#define TT_PREMIUM_GPIO_FPGA_DONE 14 -+#define TT_PREMIUM_GPIO_FPGA_INITN 13 -+ -+/* fpga interrupt register addresses */ -+#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ -+#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ -+#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ -+#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ -+#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ -+#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ -+#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ -+#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ -+ -+/* fpga TS router register addresses */ -+#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ -+#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ -+#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ -+#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ -+#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ -+#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ -+ -+#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ -+#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ -+#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ -+#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ -+#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ -+#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ -+ -+/* fpga TS FIFO register addresses */ -+#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ -+#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ -+ -+#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ -+ -+#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ -+ -+#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ -+#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ -+#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ -+#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ -+#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ -+#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ -+#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ -+#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ -+#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ -+#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ -+#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ -+#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ -+#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ -+#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ -+#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ -+#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ -+ -+#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ -+#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ -+#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ -+#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ -+#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ -+#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ -+#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ -+#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ -+#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ -+#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ -+ -+#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ -+#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ -+#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ -+#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ -+#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ -+ -+#define SIZE_BLOCK_HEADER 8 /* block header size */ -+ -+#define MAX_RESULT_LEN 256 -+#define MAX_DATA_LEN (1024 * 1024) -+ -+#define TSOUT_LEN (1024 * TS_SIZE) -+#define TSBUF_LEN (8 * 1024) -+ -+/* place to store all the necessary device information */ -+struct sti7109_dev { -+ struct saa716x_dev *dev; -+ struct dvb_device *osd_dev; -+ struct dvb_device *video_dev; -+ struct dvb_device *audio_dev; -+ -+ void *iobuf; /* memory for all buffers */ -+ struct dvb_ringbuffer tsout; /* buffer for TS output */ -+ u8 *tsbuf; /* temp ts buffer */ -+ -+ struct tasklet_struct fifo_tasklet; -+ -+ wait_queue_head_t boot_finish_wq; -+ int boot_finished; -+ -+ wait_queue_head_t cmd_ready_wq; -+ int cmd_ready; -+ u8 cmd_data[SIZE_CMD_DATA]; -+ u32 cmd_len; -+ -+ wait_queue_head_t result_avail_wq; -+ int result_avail; -+ u8 result_data[MAX_RESULT_LEN]; -+ u32 result_len; -+ u32 result_max_len; -+ -+ wait_queue_head_t osd_cmd_ready_wq; -+ int osd_cmd_ready; -+ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; -+ u32 osd_cmd_len; -+ -+ wait_queue_head_t osd_result_avail_wq; -+ int osd_result_avail; -+ u8 osd_result_data[MAX_RESULT_LEN]; -+ u32 osd_result_len; -+ u32 osd_result_max_len; -+ -+ u16 data_handle; -+ u8 *data_buffer; /* raw data transfer buffer */ -+ wait_queue_head_t data_ready_wq; -+ int data_ready; -+ wait_queue_head_t block_done_wq; -+ int block_done; -+ -+ struct mutex cmd_lock; -+ struct mutex osd_cmd_lock; -+ struct mutex data_lock; -+ -+ u64 audio_pts; -+ u64 video_pts; -+ u64 current_stc; -+ -+ u32 int_count_enable; -+ u32 total_int_count; -+ u32 fgpi_int_count[2]; -+ u32 i2c_int_count[2]; -+ u32 ext_int_total_count; -+ u32 ext_int_source_count[16]; -+ u32 last_int_ticks; -+ -+ u16 fpga_version; -+}; -+ -+#endif /* __SAA716x_FF_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.c b/drivers/media/common/saa716x/saa716x_ff_cmd.c -new file mode 100644 -index 0000000..81c1078 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.c -@@ -0,0 +1,412 @@ -+#include -+ -+#include -+#include -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_phi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+ -+int sti7109_cmd_init(struct sti7109_dev *sti7109) -+{ -+ mutex_init(&sti7109->cmd_lock); -+ mutex_init(&sti7109->osd_cmd_lock); -+ mutex_init(&sti7109->data_lock); -+ -+ init_waitqueue_head(&sti7109->boot_finish_wq); -+ sti7109->boot_finished = 0; -+ -+ init_waitqueue_head(&sti7109->cmd_ready_wq); -+ sti7109->cmd_ready = 0; -+ -+ init_waitqueue_head(&sti7109->result_avail_wq); -+ sti7109->result_avail = 0; -+ -+ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); -+ sti7109->osd_cmd_ready = 0; -+ init_waitqueue_head(&sti7109->osd_result_avail_wq); -+ sti7109->osd_result_avail = 0; -+ -+ sti7109->data_handle = 0; -+ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); -+ init_waitqueue_head(&sti7109->data_ready_wq); -+ sti7109->data_ready = 0; -+ init_waitqueue_head(&sti7109->block_done_wq); -+ sti7109->block_done = 0; -+ return 0; -+} -+ -+static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, -+ sti7109->cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command ready"); -+ return -EIO; -+ } -+ -+ sti7109->cmd_ready = 0; -+ sti7109->result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, -+ sti7109->cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); -+ -+ if (sti7109->result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->result_avail_wq, -+ sti7109->result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { -+ sti7109->result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->result_len > sti7109->result_max_len) { -+ sti7109->result_len = sti7109->result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->cmd_len = cmd->cmd_len; -+ sti7109->result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->result_len; -+ if (sti7109->result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->result_data, -+ sti7109->result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, -+ sti7109->osd_cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command ready"); -+ return -EIO; -+ } -+ -+ sti7109->osd_cmd_ready = 0; -+ sti7109->osd_result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, -+ sti7109->osd_cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); -+ -+ if (sti7109->osd_result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->osd_result_avail_wq, -+ sti7109->osd_result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { -+ sti7109->osd_result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, -+ "osd result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { -+ sti7109->osd_result_len = sti7109->osd_result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->osd_cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->osd_cmd_len = cmd->cmd_len; -+ sti7109->osd_result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_osd_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->osd_result_len; -+ if (sti7109->osd_result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->osd_result_data, -+ sti7109->osd_result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->osd_cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ u16 blockSize; -+ u16 lastBlockSize; -+ u16 numBlocks; -+ u16 blockIndex; -+ u8 blockHeader[SIZE_BLOCK_HEADER]; -+ u8 * blockPtr; -+ int activeBlock; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, -+ sti7109->data_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); -+ return -EIO; -+ } -+ -+ sti7109->data_ready = 0; -+ -+ /* -+ * 8 bytes is the size of the block header. Block header structure is: -+ * 16 bit - block index -+ * 16 bit - number of blocks -+ * 16 bit - current block data size -+ * 16 bit - block handle. This is used to reference the data in the -+ * command that uses it. -+ */ -+ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; -+ numBlocks = data->data_length / blockSize; -+ lastBlockSize = data->data_length % blockSize; -+ if (lastBlockSize > 0) -+ numBlocks++; -+ -+ blockHeader[2] = (u8) (numBlocks >> 8); -+ blockHeader[3] = (u8) numBlocks; -+ blockHeader[6] = (u8) (sti7109->data_handle >> 8); -+ blockHeader[7] = (u8) sti7109->data_handle; -+ blockPtr = sti7109->data_buffer; -+ activeBlock = 0; -+ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { -+ u32 addr; -+ -+ if (lastBlockSize && (blockIndex == (numBlocks - 1))) -+ blockSize = lastBlockSize; -+ -+ blockHeader[0] = (uint8_t) (blockIndex >> 8); -+ blockHeader[1] = (uint8_t) blockIndex; -+ blockHeader[4] = (uint8_t) (blockSize >> 8); -+ blockHeader[5] = (uint8_t) blockSize; -+ -+ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); -+ saa716x_phi_write(saa716x, addr, blockHeader, -+ SIZE_BLOCK_HEADER); -+ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, -+ blockSize); -+ activeBlock = (activeBlock + 1) & 1; -+ if (blockIndex > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for block done"); -+ return -EIO; -+ } -+ } -+ sti7109->block_done = 0; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); -+ blockPtr += blockSize; -+ } -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); -+ return -EIO; -+ } -+ sti7109->block_done = 0; -+ -+ data->data_handle = sti7109->data_handle; -+ sti7109->data_handle++; -+ return 0; -+} -+ -+int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (data->data_length > MAX_DATA_LEN) { -+ dprintk(SAA716x_ERROR, 1, "data too big"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->data_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->data_buffer, -+ (void __user *)data->data_buffer, -+ data->data_length)) -+ goto out; -+ -+ err = sti7109_do_raw_data(sti7109, data); -+ if (err) -+ goto out; -+ -+out: -+ mutex_unlock(&sti7109->data_lock); -+ return err; -+} -+ -+int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x04; -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x00; -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x00; -+ sti7109->cmd_len = 6; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ *fw_version = (sti7109->result_data[6] << 16) -+ | (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -+int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x05; /* command length */ -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x10; /* get video format info command */ -+ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ -+ sti7109->cmd_len = 7; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ vs->w = (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ vs->h = (sti7109->result_data[9] << 8) -+ | sti7109->result_data[10]; -+ vs->aspect_ratio = sti7109->result_data[11] >> 4; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.h b/drivers/media/common/saa716x/saa716x_ff_cmd.h -new file mode 100644 -index 0000000..fc79f08 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_cmd.h -@@ -0,0 +1,16 @@ -+#ifndef __SAA716x_FF_CMD_H -+#define __SAA716x_FF_CMD_H -+ -+extern int sti7109_cmd_init(struct sti7109_dev *sti7109); -+extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_data(struct sti7109_dev * sti7109, -+ osd_raw_data_t * data); -+extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, -+ u32 *fw_version); -+extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, -+ video_size_t *vs); -+ -+#endif /* __SAA716x_FF_CMD_H */ -diff --git a/drivers/media/common/saa716x/saa716x_ff_ir.c b/drivers/media/common/saa716x/saa716x_ff_ir.c -new file mode 100644 -index 0000000..3562478 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_ir.c -@@ -0,0 +1,265 @@ -+/* -+ * Driver for the remote control of the TT6400 DVB-S2 card -+ * -+ * Copyright (C) 2010 Oliver Endriss -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ * -+ */ -+ -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+ -+ -+/* infrared remote control */ -+struct infrared { -+ u16 key_map[128]; -+ struct input_dev *input_dev; -+ char input_phys[32]; -+ struct timer_list keyup_timer; -+ struct tasklet_struct tasklet; -+ u32 command; -+ u32 device_mask; -+ u8 protocol; -+ u16 last_key; -+ u16 last_toggle; -+ bool delay_timer_finished; -+}; -+ -+#define IR_RC5 0 -+#define UP_TIMEOUT (HZ*7/25) -+ -+ -+/* key-up timer */ -+static void ir_emit_keyup(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) -+ return; -+ -+ input_report_key(ir->input_dev, ir->last_key, 0); -+ input_sync(ir->input_dev); -+} -+ -+ -+/* tasklet */ -+static void ir_emit_key(unsigned long parm) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; -+ struct infrared *ir = saa716x->ir_priv; -+ u32 ircom = ir->command; -+ u8 data; -+ u8 addr; -+ u16 toggle; -+ u16 keycode; -+ -+ /* extract device address and data */ -+ if (ircom & 0x80000000) { /* CEC remote command */ -+ addr = 0; -+ data = ircom & 0x7F; -+ toggle = 0; -+ } else { -+ switch (ir->protocol) { -+ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ -+ addr = (ircom >> 6) & 0x1f; -+ /* data bits 1..6 */ -+ data = ircom & 0x3f; -+ /* data bit 7 (inverted) */ -+ if (!(ircom & 0x1000)) -+ data |= 0x40; -+ toggle = ircom & 0x0800; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: invalid protocol %x\n", -+ __func__, ir->protocol); -+ return; -+ } -+ } -+ -+ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); -+ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); -+ -+ keycode = ir->key_map[data]; -+ -+ dprintk(SAA716x_DEBUG, 0, -+ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", -+ __func__, ircom, addr, data, keycode); -+ -+ /* check device address */ -+ if (!(ir->device_mask & (1 << addr))) -+ return; -+ -+ if (!keycode) { -+ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", -+ __func__, ircom, addr, data); -+ return; -+ } -+ -+ if (timer_pending(&ir->keyup_timer)) { -+ del_timer(&ir->keyup_timer); -+ if (ir->last_key != keycode || toggle != ir->last_toggle) { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } else if (ir->delay_timer_finished) { -+ input_event(ir->input_dev, EV_KEY, keycode, 2); -+ input_sync(ir->input_dev); -+ } -+ } else { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } -+ -+ ir->last_key = keycode; -+ ir->last_toggle = toggle; -+ -+ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; -+ add_timer(&ir->keyup_timer); -+ -+} -+ -+ -+/* register with input layer */ -+static void ir_register_keys(struct infrared *ir) -+{ -+ int i; -+ -+ set_bit(EV_KEY, ir->input_dev->evbit); -+ set_bit(EV_REP, ir->input_dev->evbit); -+ set_bit(EV_MSC, ir->input_dev->evbit); -+ -+ set_bit(MSC_RAW, ir->input_dev->mscbit); -+ set_bit(MSC_SCAN, ir->input_dev->mscbit); -+ -+ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); -+ -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { -+ if (ir->key_map[i] > KEY_MAX) -+ ir->key_map[i] = 0; -+ else if (ir->key_map[i] > KEY_RESERVED) -+ set_bit(ir->key_map[i], ir->input_dev->keybit); -+ } -+ -+ ir->input_dev->keycode = ir->key_map; -+ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); -+ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); -+} -+ -+ -+/* called by the input driver after rep[REP_DELAY] ms */ -+static void ir_repeat_key(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ ir->delay_timer_finished = true; -+} -+ -+ -+/* interrupt handler */ -+void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ if (!ir) -+ return; -+ -+ ir->command = ir_cmd; -+ tasklet_schedule(&ir->tasklet); -+} -+ -+ -+int saa716x_ir_init(struct saa716x_dev *saa716x) -+{ -+ struct input_dev *input_dev; -+ struct infrared *ir; -+ int rc; -+ int i; -+ -+ if (!saa716x) -+ return -ENOMEM; -+ -+ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); -+ if (!ir) -+ return -ENOMEM; -+ -+ init_timer(&ir->keyup_timer); -+ ir->keyup_timer.function = ir_emit_keyup; -+ ir->keyup_timer.data = (unsigned long) ir; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto err; -+ -+ ir->input_dev = input_dev; -+ input_dev->name = "TT6400 DVB IR receiver"; -+ snprintf(ir->input_phys, sizeof(ir->input_phys), -+ "pci-%s/ir0", pci_name(saa716x->pdev)); -+ input_dev->phys = ir->input_phys; -+ input_dev->id.bustype = BUS_PCI; -+ input_dev->id.version = 1; -+ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; -+ input_dev->id.product = saa716x->pdev->subsystem_device; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -+ input_dev->dev.parent = &saa716x->pdev->dev; -+#else -+ input_dev->cdev.dev = &saa716x->pdev->dev; -+#endif -+ rc = input_register_device(input_dev); -+ if (rc) -+ goto err; -+ -+ /* TODO: fix setup/keymap */ -+ ir->protocol = IR_RC5; -+ ir->device_mask = 0xffffffff; -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) -+ ir->key_map[i] = i+1; -+ ir_register_keys(ir); -+ -+ /* override repeat timer */ -+ input_dev->timer.function = ir_repeat_key; -+ input_dev->timer.data = (unsigned long) ir; -+ -+ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); -+ saa716x->ir_priv = ir; -+ -+ return 0; -+ -+err: -+ if (ir->input_dev) -+ input_free_device(ir->input_dev); -+ kfree(ir); -+ return -ENOMEM; -+} -+ -+ -+void saa716x_ir_exit(struct saa716x_dev *saa716x) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ saa716x->ir_priv = NULL; -+ tasklet_kill(&ir->tasklet); -+ del_timer_sync(&ir->keyup_timer); -+ input_unregister_device(ir->input_dev); -+ kfree(ir); -+} -diff --git a/drivers/media/common/saa716x/saa716x_ff_main.c b/drivers/media/common/saa716x/saa716x_ff_main.c -new file mode 100644 -index 0000000..34093c2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_ff_main.c -@@ -0,0 +1,1535 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_dma_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_phi_reg.h" -+#include "saa716x_spi_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_vip.h" -+#include "saa716x_aip.h" -+#include "saa716x_msi.h" -+#include "saa716x_adap.h" -+#include "saa716x_gpio.h" -+#include "saa716x_phi.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "isl6423.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+unsigned int int_count_enable; -+module_param(int_count_enable, int, 0644); -+MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); -+ -+#define DRIVER_NAME "SAA716x FF" -+ -+static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ int fpgaInit; -+ int fpgaDone; -+ int rounds; -+ int ret; -+ const struct firmware *fw; -+ -+ /* request the FPGA firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," -+ " file not found: dvb-ttpremium-fpga-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ /* set FPGA PROGRAMN high */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN low to set it into configuration mode */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN high to start configuration process */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ -+ rounds = 0; -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ while (fpgaInit == 0 && rounds < 5000) { -+ //msleep(1); -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ rounds++; -+ } -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", -+ fpgaInit, rounds); -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); -+ -+ msleep(10); -+ -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); -+ saa716x_spi_write(saa716x, fw->data, fw->size); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ if (!fpgaDone) { -+ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " -+ "connect the power supply?\n"); -+ return -EINVAL; -+ } -+ -+ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); -+ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", -+ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); -+ -+ return 0; -+} -+ -+static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) -+{ -+ int i; -+ int length; -+ u32 requestedBlock; -+ u32 writtenBlock; -+ u32 numBlocks; -+ u32 blockSize; -+ u32 lastBlockSize; -+ u64 startTime; -+ u64 currentTime; -+ u64 waitTime; -+ int ret; -+ const struct firmware *fw; -+ u32 loaderVersion; -+ -+ /* request the st7109 loader, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," -+ " file not found: dvb-ttpremium-loader-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; -+ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", -+ loaderVersion >> 8, loaderVersion & 0xFF); -+ -+ saa716x_phi_write(saa716x, 0, fw->data, fw->size); -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ /* take ST out of reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); -+ -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == 1) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ return -1; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); -+ -+ /* request the st7109 firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," -+ " file not found: dvb-ttpremium-st7109-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); -+ writtenBlock = 0; -+ blockSize = 0x3c00; -+ length = fw->size; -+ numBlocks = length / blockSize; -+ lastBlockSize = length % blockSize; -+ for (i = 0; i < length; i += blockSize) { -+ writtenBlock++; -+ /* write one block (last may differ from blockSize) */ -+ if (lastBlockSize && writtenBlock == (numBlocks + 1)) -+ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); -+ else -+ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); -+ -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == (writtenBlock + 1)) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ release_firmware(fw); -+ return -1; -+ } -+ } -+ -+ /* disable frontend support through ST firmware */ -+ SAA716x_EPWR(PHI_1, 0x3ff4, 1); -+ -+ /* indicate end of transfer */ -+ writtenBlock++; -+ writtenBlock |= 0x80000000; -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); -+ -+ release_firmware(fw); -+ -+ return 0; -+} -+ -+static int saa716x_usercopy(struct dvb_device *dvbdev, -+ unsigned int cmd, unsigned long arg, -+ int (*func)(struct dvb_device *dvbdev, -+ unsigned int cmd, void *arg)) -+{ -+ char sbuf[128]; -+ void *mbuf = NULL; -+ void *parg = NULL; -+ int err = -EINVAL; -+ -+ /* Copy arguments into temp kernel buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_NONE: -+ /* -+ * For this command, the pointer is actually an integer -+ * argument. -+ */ -+ parg = (void *) arg; -+ break; -+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -+ case _IOC_WRITE: -+ case (_IOC_WRITE | _IOC_READ): -+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -+ parg = sbuf; -+ } else { -+ /* too big to allocate from stack */ -+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); -+ if (NULL == mbuf) -+ return -ENOMEM; -+ parg = mbuf; -+ } -+ -+ err = -EFAULT; -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto out; -+ break; -+ } -+ -+ /* call driver */ -+ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) -+ err = -EINVAL; -+ -+ if (err < 0) -+ goto out; -+ -+ /* Copy results into user buffer */ -+ switch (_IOC_DIR(cmd)) -+ { -+ case _IOC_READ: -+ case (_IOC_WRITE | _IOC_READ): -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ break; -+ } -+ -+out: -+ kfree(mbuf); -+ return err; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_osd_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_osd_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ int err = -EINVAL; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ if (cmd == OSD_RAW_CMD) { -+ osd_raw_cmd_t raw_cmd; -+ u8 hdr[4]; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_cmd, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) -+ goto out; -+ -+ if (hdr[3] == 4) -+ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); -+ else -+ err = sti7109_raw_cmd(sti7109, &raw_cmd); -+ -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ else if (cmd == OSD_RAW_DATA) { -+ osd_raw_data_t raw_data; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_data, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ err = sti7109_raw_data(sti7109, &raw_data); -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ -+out: -+ return err; -+} -+ -+static struct file_operations dvb_osd_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_osd_ioctl, -+#else -+ .unlocked_ioctl = dvb_osd_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_osd = { -+ .priv = NULL, -+ .users = 2, -+ .writers = 2, -+ .fops = &dvb_osd_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->osd_dev); -+ return 0; -+} -+ -+static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->osd_dev, -+ &dvbdev_osd, -+ sti7109, -+ DVB_DEVICE_OSD); -+ -+ return 0; -+} -+ -+static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ //struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case AUDIO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->audio_pts; -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_audio_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_audio_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); -+} -+ -+static struct file_operations dvb_audio_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_audio_ioctl, -+#else -+ .unlocked_ioctl = dvb_audio_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_audio = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_audio_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->audio_dev); -+ return 0; -+} -+ -+static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->audio_dev, -+ &dvbdev_audio, -+ sti7109, -+ DVB_DEVICE_AUDIO); -+ -+ return 0; -+} -+ -+static void fifo_worker(unsigned long data) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ u32 fifoCtrl; -+ u32 fifoStat; -+ u16 fifoSize; -+ u16 fifoUsage; -+ u16 fifoFree; -+ int len; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); -+ fifoSize = (u16) (fifoStat >> 16); -+ fifoUsage = (u16) fifoStat; -+ fifoFree = fifoSize - fifoUsage; -+ spin_lock(&sti7109->tsout.lock); -+ len = dvb_ringbuffer_avail(&sti7109->tsout); -+ if (len > fifoFree) -+ len = fifoFree; -+ if (len >= TS_SIZE) -+ { -+ while (len >= TS_SIZE) -+ { -+ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); -+ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); -+ len -= TS_SIZE; -+ } -+ wake_up(&sti7109->tsout.queue); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ spin_unlock(&sti7109->tsout.lock); -+} -+ -+#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) -+ -+static ssize_t dvb_video_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ unsigned long todo = count; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ return -EPERM; -+/* -+ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) -+ return -EPERM; -+*/ -+ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) -+ return -EWOULDBLOCK; -+ -+ while (todo >= TS_SIZE) { -+ if (!FREE_COND_TS) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) -+ break; -+ } -+ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); -+ todo -= TS_SIZE; -+ buf += TS_SIZE; -+ } -+ -+ if (count > todo) { -+ u32 fifoCtrl; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ -+ return count - todo; -+} -+ -+static unsigned int dvb_video_poll(struct file *file, poll_table *wait) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ unsigned int mask = 0; -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) -+ poll_wait(file, &sti7109->tsout.queue, wait); -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { -+ if (1/*sti7109->playing*/) { -+ if (FREE_COND_TS) -+ mask |= (POLLOUT | POLLWRNORM); -+ } else /* if not playing: may play if asked for */ -+ mask |= (POLLOUT | POLLWRNORM); -+ } -+ -+ return mask; -+} -+ -+static int do_dvb_video_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case VIDEO_SELECT_SOURCE: -+ { -+ video_stream_source_t stream_source; -+ -+ stream_source = (video_stream_source_t) parg; -+ if (stream_source == VIDEO_SOURCE_DEMUX) { -+ /* stop and reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ } -+ else { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ /* reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ /* start FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); -+ } -+ break; -+ } -+ case VIDEO_CLEAR_BUFFER: -+ { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ break; -+ } -+ case VIDEO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->video_pts; -+ break; -+ } -+ case VIDEO_GET_SIZE: -+ { -+ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_video_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_video_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); -+} -+ -+static struct file_operations dvb_video_fops = { -+ .owner = THIS_MODULE, -+ .write = dvb_video_write, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_video_ioctl, -+#else -+ .unlocked_ioctl = dvb_video_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+ .poll = dvb_video_poll, -+}; -+ -+static struct dvb_device dvbdev_video = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_video_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ tasklet_kill(&sti7109->fifo_tasklet); -+ dvb_unregister_device(sti7109->video_dev); -+ return 0; -+} -+ -+static int saa716x_ff_video_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); -+ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->video_dev, -+ &dvbdev_video, -+ sti7109, -+ DVB_DEVICE_VIDEO); -+ -+ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, -+ (unsigned long)saa716x); -+ -+ return 0; -+} -+ -+static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ struct sti7109_dev *sti7109; -+ int err = 0; -+ u32 value; -+ unsigned long timeout; -+ u32 fw_version; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ err = saa716x_phi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ /* prepare the sti7109 device struct */ -+ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); -+ if (!sti7109) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); -+ goto fail3; -+ } -+ -+ sti7109->dev = saa716x; -+ -+ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); -+ if (!sti7109->iobuf) -+ goto fail4; -+ -+ sti7109_cmd_init(sti7109); -+ -+ sti7109->int_count_enable = int_count_enable; -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ -+ saa716x->priv = sti7109; -+ -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ -+ /* hold ST in reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); -+ -+ /* enable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); -+ msleep(100); -+ -+ err = saa716x_ff_fpga_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); -+ goto fail5; -+ } -+ -+ /* configure TS muxer */ -+ if (sti7109->fpga_version < 0x110) { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); -+ } else { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); -+ } -+ -+ /* enable interrupts from ST7109 -> PC */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); -+ -+ value = SAA716x_EPRD(MSI, MSI_CONFIG33); -+ value &= 0xFCFFFFFF; -+ value |= MSI_INT_POL_EDGE_FALL; -+ SAA716x_EPWR(MSI, MSI_CONFIG33, value); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); -+ -+ /* enable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); -+ msleep(50); -+ /* disable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); -+ -+ err = saa716x_ff_st7109_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); -+ goto fail5; -+ } -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable FGPI2 and FGPI3 for TS inputs */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail6; -+ } -+ -+ /* wait a maximum of 10 seconds for the STi7109 to boot */ -+ timeout = 10 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, -+ sti7109->boot_finished == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ goto fail6; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); -+ err = -1; -+ goto fail6; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); -+ -+ err = saa716x_ff_video_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); -+ goto fail7; -+ } -+ -+ err = saa716x_ff_audio_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); -+ goto fail8; -+ } -+ -+ err = saa716x_ff_osd_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); -+ goto fail9; -+ } -+ -+ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); -+ if (!err) { -+ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", -+ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, -+ fw_version & 0xFF); -+ } -+ -+ err = saa716x_ir_init(saa716x); -+ if (err) -+ goto fail9; -+ -+ return 0; -+ -+fail9: -+ saa716x_ff_osd_exit(saa716x); -+fail8: -+ saa716x_ff_audio_exit(saa716x); -+fail7: -+ saa716x_ff_video_exit(saa716x); -+fail6: -+ saa716x_dvb_exit(saa716x); -+fail5: -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+fail4: -+ kfree(sti7109); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_ff_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ saa716x_ir_exit(saa716x); -+ -+ saa716x_ff_osd_exit(saa716x); -+ -+ saa716x_ff_audio_exit(saa716x); -+ -+ saa716x_ff_video_exit(saa716x); -+ -+ saa716x_dvb_exit(saa716x); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+ -+ saa716x->priv = NULL; -+ kfree(sti7109); -+ -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ struct sti7109_dev *sti7109; -+ u32 msiStatusL; -+ u32 msiStatusH; -+ u32 phiISR; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ sti7109 = saa716x->priv; -+ if (unlikely(sti7109 == NULL)) { -+ printk("%s: sti7109=NULL", __func__); -+ return IRQ_NONE; -+ } -+ if (sti7109->int_count_enable) -+ sti7109->total_int_count++; -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); -+ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); -+ -+ if (msiStatusL) { -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[0]++; -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[1]++; -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ if (msiStatusH) { -+ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); -+ } -+ -+ if (msiStatusH & MSI_INT_I2CINT_0) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[0]++; -+ saa716x->i2c[0].i2c_op = 0; -+ wake_up(&saa716x->i2c[0].i2c_wq); -+ } -+ if (msiStatusH & MSI_INT_I2CINT_1) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[1]++; -+ saa716x->i2c[1].i2c_op = 0; -+ wake_up(&saa716x->i2c[1].i2c_wq); -+ } -+ -+ if (msiStatusH & MSI_INT_EXTINT_0) { -+ -+ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); -+ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); -+ -+ if (sti7109->int_count_enable) { -+ int i; -+ sti7109->ext_int_total_count++; -+ for (i = 0; i < 16; i++) -+ if (phiISR & (1 << i)) -+ sti7109->ext_int_source_count[i]++; -+ } -+ -+ if (phiISR & ISR_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); -+ sti7109->result_len = length; -+ sti7109->result_avail = 1; -+ wake_up(&sti7109->result_avail_wq); -+ -+ phiISR &= ~ISR_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ -+ sti7109->cmd_ready = 1; -+ wake_up(&sti7109->cmd_ready_wq); -+ phiISR &= ~ISR_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); -+ sti7109->osd_result_len = length; -+ sti7109->osd_result_avail = 1; -+ wake_up(&sti7109->osd_result_avail_wq); -+ -+ phiISR &= ~ISR_OSD_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ -+ sti7109->osd_cmd_ready = 1; -+ wake_up(&sti7109->osd_cmd_ready_wq); -+ phiISR &= ~ISR_OSD_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); -+ } -+ -+ if (phiISR & ISR_BLOCK_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ -+ sti7109->block_done = 1; -+ wake_up(&sti7109->block_done_wq); -+ phiISR &= ~ISR_BLOCK_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); -+ } -+ -+ if (phiISR & ISR_DATA_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ -+ sti7109->data_ready = 1; -+ wake_up(&sti7109->data_ready_wq); -+ phiISR &= ~ISR_DATA_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); -+ } -+ -+ if (phiISR & ISR_BOOT_FINISH_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ -+ sti7109->boot_finished = 1; -+ wake_up(&sti7109->boot_finish_wq); -+ phiISR &= ~ISR_BOOT_FINISH_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); -+ } -+ -+ if (phiISR & ISR_AUDIO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); -+ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_AUDIO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ -+ } -+ -+ if (phiISR & ISR_VIDEO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); -+ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_VIDEO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ -+ } -+ -+ if (phiISR & ISR_CURRENT_STC_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); -+ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_CURRENT_STC_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ -+ } -+ -+ if (phiISR & ISR_REMOTE_EVENT_MASK) { -+ u8 data[4]; -+ u32 remote_event; -+ -+ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ remote_event = (data[3] << 24) -+ | (data[2] << 16) -+ | (data[1] << 8) -+ | (data[0]); -+ memset(data, 0, sizeof(data)); -+ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ -+ phiISR &= ~ISR_REMOTE_EVENT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); -+ -+ if (remote_event == 0) { -+ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); -+ } else { -+ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); -+ saa716x_ir_handler(saa716x, remote_event); -+ } -+ } -+ -+ if (phiISR & ISR_DVO_FORMAT_MASK) { -+ u8 data[4]; -+ u32 format; -+ -+ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); -+ format = (data[0] << 24) -+ | (data[1] << 16) -+ | (data[2] << 8) -+ | (data[3]); -+ -+ phiISR &= ~ISR_DVO_FORMAT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); -+ } -+ -+ if (phiISR & ISR_LOG_MESSAGE_MASK) { -+ char message[SIZE_LOG_MESSAGE_DATA]; -+ -+ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, -+ SIZE_LOG_MESSAGE_DATA); -+ -+ phiISR &= ~ISR_LOG_MESSAGE_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", -+ SIZE_LOG_MESSAGE_DATA, message); -+ } -+ -+ if (phiISR & ISR_FIFO1_EMPTY_MASK) { -+ u32 fifoCtrl; -+ -+ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl &= ~0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ tasklet_schedule(&sti7109->fifo_tasklet); -+ phiISR &= ~ISR_FIFO1_EMPTY_MASK; -+ } -+ -+ if (phiISR) { -+ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); -+ } -+ } -+ -+ if (sti7109->int_count_enable) { -+ if (jiffies - sti7109->last_int_ticks >= HZ) { -+ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," -+ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", -+ sti7109->total_int_count, -+ sti7109->fgpi_int_count[0], -+ sti7109->fgpi_int_count[1], -+ sti7109->i2c_int_count[0], -+ sti7109->i2c_int_count[1], -+ sti7109->ext_int_total_count, -+ sti7109->ext_int_source_count[0], -+ sti7109->ext_int_source_count[1], -+ sti7109->ext_int_source_count[2], -+ sti7109->ext_int_source_count[3], -+ sti7109->ext_int_source_count[4], -+ sti7109->ext_int_source_count[5], -+ sti7109->ext_int_source_count[6], -+ sti7109->ext_int_source_count[7], -+ sti7109->ext_int_source_count[8], -+ sti7109->ext_int_source_count[9], -+ sti7109->ext_int_source_count[10], -+ sti7109->ext_int_source_count[11], -+ sti7109->ext_int_source_count[12], -+ sti7109->ext_int_source_count[13], -+ sti7109->ext_int_source_count[14], -+ sti7109->ext_int_source_count[15]); -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" -+#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" -+ -+static struct stv090x_config tt6400_stv090x_config = { -+ .device = STV0900, -+ .demod_mode = STV090x_DUAL, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 13500000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts1_clk = 135000000, -+ .ts2_clk = 135000000, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static struct stv6110x_config tt6400_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 27000000, -+ .clk_div = 2, -+}; -+ -+static struct isl6423_config tt6400_isl6423_config[2] = { -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x09, -+ }, -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x08, -+ } -+}; -+ -+ -+static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ if (count == 0 || count == 1) { -+ adapter->fe = dvb_attach(stv090x_attach, -+ &tt6400_stv090x_config, -+ i2c_adapter, -+ STV090x_DEMODULATOR_0 + count); -+ -+ if (adapter->fe) { -+ struct stv6110x_devctl *ctl; -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &tt6400_stv6110x_config, -+ i2c_adapter); -+ -+ tt6400_stv090x_config.tuner_init = ctl->tuner_init; -+ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ if (count == 1) { -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ /* The second tuner drives the STV0900 so -+ call it only for adapter 1 */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } -+ -+ dvb_attach(isl6423_attach, -+ adapter->fe, -+ i2c_adapter, -+ &tt6400_isl6423_config[count]); -+ -+ } -+ } -+ return 0; -+} -+ -+static struct saa716x_config saa716x_s26400_config = { -+ .model_name = SAA716x_MODEL_S2_6400_DUAL, -+ .dev_type = SAA716x_DEV_S2_6400_DUAL, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_s26400_frontend_attach, -+ .irq_handler = saa716x_ff_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 2, -+ .worker = demux_worker -+ },{ -+ /* Adapter 1 */ -+ .ts_port = 3, -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+static struct pci_device_id saa716x_ff_pci_table[] = { -+ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); -+ -+static struct pci_driver saa716x_ff_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_ff_pci_table, -+ .probe = saa716x_ff_pci_probe, -+ .remove = saa716x_ff_pci_remove, -+}; -+ -+static int saa716x_ff_init(void) -+{ -+ return pci_register_driver(&saa716x_ff_pci_driver); -+} -+ -+static void saa716x_ff_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_ff_pci_driver); -+} -+ -+module_init(saa716x_ff_init); -+module_exit(saa716x_ff_exit); -+ -+MODULE_DESCRIPTION("SAA716x FF driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_fgpi.c b/drivers/media/common/saa716x/saa716x_fgpi.c -new file mode 100644 -index 0000000..8bdb13d ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi.c -@@ -0,0 +1,389 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static const u32 mmu_pta_base[] = { -+ MMU_PTA_BASE0, -+ MMU_PTA_BASE1, -+ MMU_PTA_BASE2, -+ MMU_PTA_BASE3, -+ MMU_PTA_BASE4, -+ MMU_PTA_BASE5, -+ MMU_PTA_BASE6, -+ MMU_PTA_BASE7, -+ MMU_PTA_BASE8, -+ MMU_PTA_BASE9, -+ MMU_PTA_BASE10, -+ MMU_PTA_BASE11, -+ MMU_PTA_BASE12, -+ MMU_PTA_BASE13, -+ MMU_PTA_BASE14, -+ MMU_PTA_BASE15, -+}; -+ -+static const u32 mmu_dma_cfg[] = { -+ MMU_DMA_CONFIG0, -+ MMU_DMA_CONFIG1, -+ MMU_DMA_CONFIG2, -+ MMU_DMA_CONFIG3, -+ MMU_DMA_CONFIG4, -+ MMU_DMA_CONFIG5, -+ MMU_DMA_CONFIG6, -+ MMU_DMA_CONFIG7, -+ MMU_DMA_CONFIG8, -+ MMU_DMA_CONFIG9, -+ MMU_DMA_CONFIG10, -+ MMU_DMA_CONFIG11, -+ MMU_DMA_CONFIG12, -+ MMU_DMA_CONFIG13, -+ MMU_DMA_CONFIG14, -+ MMU_DMA_CONFIG15, -+}; -+ -+static const u32 fgpi_ch[] = { -+ FGPI0, -+ FGPI1, -+ FGPI2, -+ FGPI3 -+}; -+ -+static const u32 bamdma_bufmode[] = { -+ BAM_FGPI0_DMA_BUF_MODE, -+ BAM_FGPI1_DMA_BUF_MODE, -+ BAM_FGPI2_DMA_BUF_MODE, -+ BAM_FGPI3_DMA_BUF_MODE -+}; -+ -+static const u32 msi_int_tagack[] = { -+ MSI_INT_TAGACK_FGPI_0, -+ MSI_INT_TAGACK_FGPI_1, -+ MSI_INT_TAGACK_FGPI_2, -+ MSI_INT_TAGACK_FGPI_3 -+}; -+ -+static const u32 msi_int_ovrflw[] = { -+ MSI_INT_OVRFLW_FGPI_0, -+ MSI_INT_OVRFLW_FGPI_1, -+ MSI_INT_OVRFLW_FGPI_2, -+ MSI_INT_OVRFLW_FGPI_3 -+}; -+ -+static const u32 msi_int_avint[] = { -+ MSI_INT_AVINT_FGPI_0, -+ MSI_INT_AVINT_FGPI_1, -+ MSI_INT_AVINT_FGPI_2, -+ MSI_INT_AVINT_FGPI_3 -+}; -+ -+void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port; -+ -+ fgpi_port = fgpi_ch[channel]; -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ -+ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); -+ -+int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) -+{ -+ u32 fgpi_base; -+ u32 buf_mode_reg; -+ u32 buf_mode; -+ -+ switch (fgpi_index) { -+ case 0: /* FGPI_0 */ -+ fgpi_base = FGPI0; -+ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; -+ break; -+ -+ case 1: /* FGPI_1 */ -+ fgpi_base = FGPI1; -+ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; -+ break; -+ -+ case 2: /* FGPI_2 */ -+ fgpi_base = FGPI2; -+ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; -+ break; -+ -+ case 3: /* FGPI_3 */ -+ fgpi_base = FGPI3; -+ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: unexpected fgpi %u\n", -+ __func__, fgpi_index); -+ return -1; -+ } -+ -+ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); -+ if (saa716x->revision < 2) { -+ /* workaround for revision 1: restore buffer numbers on BAM */ -+ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); -+ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); -+ } -+ return (buf_mode >> 3) & 0x7; -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); -+ -+static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 config, i; -+ -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); -+ -+ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ -+ -+ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); -+ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ -+ -+ return 0; -+} -+ -+int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, -+ struct fgpi_stream_params *stream_params, -+ int port) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port, buf_mode, val, mid; -+ u32 D1_XY_END, offst_1, offst_2; -+ int i = 0; -+ -+ fgpi_port = fgpi_ch[port]; -+ buf_mode = bamdma_bufmode[port]; -+ -+ /* Reset FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* Reset DMA channel */ -+ SAA716x_EPWR(BAM, buf_mode, 0x00000040); -+ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); -+ -+ -+ /* monitor BAM reset */ -+ val = SAA716x_EPRD(BAM, buf_mode); -+ while (val && (i < 100)) { -+ msleep(30); -+ val = SAA716x_EPRD(BAM, buf_mode); -+ i++; -+ } -+ -+ if (val) { -+ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); -+ return -EIO; -+ } -+ -+ /* set buffer count */ -+ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); -+ -+ /* initialize all available address offsets */ -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); -+ -+ /* get module ID */ -+ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); -+ if (mid != 0x14b0100) -+ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); -+ -+ /* Initialize FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); -+ -+ offst_1 = 0; -+ offst_2 = 0; -+ switch (stream_params->stream_type) { -+ case FGPI_TRANSPORT_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_PROGRAM_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_VIDEO_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); -+ -+ if ((stream_params->stream_flags & FGPI_INTERLACED) && -+ (stream_params->stream_flags & FGPI_ODD_FIELD) && -+ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { -+ -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ -+ -+ D1_XY_END = (stream_params->samples << 16); -+ D1_XY_END |= (stream_params->lines / 2) + 2; -+ -+ if (stream_params->stream_flags & FGPI_PAL) -+ offst_1 = 768 * 2; -+ else -+ offst_2 = 768 * 2; -+ -+ } else { -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ -+ -+ D1_XY_END = stream_params->samples << 16; -+ D1_XY_END |= stream_params->lines + 2; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); -+ break; -+ -+ default: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ break; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params) -+{ -+ u32 fgpi_port; -+ u32 config; -+ u32 val; -+ u32 i; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); -+ msleep(10); -+ -+ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { -+ return -EIO; -+ } -+ -+ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ -+ -+ val = SAA716x_EPRD(MMU, config); -+ SAA716x_EPWR(MMU, config, val & ~0x40); -+ SAA716x_EPWR(MMU, config, val | 0x40); -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); -+ -+ val = SAA716x_EPRD(MMU, config); -+ i = 0; -+ while (i < 500) { -+ if (val & 0x80) -+ break; -+ msleep(10); -+ val = SAA716x_EPRD(MMU, config); -+ i++; -+ } -+ -+ if (!(val & 0x80)) { -+ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); -+ return -EIO; -+ } -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val |= 0x3000; -+ -+ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) -+{ -+ u32 fgpi_port; -+ u32 val; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val &= ~0x3000; -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)) -+{ -+ int i; -+ int ret; -+ -+ saa716x->fgpi[port].dma_channel = port + 6; -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ /* TODO: what is a good size for TS DMA buffer? */ -+ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ saa716x->fgpi[port].saa716x = saa716x; -+ tasklet_init(&saa716x->fgpi[port].tasklet, worker, -+ (unsigned long)&saa716x->fgpi[port]); -+ saa716x->fgpi[port].read_index = 0; -+ -+ return 0; -+} -+ -+int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) -+{ -+ int i; -+ -+ tasklet_kill(&saa716x->fgpi[port].tasklet); -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); -+ } -+ -+ return 0; -+} -diff --git a/drivers/media/common/saa716x/saa716x_fgpi.h b/drivers/media/common/saa716x/saa716x_fgpi.h -new file mode 100644 -index 0000000..225aff0 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi.h -@@ -0,0 +1,112 @@ -+#ifndef __SAA716x_FGPI_H -+#define __SAA716x_FGPI_H -+ -+#include -+ -+#define FGPI_BUFFERS 8 -+#define PTA_LSB(__mem) ((u32 ) (__mem)) -+#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) -+ -+#define BAM_DMA_BUF_MODE_BASE 0x0d8 -+#define BAM_DMA_BUF_MODE_OFFSET 0x24 -+ -+#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc -+#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 -+ -+#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 -+#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 -+#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 -+#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c -+#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 -+#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 -+#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 -+#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c -+ -+struct saa716x_dmabuf; -+ -+/* -+ * Port supported streams -+ * -+ * FGPI_AUDIO_STREAM -+ * FGPI_VIDEO_STREAM -+ * FGPI_VBI_STREAM -+ * FGPI_TRANSPORT_STREAM -+ * FGPI_PROGRAM_STREAM -+ */ -+enum fgpi_stream_type { -+ FGPI_AUDIO_STREAM = 0x01, -+ FGPI_VIDEO_STREAM = 0x02, -+ FGPI_VBI_STREAM = 0x04, -+ FGPI_TRANSPORT_STREAM = 0x08, -+ FGPI_PROGRAM_STREAM = 0x10 -+}; -+ -+/* -+ * Stream port flags -+ * -+ * FGPI_ODD_FIELD -+ * FGPI_EVEN_FIELD -+ * FGPI_HD_0 -+ * FGPI_HD_1 -+ * FGPI_PAL -+ * FGPI_NTSC -+ */ -+enum fgpi_stream_flags { -+ FGPI_ODD_FIELD = 0x0001, -+ FGPI_EVEN_FIELD = 0x0002, -+ FGPI_INTERLACED = 0x0004, -+ FGPI_HD0 = 0x0010, -+ FGPI_HD1 = 0x0020, -+ FGPI_PAL = 0x0040, -+ FGPI_NTSC = 0x0080, -+ FGPI_NO_SCALER = 0x0100, -+}; -+ -+/* -+ * Stream port parameters -+ * bits: Bits per sample -+ * samples: samples perline -+ * lines: number of lines -+ * pitch: stream pitch in bytes -+ * offset: offset to first valid line -+ */ -+struct fgpi_stream_params { -+ u32 bits; -+ u32 samples; -+ u32 lines; -+ -+ s32 pitch; -+ -+ u32 offset; -+ u32 page_tables; -+ -+ enum fgpi_stream_flags stream_flags; -+ enum fgpi_stream_type stream_type; -+}; -+ -+struct saa716x_dmabuf; -+ -+struct saa716x_fgpi_stream_port { -+ u8 dma_channel; -+ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; -+ struct saa716x_dev *saa716x; -+ struct tasklet_struct tasklet; -+ u8 read_index; -+}; -+ -+extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); -+extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, -+ u32 fgpi_index); -+extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params); -+extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); -+ -+extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)); -+extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); -+ -+#endif /* __SAA716x_FGPI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_fgpi_reg.h b/drivers/media/common/saa716x/saa716x_fgpi_reg.h -new file mode 100644 -index 0000000..1193016 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_fgpi_reg.h -@@ -0,0 +1,74 @@ -+#ifndef __SAA716x_FGPI_REG_H -+#define __SAA716x_FGPI_REG_H -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+#endif /* __SAA716x_FGPI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_gpio.c b/drivers/media/common/saa716x/saa716x_gpio.c -new file mode 100644 -index 0000000..62b6112 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio.c -@@ -0,0 +1,140 @@ -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+ -+#include "saa716x_gpio.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_gpio_init(struct saa716x_dev *saa716x) -+{ -+ spin_lock_init(&saa716x->gpio_lock); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_init); -+ -+int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) -+{ -+ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ -+ return 0; -+} -+ -+int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ reg &= ~mask; -+ reg |= (config & mask); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) -+{ -+ return SAA716x_EPRD(GPIO, GPIO_RD); -+} -+ -+void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) -+{ -+ SAA716x_EPWR(GPIO, GPIO_WR, data); -+} -+ -+void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_OEN); -+ reg &= mask; -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_OEN, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_WR); -+ reg &= ~bits; -+ /* TODO ! add maskable config bits in here */ -+ /* reg |= (config->mask & bits) */ -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_WR, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); -+ -+void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value |= 1 << gpio; -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); -+ -+void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ if (mode) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); -+ -+void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) -+{ -+ uint32_t value; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ value = SAA716x_EPRD(GPIO, GPIO_WR); -+ if (set) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR, value); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_write); -+ -+int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_RD); -+ if (value & (1 << gpio)) -+ return 1; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_read); -diff --git a/drivers/media/common/saa716x/saa716x_gpio.h b/drivers/media/common/saa716x/saa716x_gpio.h -new file mode 100644 -index 0000000..a82580b ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio.h -@@ -0,0 +1,26 @@ -+#ifndef __SAA716x_GPIO_H -+#define __SAA716x_GPIO_H -+ -+#define BOOT_MODE GPIO_31 | GPIO_30 -+#define AV_UNIT_B GPIO_25 -+#define AV_UNIT_A GPIO_24 -+#define AV_INTR_B GPIO_01 -+#define AV_INTR_A GPIO_00 -+ -+struct saa716x_dev; -+ -+extern void saa716x_gpio_init(struct saa716x_dev *saa716x); -+ -+extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); -+extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); -+extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); -+ -+extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); -+ -+extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); -+extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); -+extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); -+ -+#endif /* __SAA716x_GPIO_H */ -diff --git a/drivers/media/common/saa716x/saa716x_gpio_reg.h b/drivers/media/common/saa716x/saa716x_gpio_reg.h -new file mode 100644 -index 0000000..f36184a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_gpio_reg.h -@@ -0,0 +1,47 @@ -+#ifndef __SAA716x_GPIO_REG_H -+#define __SAA716x_GPIO_REG_H -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+#endif /* __SAA716x_GPIO_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_greg.c b/drivers/media/common/saa716x/saa716x_greg.c -new file mode 100644 -index 0000000..d93a3b8 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg.c -@@ -0,0 +1,42 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_greg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static u32 g_save[12]; -+ -+void saa716x_greg_save(struct saa716x_dev *saa716x) -+{ -+ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); -+ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); -+ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); -+ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); -+ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); -+ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); -+ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); -+ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); -+ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); -+ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); -+ -+ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); -+} -+ -+void saa716x_greg_restore(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); -+ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); -+ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); -+ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); -+ -+ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); -+} -diff --git a/drivers/media/common/saa716x/saa716x_greg.h b/drivers/media/common/saa716x/saa716x_greg.h -new file mode 100644 -index 0000000..487595e ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_GREG_H -+#define __SAA716x_GREG_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_greg_save(struct saa716x_dev *saa716x); -+extern void saa716x_greg_restore(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_GREG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_greg_reg.h b/drivers/media/common/saa716x/saa716x_greg_reg.h -new file mode 100644 -index 0000000..052e8cd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_greg_reg.h -@@ -0,0 +1,91 @@ -+#ifndef __SAA716x_GREG_REG_H -+#define __SAA716x_GREG_REG_H -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_GREG_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_hybrid.c b/drivers/media/common/saa716x/saa716x_hybrid.c -new file mode 100644 -index 0000000..27e5e71 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_hybrid.c -@@ -0,0 +1,726 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_hybrid.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "zl10353.h" -+#include "mb86a16.h" -+#include "tda1004x.h" -+#include "tda827x.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Hybrid" -+ -+static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable decoders on 7162 */ -+ if (pdev->device == SAA7162) { -+ saa716x_gpio_set_output(saa716x, 24); -+ saa716x_gpio_set_output(saa716x, 25); -+ -+ saa716x_gpio_write(saa716x, 24, 0); -+ saa716x_gpio_write(saa716x, 25, 0); -+ -+ msleep(10); -+ -+ saa716x_gpio_write(saa716x, 24, 1); -+ saa716x_gpio_write(saa716x, 25, 1); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); -+ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+/* -+ * Twinhan/Azurewave VP-6090 -+ * DVB-S Frontend: 2x MB86A16 -+ * DVB-T Frontend: 2x TDA10046 + TDA8275 -+ */ -+#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" -+#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" -+ -+static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_vp6090_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_4M, -+ .agc_config = TDA10046_AGC_DEFAULT, -+ .if_freq = TDA10046_FREQ_3617, -+ .request_firmware = tda1004x_vp6090_request_firmware, -+}; -+ -+static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp6090_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp6090_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[count]; -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ saa716x_gpio_set_output(saa716x, 11); -+ saa716x_gpio_set_output(saa716x, 10); -+ saa716x_gpio_write(saa716x, 11, 1); -+ saa716x_gpio_write(saa716x, 10, 1); -+ msleep(100); -+#if 0 -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp6090_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+#endif -+ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_vp6090_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6090, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6090, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6090_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+/* -+ * NXP Reference design (Atlantis) -+ * 2x DVB-T Frontend: 2x TDA10046 -+ * Analog Decoder: 2x Internal -+ */ -+#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" -+#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" -+ -+static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_atlantis_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_atlantis_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_atlantis_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c; -+ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ -+ struct i2c_msg msg = { -+ .addr = 0x42 >> 1, -+ .flags = 0, -+ .buf = i2c_buf, -+ .len = sizeof(i2c_buf) -+ }; -+ -+ if (count < saa716x->config->adapters) { -+ u32 reset_gpio; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ if (count == 0) { -+ reset_gpio = 14; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ } else { -+ reset_gpio = 15; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ } -+ -+ /* activate the silent I2C bus */ -+ i2c_transfer(&i2c->i2c_adapter, &msg, 1); -+ -+ saa716x_gpio_set_output(saa716x, reset_gpio); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, -+ &i2c->i2c_adapter); -+ if (adapter->fe == NULL) -+ goto exit; -+ -+ dprintk(SAA716x_ERROR, 1, -+ "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_atlantis_config.demod_address); -+ -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_atlantis_config.tuner_address, -+ &i2c->i2c_adapter, &tda827x_atlantis_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_atlantis_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_atlantis_config = { -+ .model_name = SAA716x_MODEL_NXP_ATLANTIS, -+ .dev_type = SAA716x_DEV_NXP_ATLANTIS, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_atlantis_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ }, -+ { -+ /* Adapter 1 */ -+ .ts_port = 0, /* using FGPI 0 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+/* -+ * NXP Reference design (NEMO) -+ * DVB-T Frontend: 1x TDA10046 + TDA8275 -+ * Analog Decoder: External SAA7136 -+ */ -+#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" -+#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" -+ -+static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_nemo_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_nemo_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_nemo_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ -+ -+ if (count == 0) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ /* GPIO 26 controls a +15dB gain */ -+ saa716x_gpio_set_output(saa716x, 26); -+ saa716x_gpio_write(saa716x, 26, 0); -+ -+ saa716x_gpio_set_output(saa716x, 14); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_nemo_config, -+ &demod_i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_nemo_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_nemo_config.tuner_address, -+ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_nemo_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_nemo_config = { -+ .model_name = SAA716x_MODEL_NXP_NEMO, -+ .dev_type = SAA716x_DEV_NXP_NEMO, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_nemo_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" -+#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" -+ -+#if 0 -+static struct zl10353_config saa716x_averhc82_zl10353_config = { -+ .demod_address = 0x1f, -+ .adc_clock = 450560, -+ .if2 = 361667, -+ .no_tuner = 1, -+ .parallel_ts = 1, -+}; -+#endif -+ -+static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); -+ -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_averhc82_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, -+ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averhc82_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" -+#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" -+ -+static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_averh788_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_H788, -+ .dev_type = SAA716x_DEV_AVERMEDIA_H788, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averh88_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+static struct pci_device_id saa716x_hybrid_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), -+ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); -+ -+static struct pci_driver saa716x_hybrid_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_hybrid_pci_table, -+ .probe = saa716x_hybrid_pci_probe, -+ .remove = saa716x_hybrid_pci_remove, -+}; -+ -+static int saa716x_hybrid_init(void) -+{ -+ return pci_register_driver(&saa716x_hybrid_pci_driver); -+} -+ -+static void saa716x_hybrid_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_hybrid_pci_driver); -+} -+ -+module_init(saa716x_hybrid_init); -+module_exit(saa716x_hybrid_exit); -+ -+MODULE_DESCRIPTION("SAA716x Hybrid driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_hybrid.h b/drivers/media/common/saa716x/saa716x_hybrid.h -new file mode 100644 -index 0000000..df34a59 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_hybrid.h -@@ -0,0 +1,13 @@ -+#ifndef __SAA716x_HYBRID_H -+#define __SAA716x_HYBRID_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define AVERMEDIA 0x1461 -+#define KWORLD 0x17DE -+ -+#define TWINHAN_VP_6090 0x0027 -+#define AVERMEDIA_HC82 0x2355 -+#define AVERMEDIA_H788 0x1455 -+#define KWORLD_DVB_T_PE310 0x7521 -+ -+#endif /* __SAA716x_HYBRID_H */ -diff --git a/drivers/media/common/saa716x/saa716x_i2c.c b/drivers/media/common/saa716x/saa716x_i2c.c -new file mode 100644 -index 0000000..91a091d ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c.c -@@ -0,0 +1,734 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_i2c_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_cgu_reg.h" -+ -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ -+ I2C_ACK_INTER_MTNA | \ -+ I2C_FAILURE_INTER_MAF) -+ -+#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ -+ I2C_TRANSMIT_PROG) -+ -+#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ -+ I2C_RECEIVE_CLEAR) -+ -+static const char* state[] = { -+ "Idle", -+ "DoneStop", -+ "Busy", -+ "TOscl", -+ "TOarb", -+ "DoneWrite", -+ "DoneRead", -+ "DoneWriteTO", -+ "DoneReadTO", -+ "NoDevice", -+ "NoACK", -+ "BUSErr", -+ "ArbLost", -+ "SEQErr", -+ "STErr" -+}; -+ -+int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) -+{ -+ u32 stat, mask; -+ u32 *I2C_DEV; -+ -+ BUG_ON(saa716x == NULL); -+ I2C_DEV = saa716x->I2C_DEV; -+ -+ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); -+ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); -+ saa716x->i2c[bus].i2c_stat = stat; -+ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", -+ bus, state[stat], stat, mask); -+ -+ if (!(stat & mask)) -+ return -1; -+ -+ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); -+ -+ if (stat & I2C_INTERRUPT_STFNF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTFNF) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_INTERRUPT_RFDA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPTE_RFF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_INTERRUPT_STDR) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MASTER_INTERRUPT_MTDR) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_ERROR_IBE) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MODE_CHANGE_INTER_MSMC) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_ACK_INTER_MTNA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_FAILURE_INTER_MAF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+ -+static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), -+ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); -+ -+ return; -+} -+ -+static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ struct i2c_adapter *adapter = &i2c->i2c_adapter; -+ -+ int i, err = 0; -+ u32 reg; -+ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", -+ I2C_DEV, adapter->name); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Flush queue */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ /* Reset I2C Core and generate a delay */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); -+ -+ for (i = 0; i < 100; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); -+ if (reg == 0xc0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", -+ I2C_DEV, adapter->name); -+ break; -+ } -+ msleep(1); -+ -+ if (i == 99) -+ err = -EIO; -+ } -+ -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", -+ I2C_DEV, adapter->name); -+ -+ saa716x_term_xfer(i2c, I2C_DEV); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* I2C Rate Setup */ -+ switch (i2c->i2c_rate) { -+ case SAA716x_I2C_RATE_400: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); -+ break; -+ -+ case SAA716x_I2C_RATE_100: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); -+ break; -+ -+ default: -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", -+ adapter->name, -+ i2c->i2c_rate); -+ -+ break; -+ } -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Enabled interrupts: -+ * Master Transaction Done, -+ * Master Transaction Data Request -+ * (0x81) -+ */ -+ msleep(5); -+ -+ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, -+ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); -+ -+ /* Check interrupt enable status */ -+ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); -+ if (reg != 0x81) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%d) %s Interrupt enable failed, Exiting !", -+ i, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+ } -+ -+ /* Check status */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%02x) %s has bad state, Exiting !", -+ I2C_DEV, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+#if 0 -+ saa716x_add_irqvector(saa716x, -+ i2c_vec[i].vector, -+ i2c_vec[i].edge, -+ i2c_vec[i].handler, -+ SAA716x_I2C_ADAPTER(i)); -+#endif -+ reg = SAA716x_EPRD(CGU, CGU_SCR_3); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", -+ I2C_DEV, -+ (reg >> 1) & 0x01, -+ reg & 0x01); -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ return 0; -+ } -+ -+ /* Check FIFO status before TX */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ i2c->stat_tx_prior = reg; -+ if (reg & SAA716x_I2C_TXBUSY) { -+ for (i = 0; i < 100; i++) { -+ /* TODO! check for hotplug devices */ -+ msleep(10); -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ -+ if (reg & SAA716x_I2C_TXBUSY) { -+ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); -+ -+ err = saa716x_i2c_hwinit(i2c, I2C_DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto exit; -+ } -+ } else { -+ break; -+ } -+ } -+ } -+ -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ -+ /* Check for data write */ -+ for (i = 0; i < 1000; i++) { -+ /* TODO! check for hotplug devices */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (reg & I2C_TRANSMIT_CLEAR) { -+ break; -+ } -+ } -+ i2c->stat_tx_done = reg; -+ -+ if (!(reg & I2C_TRANSMIT_CLEAR)) { -+ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); -+ err = -EIO; -+ goto exit; -+ } -+ -+ return err; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); -+ return err; -+} -+ -+static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ /* Check FIFO status before RX */ -+ for (i = 0; i < 1000; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & SAA716x_I2C_RXBUSY)) { -+ break; -+ } -+ } -+ if (reg & SAA716x_I2C_RXBUSY) { -+ dprintk(SAA716x_INFO, 1, "FIFO empty"); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Read from FIFO */ -+ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); -+ return err; -+} -+ -+static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return; -+ -+ i2c->i2c_op = 1; -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ unsigned long timeout; -+ int err = 0; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return 0; -+ -+ timeout = HZ/100 + 1; /* 10ms */ -+ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); -+ if (timeout == -ERESTARTSYS || i2c->i2c_op) { -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ err = -ERESTARTSYS; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); -+ err = -EIO; -+ } -+ } -+ return err; -+} -+ -+static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1); -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now write the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = buf[i]; -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1) | 1; -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now read the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = 0x00; /* dummy write for reading */ -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ for (i = 0; i < bytes; i++) { -+ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data receive failed"); -+ goto exit; -+ } -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); -+ buf[i] = data; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) -+{ -+ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); -+ int i, j, err = 0; -+ int t; -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); -+ mutex_lock(&i2c->i2c_lock); -+ -+ for (t = 0; t < 3; t++) { -+ for (i = 0; i < num; i++) { -+ if (msgs[i].flags & I2C_M_RD) -+ err = saa716x_i2c_read_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ else -+ err = saa716x_i2c_write_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ if (err < 0) { -+ err = -EIO; -+ goto retry; -+ } -+ } -+ break; -+retry: -+ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); -+ for (i = 0; i < num; i++) { -+ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", -+ i, msgs[i].addr, msgs[i].len, msgs[i].flags); -+ if (!(msgs[i].flags & I2C_M_RD)) { -+ for (j = 0; j < msgs[i].len; j++) { -+ dprintk(SAA716x_INFO, 1, " 0x%02x", -+ j, msgs[i].buf[j]); -+ } -+ } -+ } -+ err = saa716x_i2c_hwinit(i2c, DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto bail_out; -+ } -+ } -+ -+ mutex_unlock(&i2c->i2c_lock); -+ return num; -+ -+bail_out: -+ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); -+ mutex_unlock(&i2c->i2c_lock); -+ return err; -+} -+ -+static u32 saa716x_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm saa716x_algo = { -+ .master_xfer = saa716x_i2c_xfer, -+ .functionality = saa716x_i2c_func, -+}; -+ -+struct saa716x_i2cvec { -+ u32 vector; -+ enum saa716x_edge edge; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+static const struct saa716x_i2cvec i2c_vec[] = { -+ { -+ .vector = I2CINT_0, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ }, { -+ .vector = I2CINT_1, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ } -+}; -+ -+int saa716x_i2c_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ -+ int i, err = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ mutex_init(&i2c->i2c_lock); -+ -+ init_waitqueue_head(&i2c->i2c_wq); -+ i2c->i2c_op = 0; -+ -+ i2c->i2c_dev = i; -+ i2c->i2c_rate = saa716x->config->i2c_rate; -+ i2c->i2c_mode = saa716x->config->i2c_mode; -+ adapter = &i2c->i2c_adapter; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) -+ i2c->block_size = 8; -+ else -+ i2c->block_size = 1; -+ -+ if (adapter != NULL) { -+ -+ i2c_set_adapdata(adapter, i2c); -+ -+ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); -+ -+ adapter->owner = THIS_MODULE; -+ adapter->algo = &saa716x_algo; -+ adapter->algo_data = NULL; -+ adapter->timeout = 500; /* FIXME ! */ -+ adapter->retries = 3; /* FIXME ! */ -+ adapter->dev.parent = &pdev->dev; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", -+ i, -+ adapter->name); -+ -+ err = i2c_add_adapter(adapter); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); -+ goto exit; -+ } -+ -+ i2c->saa716x = saa716x; -+ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); -+ } -+ i2c++; -+ } -+ -+ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", -+ saa716x->pdev->device); -+ -+ return 0; -+exit: -+ return err; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_init); -+ -+int saa716x_i2c_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ int i, err = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ adapter = &i2c->i2c_adapter; -+#if 0 -+ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); -+#endif -+ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); -+ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); -+ -+ i2c_del_adapter(adapter); -+ i2c++; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); -+ -+ return 0; -+ -+exit: -+ return err; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_exit); -diff --git a/drivers/media/common/saa716x/saa716x_i2c.h b/drivers/media/common/saa716x/saa716x_i2c.h -new file mode 100644 -index 0000000..da767ac ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c.h -@@ -0,0 +1,52 @@ -+#ifndef __SAA716x_I2C_H -+#define __SAA716x_I2C_H -+ -+#define SAA716x_I2C_ADAPTERS 2 -+ -+#define SAA716x_I2C_ADAPTER(__dev) (( \ -+ (__dev == 1) ? \ -+ "SAA716x I2C Core 1" : \ -+ "SAA716x I2C Core 0")) -+ -+#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) -+ -+#define SAA716x_I2C_BUS_A 0x01 -+#define SAA716x_I2C_BUS_B 0x00 -+ -+struct saa716x_dev; -+ -+enum saa716x_i2c_rate { -+ SAA716x_I2C_RATE_400 = 1, -+ SAA716x_I2C_RATE_100, -+}; -+ -+enum saa716x_i2c_mode { -+ SAA716x_I2C_MODE_POLLING = 0, -+ SAA716x_I2C_MODE_IRQ, -+ SAA716x_I2C_MODE_IRQ_BUFFERED -+}; -+ -+struct saa716x_i2c { -+ struct i2c_adapter i2c_adapter; -+ struct mutex i2c_lock; -+ struct saa716x_dev *saa716x; -+ u8 i2c_dev; -+ -+ enum saa716x_i2c_rate i2c_rate; /* run time */ -+ enum saa716x_i2c_mode i2c_mode; -+ u32 block_size; /* block size for buffered -+ mode, 1 otherwise */ -+ u32 i2c_stat; -+ -+ u32 stat_tx_prior; -+ u32 stat_tx_done; -+ wait_queue_head_t i2c_wq; -+ int i2c_op; -+}; -+ -+extern int saa716x_i2c_init(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); -+extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); -+ -+#endif /* __SAA716x_I2C_H */ -diff --git a/drivers/media/common/saa716x/saa716x_i2c_reg.h b/drivers/media/common/saa716x/saa716x_i2c_reg.h -new file mode 100644 -index 0000000..8fa992c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_i2c_reg.h -@@ -0,0 +1,145 @@ -+#ifndef __SAA716x_I2C_REG_H -+#define __SAA716x_I2C_REG_H -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_I2C_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_mod.h b/drivers/media/common/saa716x/saa716x_mod.h -new file mode 100644 -index 0000000..273efdd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_mod.h -@@ -0,0 +1,50 @@ -+#ifndef __SAA716x_MOD_H -+#define __SAA716x_MOD_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+#define BAM 0x00008000 -+#define MMU 0x00009000 -+#define MSI 0x0000a000 -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+#define SPI 0x0000d000 -+#define GPIO 0x0000e000 -+#define PHI_0 0x0000f000 -+#define GREG 0x00012000 -+#define CGU 0x00013000 -+#define DCS 0x00014000 -+#define PHI_1 0x00020000 -+ -+#endif /* __SAA716x_MOD_H */ -diff --git a/drivers/media/common/saa716x/saa716x_msi.c b/drivers/media/common/saa716x/saa716x_msi.c -new file mode 100644 -index 0000000..b0f05a2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi.c -@@ -0,0 +1,479 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_msi_reg.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+ -+#include "saa716x_priv.h" -+ -+#define SAA716x_MSI_VECTORS 50 -+ -+static const char *vector_name[] = { -+ "TAGACK_VI0_0", -+ "TAGACK_VI0_1", -+ "TAGACK_VI0_2", -+ "TAGACK_VI1_0", -+ "TAGACK_VI1_1", -+ "TAGACK_VI1_2", -+ "TAGACK_FGPI_0", -+ "TAGACK_FGPI_1", -+ "TAGACK_FGPI_2", -+ "TAGACK_FGPI_3", -+ "TAGACK_AI_0", -+ "TAGACK_AI_1", -+ "OVRFLW_VI0_0", -+ "OVRFLW_VI0_1", -+ "OVRFLW_VI0_2", -+ "OVRFLW_VI1_0", -+ "OVRFLW_VI1_1", -+ "OVRFLW_VI1_2", -+ "OVRFLW_FGPI_O", -+ "OVRFLW_FGPI_1", -+ "OVRFLW_FGPI_2", -+ "OVRFLW_FGPI_3", -+ "OVRFLW_AI_0", -+ "OVRFLW_AI_1", -+ "AVINT_VI0", -+ "AVINT_VI1", -+ "AVINT_FGPI_0", -+ "AVINT_FGPI_1", -+ "AVINT_FGPI_2", -+ "AVINT_FGPI_3", -+ "AVINT_AI_0", -+ "AVINT_AI_1", -+ "UNMAPD_TC_INT", -+ "EXTINT_0", -+ "EXTINT_1", -+ "EXTINT_2", -+ "EXTINT_3", -+ "EXTINT_4", -+ "EXTINT_5", -+ "EXTINT_6", -+ "EXTINT_7", -+ "EXTINT_8", -+ "EXTINT_9", -+ "EXTINT_10", -+ "EXTINT_11", -+ "EXTINT_12", -+ "EXTINT_13", -+ "EXTINT_14", -+ "EXTINT_15", -+ "I2CINT_0", -+ "I2CINT_1" -+}; -+ -+static u32 MSI_CONFIG_REG[51] = { -+ MSI_CONFIG0, -+ MSI_CONFIG1, -+ MSI_CONFIG2, -+ MSI_CONFIG3, -+ MSI_CONFIG4, -+ MSI_CONFIG5, -+ MSI_CONFIG6, -+ MSI_CONFIG7, -+ MSI_CONFIG8, -+ MSI_CONFIG9, -+ MSI_CONFIG10, -+ MSI_CONFIG11, -+ MSI_CONFIG12, -+ MSI_CONFIG13, -+ MSI_CONFIG14, -+ MSI_CONFIG15, -+ MSI_CONFIG16, -+ MSI_CONFIG17, -+ MSI_CONFIG18, -+ MSI_CONFIG19, -+ MSI_CONFIG20, -+ MSI_CONFIG21, -+ MSI_CONFIG22, -+ MSI_CONFIG23, -+ MSI_CONFIG24, -+ MSI_CONFIG25, -+ MSI_CONFIG26, -+ MSI_CONFIG27, -+ MSI_CONFIG28, -+ MSI_CONFIG29, -+ MSI_CONFIG30, -+ MSI_CONFIG31, -+ MSI_CONFIG32, -+ MSI_CONFIG33, -+ MSI_CONFIG34, -+ MSI_CONFIG35, -+ MSI_CONFIG36, -+ MSI_CONFIG37, -+ MSI_CONFIG38, -+ MSI_CONFIG39, -+ MSI_CONFIG40, -+ MSI_CONFIG41, -+ MSI_CONFIG42, -+ MSI_CONFIG43, -+ MSI_CONFIG44, -+ MSI_CONFIG45, -+ MSI_CONFIG46, -+ MSI_CONFIG47, -+ MSI_CONFIG48, -+ MSI_CONFIG49, -+ MSI_CONFIG50 -+}; -+ -+int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) -+{ -+ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); -+ -+ if (stat_l & MSI_INT_AVINT_VI0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); -+ -+ if (stat_l & MSI_INT_AVINT_VI1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); -+ -+ if (stat_h & MSI_INT_UNMAPD_TC_INT) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); -+ -+ if (stat_h & MSI_INT_EXTINT_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); -+ -+ if (stat_h & MSI_INT_EXTINT_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); -+ -+ if (stat_h & MSI_INT_EXTINT_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); -+ -+ if (stat_h & MSI_INT_EXTINT_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); -+ -+ if (stat_h & MSI_INT_EXTINT_4) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); -+ -+ if (stat_h & MSI_INT_EXTINT_5) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); -+ -+ if (stat_h & MSI_INT_EXTINT_6) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); -+ -+ if (stat_h & MSI_INT_EXTINT_7) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); -+ -+ if (stat_h & MSI_INT_EXTINT_8) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); -+ -+ if (stat_h & MSI_INT_EXTINT_9) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); -+ -+ if (stat_h & MSI_INT_EXTINT_10) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); -+ -+ if (stat_h & MSI_INT_EXTINT_11) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); -+ -+ if (stat_h & MSI_INT_EXTINT_12) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); -+ -+ if (stat_h & MSI_INT_EXTINT_13) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); -+ -+ if (stat_h & MSI_INT_EXTINT_14) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); -+ -+ if (stat_h & MSI_INT_EXTINT_15) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); -+ -+ if (stat_h & MSI_INT_I2CINT_0) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); -+ saa716x_i2c_irqevent(saa716x, 0); -+ } -+ -+ if (stat_h & MSI_INT_I2CINT_1) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); -+ saa716x_i2c_irqevent(saa716x, 1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_event); -+ -+int saa716x_msi_init(struct saa716x_dev *saa716x) -+{ -+ u32 ena_l, ena_h, sta_l, sta_h, mid; -+ int i; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); -+ saa716x->handlers = 0; -+ -+ /* get module id & version */ -+ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); -+ if (mid != 0x30100) -+ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); -+ -+ /* let HW take care of MSI race */ -+ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); -+ -+ /* INTA Polarity: Active High */ -+ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); -+ -+ /* -+ * IRQ Edge Rising: 25:24 = 0x01 -+ * Traffic Class: 18:16 = 0x00 -+ * MSI ID: 4:0 = 0x00 -+ */ -+ for (i = 0; i < SAA716x_MSI_VECTORS; i++) -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); -+ -+ /* get Status */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ /* disable and clear enabled and asserted IRQ's */ -+ if (sta_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); -+ -+ if (sta_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); -+ -+ if (ena_l) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); -+ -+ if (ena_h) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); -+ -+ msleep(5); -+ -+ /* Check IRQ's really disabled */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", -+ ena_l, ena_h, sta_l, sta_h); -+ -+ return 0; -+ } else { -+ dprintk(SAA716x_DEBUG, 1, "I/O error"); -+ return -EIO; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_init); -+ -+void saa716x_msiint_disable(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); -+} -+EXPORT_SYMBOL_GPL(saa716x_msiint_disable); -+ -+ -+/* Map the given vector Id to the hardware bitmask. */ -+static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) -+{ -+ u32 tmp = 1; -+ -+ if (vector < 32) { -+ /* Bits 0 - 31 */ -+ tmp <<= vector; -+ *mask_l = tmp; -+ *mask_h = 0; -+ } else { -+ /* Bits 32 - 48 */ -+ tmp <<= vector - 32; -+ *mask_l = 0; -+ *mask_h = tmp; -+ } -+} -+ -+int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc) -+{ -+ struct saa716x_msix_entry *msix_handler = NULL; -+ -+ u32 config, mask_l, mask_h, ena_l, ena_h; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(vector > SAA716x_MSI_VECTORS); -+ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); -+ -+ if ((vector > 32) && (vector < 49)) { -+ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); -+ config &= 0xfcffffff; /* clear polarity */ -+ -+ switch (edge) { -+ default: -+ case SAA716x_EDGE_RISING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); -+ break; -+ -+ case SAA716x_EDGE_FALLING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); -+ break; -+ -+ case SAA716x_EDGE_ANY: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); -+ break; -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* add callback */ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ strcpy(msix_handler->desc, desc); -+ msix_handler->vector = vector; -+ msix_handler->handler = handler; -+ saa716x->handlers++; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); -+ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); -+ -+ return 0; -+} -+ -+int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) -+{ -+ struct saa716x_msix_entry *msix_handler; -+ int i; -+ u32 mask_l, mask_h; -+ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ BUG_ON(msix_handler == NULL); -+ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); -+ -+ /* loop through the registered handlers */ -+ for (i = 0; i < saa716x->handlers; i++) { -+ -+ /* we found our vector */ -+ if (msix_handler->vector == vector) { -+ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ -+ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", -+ msix_handler->vector, -+ msix_handler->desc); -+ -+ /* check whether it is already released */ -+ if (msix_handler->handler) { -+ msix_handler->vector = 0; -+ msix_handler->handler = NULL; -+ saa716x->handlers--; -+ } -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* disable vector */ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); -+ -+ return 0; -+} -diff --git a/drivers/media/common/saa716x/saa716x_msi.h b/drivers/media/common/saa716x/saa716x_msi.h -new file mode 100644 -index 0000000..8eb72d7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi.h -@@ -0,0 +1,87 @@ -+#ifndef __SAA716x_MSI_H -+#define __SAA716x_MSI_H -+ -+#define TAGACK_VI0_0 0x000 -+#define TAGACK_VI0_1 0x001 -+#define TAGACK_VI0_2 0x002 -+#define TAGACK_VI1_0 0x003 -+#define TAGACK_VI1_1 0x004 -+#define TAGACK_VI1_2 0x005 -+#define TAGACK_FGPI_0 0x006 -+#define TAGACK_FGPI_1 0x007 -+#define TAGACK_FGPI_2 0x008 -+#define TAGACK_FGPI_3 0x009 -+#define TAGACK_AI_0 0x00a -+#define TAGACK_AI_1 0x00b -+#define OVRFLW_VI0_0 0x00c -+#define OVRFLW_VI0_1 0x00d -+#define OVRFLW_VI0_2 0x00e -+#define OVRFLW_VI1_0 0x00f -+#define OVRFLW_VI1_1 0x010 -+#define OVRFLW_VI1_2 0x011 -+#define OVRFLW_FGPI_O 0x012 -+#define OVRFLW_FGPI_1 0x013 -+#define OVRFLW_FGPI_2 0x014 -+#define OVRFLW_FGPI_3 0x015 -+#define OVRFLW_AI_0 0x016 -+#define OVRFLW_AI_1 0x017 -+#define AVINT_VI0 0x018 -+#define AVINT_VI1 0x019 -+#define AVINT_FGPI_0 0x01a -+#define AVINT_FGPI_1 0x01b -+#define AVINT_FGPI_2 0x01c -+#define AVINT_FGPI_3 0x01d -+#define AVINT_AI_0 0x01e -+#define AVINT_AI_1 0x01f -+#define UNMAPD_TC_INT 0x020 -+#define EXTINT_0 0x021 -+#define EXTINT_1 0x022 -+#define EXTINT_2 0x023 -+#define EXTINT_3 0x024 -+#define EXTINT_4 0x025 -+#define EXTINT_5 0x026 -+#define EXTINT_6 0x027 -+#define EXTINT_7 0x028 -+#define EXTINT_8 0x029 -+#define EXTINT_9 0x02a -+#define EXTINT_10 0x02b -+#define EXTINT_11 0x02c -+#define EXTINT_12 0x02d -+#define EXTINT_13 0x02e -+#define EXTINT_14 0x02f -+#define EXTINT_15 0x030 -+#define I2CINT_0 0x031 -+#define I2CINT_1 0x032 -+ -+#define SAA716x_TC0 0x000 -+#define SAA716x_TC1 0x001 -+#define SAA716x_TC2 0x002 -+#define SAA716x_TC3 0x003 -+#define SAA716x_TC4 0x004 -+#define SAA716x_TC5 0x005 -+#define SAA716x_TC6 0x006 -+#define SAA716x_TC7 0x007 -+ -+ -+enum saa716x_edge { -+ SAA716x_EDGE_RISING = 1, -+ SAA716x_EDGE_FALLING = 2, -+ SAA716x_EDGE_ANY = 3 -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); -+ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc); -+ -+extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); -+ -+#endif /* __SAA716x_MSI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_msi_reg.h b/drivers/media/common/saa716x/saa716x_msi_reg.h -new file mode 100644 -index 0000000..d9a12c7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_msi_reg.h -@@ -0,0 +1,143 @@ -+#ifndef __SAA716x_MSI_REG_H -+#define __SAA716x_MSI_REG_H -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+#endif /* __SAA716x_MSI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_pci.c b/drivers/media/common/saa716x/saa716x_pci.c -new file mode 100644 -index 0000000..7fa6bad ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_pci.c -@@ -0,0 +1,275 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_msi.h" -+#include "saa716x_priv.h" -+ -+#define DRIVER_NAME "SAA716x Core" -+ -+static irqreturn_t saa716x_msi_handler(int irq, void *dev_id) -+{ -+ return IRQ_HANDLED; -+} -+ -+static int saa716x_enable_msi(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err; -+ -+ err = pci_enable_msi(pdev); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); -+ return err; -+ } -+ -+ return err; -+} -+ -+static int saa716x_enable_msix(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, ret = 0; -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); -+ if (ret < 0) -+ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); -+ if (ret > 0) -+ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); -+ -+ return ret; -+} -+ -+static int saa716x_request_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_config *config = saa716x->config; -+ int i, ret = 0; -+ -+ if (saa716x->int_type == MODE_MSI) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); -+ ret = saa716x_enable_msi(saa716x); -+ } else if (saa716x->int_type == MODE_MSI_X) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); -+ ret = saa716x_enable_msix(saa716x); -+ } -+ -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); -+ saa716x->int_type = MODE_INTA; -+ } -+ -+ if (saa716x->int_type == MODE_MSI) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ 0, -+ DRIVER_NAME, -+ saa716x); -+ -+ if (ret) { -+ pci_disable_msi(pdev); -+ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); -+ ret = -EIO; -+ } -+ } -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { -+ ret = request_irq(saa716x->msix_entries[i].vector, -+ saa716x->saa716x_msix_handler[i].handler, -+ IRQF_SHARED, -+ saa716x->saa716x_msix_handler[i].desc, -+ saa716x); -+ -+ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); -+ return -1; -+ } -+ } -+ } -+ -+ if (saa716x->int_type == MODE_INTA) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ IRQF_SHARED, -+ DRIVER_NAME, -+ saa716x); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); -+ ret = -ENODEV; -+ } -+ } -+ -+ return ret; -+} -+ -+static void saa716x_free_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, vector; -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { -+ vector = saa716x->msix_entries[i].vector; -+ free_irq(vector, saa716x); -+ } -+ -+ pci_disable_msix(pdev); -+ -+ } else { -+ free_irq(pdev->irq, saa716x); -+ if (saa716x->int_type == MODE_MSI) -+ pci_disable_msi(pdev); -+ } -+} -+ -+int saa716x_pci_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; -+ u32 msi_cap; -+ u8 revision; -+ -+ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); -+ -+ err = pci_enable_device(pdev); -+ if (err != 0) { -+ ret = -ENODEV; -+ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); -+ goto fail0; -+ } -+ -+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { -+ use_dac = 1; -+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); -+ goto fail1; -+ } -+ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); -+ goto fail1; -+ } -+ -+ pci_set_master(pdev); -+ -+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); -+ if (pm_cap == 0) { -+ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); -+ err = -EIO; -+ goto fail1; -+ } -+ -+ if (!request_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0), -+ DRIVER_NAME)) { -+ -+ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); -+ ret = -ENODEV; -+ goto fail1; -+ } -+ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+ if (!saa716x->mmio) { -+ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); -+ ret = -ENODEV; -+ goto fail2; -+ } -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ err = saa716x_request_irq(saa716x); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); -+ ret = -ENODEV; -+ goto fail3; -+ } -+ -+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -+ pci_read_config_dword(pdev, 0x40, &msi_cap); -+ -+ saa716x->revision = revision; -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", -+ saa716x->pdev->device, -+ revision, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 0, -+ "irq: %d,\n mmio: 0x%p\n", -+ saa716x->pdev->irq, -+ saa716x->mmio); -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", -+ saa716x->pdev->device, -+ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), -+ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), -+ (1 << ((msi_cap >> 17) & 0x07))); -+ -+ dprintk(SAA716x_ERROR, 0, "\n"); -+ -+ pci_set_drvdata(pdev, saa716x); -+ -+ return 0; -+ -+fail3: -+ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); -+ if (saa716x->mmio) -+ iounmap(saa716x->mmio); -+fail2: -+ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+fail1: -+ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); -+ pci_disable_device(pdev); -+ -+fail0: -+ pci_set_drvdata(pdev, NULL); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_init); -+ -+void saa716x_pci_exit(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ saa716x_free_irq(saa716x); -+ -+ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", -+ saa716x->pdev->device, -+ saa716x->mmio); -+ -+ if (saa716x->mmio) { -+ iounmap(saa716x->mmio); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ } -+ -+ pci_disable_device(pdev); -+ pci_set_drvdata(pdev, NULL); -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_exit); -+ -+MODULE_DESCRIPTION("SAA716x bridge driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/common/saa716x/saa716x_phi.c b/drivers/media/common/saa716x/saa716x_phi.c -new file mode 100644 -index 0000000..7df9a98 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi.c -@@ -0,0 +1,152 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_spi.h" -+#include "saa716x_phi.h" -+#include "saa716x_priv.h" -+ -+u32 PHI_0_REGS[] = { -+ PHI_0_MODE, -+ PHI_0_0_CONFIG, -+ PHI_0_1_CONFIG, -+ PHI_0_2_CONFIG, -+ PHI_0_3_CONFIG -+}; -+ -+u32 PHI_1_REGS[] = { -+ PHI_1_MODE, -+ PHI_1_0_CONFIG, -+ PHI_1_1_CONFIG, -+ PHI_1_2_CONFIG, -+ PHI_1_3_CONFIG, -+ PHI_1_4_CONFIG, -+ PHI_1_5_CONFIG, -+ PHI_1_6_CONFIG, -+ PHI_1_7_CONFIG -+}; -+ -+#define PHI_BASE(__port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_BASE : \ -+ PHI_0_BASE \ -+)) -+ -+#define PHI_APERTURE(_port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_APERTURE: \ -+ PHI_0_APERTURE \ -+)) -+ -+#define PHI_REG(__port, __reg) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_REGS[__reg] : \ -+ PHI_0_REGS[__reg] \ -+)) -+ -+#define PHI_SLAVE(__port, __slave) (( \ -+ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ -+)) -+ -+/* // Read SAA716x registers -+ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) -+ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) -+ * -+ * // Read slave registers -+ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) -+ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) -+ */ -+ -+int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) -+{ -+ int i; -+ -+ /* Reset */ -+ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); -+ -+ for (i = 0; i < 20; i++) { -+ msleep(1); -+ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_phi_init(struct saa716x_dev *saa716x) -+{ -+ uint32_t value; -+ -+ /* init PHI 0 to FIFO mode */ -+ value = 0; -+ value |= PHI_FIFO_MODE; -+ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); -+ -+ value = 0; -+ value |= 0x02; /* chip select 1 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x06 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); -+ -+ /* init PHI 1 to SRAM mode, auto increment on */ -+ value = 0; -+ value |= PHI_AUTO_INCREMENT; -+ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); -+ -+ value = 0; -+ value |= 0x01; /* chip select 0 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x05 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); -+ -+ value = 0; -+ value |= PHI_ALE_POL; /* ALE is active high */ -+ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); -+ -+ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_init); -+ -+int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write); -+ -+int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_read); -+ -+int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); -diff --git a/drivers/media/common/saa716x/saa716x_phi.h b/drivers/media/common/saa716x/saa716x_phi.h -new file mode 100644 -index 0000000..ff5cda2 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi.h -@@ -0,0 +1,39 @@ -+#ifndef __SAA716x_PHI_H -+#define __SAA716x_PHI_H -+ -+/* PHI SLAVE */ -+#define PHI_SLAVE_0 0 -+#define PHI_SLAVE_1 1 -+#define PHI_SLAVE_2 2 -+#define PHI_SLAVE_3 3 -+#define PHI_SLAVE_4 4 -+#define PHI_SLAVE_5 5 -+#define PHI_SLAVE_6 6 -+#define PHI_SLAVE_7 7 -+ -+/* PHI_REG */ -+#define PHI_MODE 0 -+#define PHI_CONFIG_0 1 -+#define PHI_CONFIG_1 2 -+#define PHI_CONFIG_2 3 -+#define PHI_CONFIG_3 4 -+#define PHI_CONFIG_4 5 -+#define PHI_CONFIG_5 6 -+#define PHI_CONFIG_6 7 -+#define PHI_CONFIG_7 8 -+ -+#define PHI_0_BASE 0x1000 -+#define PHI_0_APERTURE 0x0800 -+ -+#define PHI_1_BASE 0x0000 -+#define PHI_1_APERTURE 0xfffc -+ -+struct saa716x_dev; -+ -+extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); -+extern int saa716x_phi_init(struct saa716x_dev *saa716x); -+extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); -+extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); -+extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); -+ -+#endif /* __SAA716x_PHI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_phi_reg.h b/drivers/media/common/saa716x/saa716x_phi_reg.h -new file mode 100644 -index 0000000..08f0aa7 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_phi_reg.h -@@ -0,0 +1,100 @@ -+#ifndef __SAA716x_PHI_REG_H -+#define __SAA716x_PHI_REG_H -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+ -+/* BAR = 20 bits */ -+/* -------------- PHI1 Registers -------------- */ -+ -+ -+#endif /* __SAA716x_PHI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_priv.h b/drivers/media/common/saa716x/saa716x_priv.h -new file mode 100644 -index 0000000..1ad1d9c ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_priv.h -@@ -0,0 +1,194 @@ -+#ifndef __SAA716x_PRIV_H -+#define __SAA716x_PRIV_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "saa716x_i2c.h" -+#include "saa716x_boot.h" -+#include "saa716x_cgu.h" -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+ -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dmxdev.h" -+#include "dvb_frontend.h" -+#include "dvb_net.h" -+ -+#define SAA716x_ERROR 0 -+#define SAA716x_NOTICE 1 -+#define SAA716x_INFO 2 -+#define SAA716x_DEBUG 3 -+ -+#define SAA716x_DEV (saa716x)->num -+#define SAA716x_VERBOSE (saa716x)->verbose -+#define SAA716x_MAX_ADAPTERS 4 -+ -+#define dprintk(__x, __y, __fmt, __arg...) do { \ -+ if (__y) { \ -+ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ } else { \ -+ if (SAA716x_VERBOSE > __x) \ -+ printk(__fmt , ##__arg); \ -+ } \ -+} while(0) -+ -+ -+#define NXP_SEMICONDUCTOR 0x1131 -+#define SAA7160 0x7160 -+#define SAA7161 0x7161 -+#define SAA7162 0x7162 -+ -+#define NXP_REFERENCE_BOARD 0x1131 -+ -+#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ -+ .vendor = NXP_SEMICONDUCTOR, \ -+ .device = (__chip), \ -+ .subvendor = (__subven), \ -+ .subdevice = (__subdev), \ -+ .driver_data = (unsigned long) (__configptr) \ -+} -+ -+#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+ -+#define SAA716x_MSI_MAX_VECTORS 16 -+ -+struct saa716x_msix_entry { -+ int vector; -+ u8 desc[32]; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+struct saa716x_dev; -+struct saa716x_adapter; -+struct saa716x_spi_config; -+ -+struct saa716x_adap_config { -+ u32 ts_port; -+ void (*worker)(unsigned long); -+}; -+ -+struct saa716x_config { -+ char *model_name; -+ char *dev_type; -+ -+ enum saa716x_boot_mode boot_mode; -+ -+ int adapters; -+ int frontends; -+ -+ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); -+ irqreturn_t (*irq_handler)(int irq, void *dev_id); -+ -+ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; -+ enum saa716x_i2c_rate i2c_rate; -+ enum saa716x_i2c_mode i2c_mode; -+}; -+ -+struct saa716x_adapter { -+ struct dvb_adapter dvb_adapter; -+ struct dvb_frontend *fe; -+ struct dvb_demux demux; -+ struct dmxdev dmxdev; -+ struct dmx_frontend fe_hw; -+ struct dmx_frontend fe_mem; -+ struct dvb_net dvb_net; -+ -+ struct saa716x_dev *saa716x; -+ -+ u8 feeds; -+ u8 count; -+}; -+ -+struct saa716x_dev { -+ struct saa716x_config *config; -+ struct pci_dev *pdev; -+ -+ int num; /* device count */ -+ int verbose; -+ -+ u8 revision; -+ -+ /* PCI */ -+ void __iomem *mmio; -+ -+#define MODE_INTA 0 -+#define MODE_MSI 1 -+#define MODE_MSI_X 2 -+ u8 int_type; -+ -+ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; -+ struct saa716x_msix_entry saa716x_msix_handler[56]; -+ u8 handlers; /* no. of active handlers */ -+ -+ /* I2C */ -+ struct saa716x_i2c i2c[2]; -+ u32 i2c_rate; /* init time */ -+ u32 I2C_DEV[2]; -+ -+ struct saa716x_spi_state *saa716x_spi; -+ struct saa716x_spi_config spi_config; -+ -+ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; -+ struct mutex adap_lock; -+ struct saa716x_cgu cgu; -+ -+ spinlock_t gpio_lock; -+ /* DMA */ -+ -+ struct saa716x_fgpi_stream_port fgpi[4]; -+ -+ u32 id_offst; -+ u32 id_len; -+ void *priv; -+ -+ /* remote control */ -+ void *ir_priv; -+}; -+ -+/* PCI */ -+extern int saa716x_pci_init(struct saa716x_dev *saa716x); -+extern void saa716x_pci_exit(struct saa716x_dev *saa716x); -+ -+/* MSI */ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msi_exit(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+/* DMA */ -+extern int saa716x_dma_init(struct saa716x_dev *saa716x); -+extern void saa716x_dma_exit(struct saa716x_dev *saa716x); -+ -+/* AUDIO */ -+extern int saa716x_audio_init(struct saa716x_dev *saa716x); -+extern void saa716x_audio_exit(struct saa716x_dev *saa716x); -+ -+/* Boot */ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+ -+/* Remote control */ -+extern int saa716x_ir_init(struct saa716x_dev *saa716x); -+extern void saa716x_ir_exit(struct saa716x_dev *saa716x); -+extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); -+ -+#endif /* __SAA716x_PRIV_H */ -diff --git a/drivers/media/common/saa716x/saa716x_reg.h b/drivers/media/common/saa716x/saa716x_reg.h -new file mode 100644 -index 0000000..effd966 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_reg.h -@@ -0,0 +1,1279 @@ -+#ifndef __SAA716x_REG_H -+#define __SAA716x_REG_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+ -+ -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM 0x00008000 -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU 0x00009000 -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI 0x0000a000 -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI 0x0000d000 -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO 0x0000e000 -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0 0x0000f000 -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU 0x00013000 -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCS 0x00014000 -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG 0x00012000 -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+/* BAR = 20 bits */ -+ -+/* -------------- PHI1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+ -+ -+#endif /* __SAA716x_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_rom.c b/drivers/media/common/saa716x/saa716x_rom.c -new file mode 100644 -index 0000000..7f8dbe1 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_rom.c -@@ -0,0 +1,1071 @@ -+#include -+#include -+ -+#include "saa716x_rom.h" -+#include "saa716x_adap.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+int i; -+ -+static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ -+ u8 b0[] = { MSB(reg), LSB(reg) }; -+ int ret; -+ -+ struct i2c_msg msg[] = { -+ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, -+ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } -+ }; -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ struct i2c_msg msg[2]; -+ -+ u8 b0[2]; -+ int ret, count; -+ -+ count = len / DUMP_BYTES; -+ if (len % DUMP_BYTES) -+ count++; -+ -+ count *= 2; -+ -+ for (i = 0; i < count; i += 2) { -+ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", -+ len, -+ count, -+ reg); -+ -+ b0[0] = MSB(reg); -+ b0[1] = LSB(reg); -+ -+ /* Write */ -+ msg[0].addr = 0x50; -+ msg[0].flags = 0; -+ msg[0].buf = b0; -+ msg[0].len = 2; -+ -+ /* Read */ -+ msg[1].addr = 0x50; -+ msg[1].flags = I2C_M_RD; -+ msg[1].buf = val; -+ -+ if (i == (count - 2)) { -+ /* last message */ -+ if (len % DUMP_BYTES) { -+ msg[1].len = len % DUMP_BYTES; -+ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ reg += DUMP_BYTES; -+ val += DUMP_BYTES; -+ } -+ -+ return 0; -+} -+ -+static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) -+{ -+ int i; -+ -+ *offset = 0; -+ for (i = 0; i < 256; i++) { -+ if (!(strncmp("START", buf + i, 5))) -+ break; -+ } -+ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); -+ *offset = i; -+ -+ return 0; -+} -+ -+static int saa716x_eeprom_header(struct saa716x_dev *saa716x, -+ struct saa716x_romhdr *rom_header, -+ u8 *buf, -+ u32 *offset) -+{ -+ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); -+ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ (int)sizeof (struct saa716x_romhdr), -+ rom_header->header_size); -+ -+ return -1; -+ } -+ *offset += sizeof (struct saa716x_romhdr); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", -+ saa716x->pdev->device, -+ rom_header->data_size); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", -+ saa716x->pdev->device, -+ rom_header->version); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", -+ saa716x->pdev->device, -+ rom_header->devices); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", -+ saa716x->pdev->device, -+ rom_header->compression); -+ -+ return 0; -+} -+ -+int saa716x_dump_eeprom(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ u8 buf[DUMP_BYTES]; -+ int i, err = 0; -+ u32 offset = 0; -+ -+ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); -+ return err; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", -+ saa716x->config->model_name); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", -+ saa716x->pdev->device, -+ DUMP_OFFST); -+ -+ for (i = 0; i < DUMP_BYTES; i++) { -+ if ((i % 16) == 0) { -+ dprintk(SAA716x_NOTICE, 0, "\n "); -+ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); -+ } -+ -+ if ((i % 8) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); -+ } -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", -+ saa716x->pdev->device); -+ -+ err = saa716x_get_offset(saa716x, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); -+ return err; -+ } -+ offset += 5; -+ saa716x->id_offst = offset; -+ /* Get header */ -+ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); -+ return -1; -+ } -+ saa716x->id_len = rom_header.data_size; -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); -+ -+static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+static int saa716x_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext Data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_gpio_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_gpio_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_gpio_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_gpio_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pins=%d\n", -+ saa716x->pdev->device, -+ header.pins); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ -+ return 0; -+} -+ -+static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_video_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_video_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 0=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port0); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 1=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port1); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 2=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port2); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT ID=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_id); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_audio_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_audio_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_event_source_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_evsrc_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_evsrc_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_crossbar_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_xbar_hdr header; -+ struct saa716x_xbar_pair_info pair_info; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_xbar_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_xbar_hdr)); -+ -+ return -1; -+ } -+ -+ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pairs=%d\n", -+ saa716x->pdev->device, -+ header.pair_inputs); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); -+ return 0; -+} -+ -+static int saa716x_tuner_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_tuner_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_tuner_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_tuner_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_pll_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_pll_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_pll_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_pll_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_channel_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_channel_decoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_encoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_encoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_encoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_encoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_ir_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_ir_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_ir_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_ir_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_eeprom_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_eeprom_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_eeprom_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_filter_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_filter_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_filter_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_filter_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_streamdev_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_streamdev_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_streamdev_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 size; -+ u8 ext_size = 0; -+ -+ size = buf[*offset]; -+ if (size > 1) -+ ext_size = buf[*offset + size -1]; -+ -+ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ ext_size); -+ -+ *offset += size + ext_size; -+ return 0; -+} -+ -+ -+static void saa716x_device_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size, -+ u8 addr_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size + addr_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+ -+static int saa716x_device_info(struct saa716x_dev *saa716x, -+ struct saa716x_devinfo *device, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 address = 0; -+ -+ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); -+ if (device->struct_size != sizeof(struct saa716x_devinfo)) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", -+ device->struct_size, -+ (int)sizeof(struct saa716x_devinfo)); -+ -+ return -1; -+ } -+ -+ saa716x_device_dbg(saa716x, -+ buf, -+ offset, -+ device->struct_size, -+ device->extd_data_size, -+ device->addr_size); -+ -+ *offset += device->struct_size; -+ -+ if (device->addr_size) { -+ address = buf[*offset]; -+ address >>= 1; -+ *offset += device->addr_size; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", -+ saa716x->pdev->device, -+ address); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ device->struct_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_devid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_busid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_type); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->implem_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->path_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->gpio_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", -+ saa716x->pdev->device, -+ device->addr_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", -+ saa716x->pdev->device, -+ device->extd_data_size); -+ -+ if (device->extd_data_size) { -+ u32 mask; -+ -+ mask = 0x00000001; -+ while (mask) { -+ if (device->device_type & mask) { -+ switch (mask) { -+ case DECODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case GPIO_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found GPIO device\n", -+ saa716x->pdev->device); -+ -+ saa716x_gpio_info(saa716x, buf, offset); -+ break; -+ -+ case VIDEO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Video Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_video_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case AUDIO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Audio Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_audio_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case EVENT_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Event source\n", -+ saa716x->pdev->device); -+ -+ saa716x_event_source_info(saa716x, buf, offset); -+ break; -+ -+ case CROSSBAR: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Crossbar device\n", -+ saa716x->pdev->device); -+ -+ saa716x_crossbar_info(saa716x, buf, offset); -+ break; -+ -+ case TUNER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Tuner device\n", -+ saa716x->pdev->device); -+ -+ saa716x_tuner_info(saa716x, buf, offset); -+ break; -+ -+ case PLL_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found PLL device\n", -+ saa716x->pdev->device); -+ -+ saa716x_pll_info(saa716x, buf, offset); -+ break; -+ -+ case CHANNEL_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Channel Demodulator device\n", -+ saa716x->pdev->device); -+ -+ saa716x_channel_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case RDS_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found RDS Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case ENCODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Encoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_encoder_info(saa716x, buf, offset); -+ break; -+ -+ case IR_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found IR device\n", -+ saa716x->pdev->device); -+ -+ saa716x_ir_info(saa716x, buf, offset); -+ break; -+ -+ case EEPROM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found EEPROM device\n", -+ saa716x->pdev->device); -+ -+ saa716x_eeprom_info(saa716x, buf, offset); -+ break; -+ -+ case NOISE_FILTER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Noise filter device\n", -+ saa716x->pdev->device); -+ -+ saa716x_filter_info(saa716x, buf, offset); -+ break; -+ -+ case LNx_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found LNx device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case STREAM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found streaming device\n", -+ saa716x->pdev->device); -+ -+ saa716x_streamdev_info(saa716x, buf, offset); -+ break; -+ -+ case CONFIGSPACE_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Configspace device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ default: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found unknown device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ } -+ } -+ mask <<= 1; -+ } -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ -+ return 0; -+} -+ -+int saa716x_eeprom_data(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ struct saa716x_devinfo *device; -+ -+ u8 buf[1024]; -+ int i, ret = 0; -+ u32 offset = 0; -+ -+ /* dump */ -+ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); -+ goto err0; -+ } -+ -+ /* Get header */ -+ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); -+ goto err0; -+ } -+ -+ /* allocate for device info */ -+ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); -+ if (device == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); -+ goto err0; -+ } -+ -+ for (i = 0; i < rom_header.devices; i++) { -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", -+ saa716x->pdev->device, -+ i); -+ -+ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); -+ goto err1; -+ } -+ } -+ -+ kfree(device); -+ -+ return 0; -+ -+err1: -+ kfree(device); -+ -+err0: -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_eeprom_data); -diff --git a/drivers/media/common/saa716x/saa716x_rom.h b/drivers/media/common/saa716x/saa716x_rom.h -new file mode 100644 -index 0000000..6bb317f ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_rom.h -@@ -0,0 +1,253 @@ -+#ifndef __SAA716x_ROM_H -+#define __SAA716x_ROM_H -+ -+ -+#define MSB(__x) ((__x >> 8) & 0xff) -+#define LSB(__x) (__x & 0xff) -+ -+#define DUMP_BYTES 0xf0 -+#define DUMP_OFFST 0x000 -+ -+struct saa716x_dev; -+ -+struct saa716x_romhdr { -+ u16 header_size; -+ u8 compression; -+ u8 version; -+ u16 data_size; -+ u8 devices; -+ u8 checksum; -+} __attribute__((packed)); -+ -+struct saa716x_devinfo { -+ u8 struct_size; -+ u8 device_id; -+ u8 master_devid; -+ u8 master_busid; -+ u32 device_type; -+ u16 implem_id; -+ u8 path_id; -+ u8 gpio_id; -+ u16 addr_size; -+ u16 extd_data_size; -+} __attribute__((packed)); -+ -+enum saa716x_device_types { -+ DECODER_DEVICE = 0x00000001, -+ GPIO_SOURCE = 0x00000002, -+ VIDEO_DECODER = 0x00000004, -+ AUDIO_DECODER = 0x00000008, -+ EVENT_SOURCE = 0x00000010, -+ CROSSBAR = 0x00000020, -+ TUNER_DEVICE = 0x00000040, -+ PLL_DEVICE = 0x00000080, -+ CHANNEL_DECODER = 0x00000100, -+ RDS_DECODER = 0x00000200, -+ ENCODER_DEVICE = 0x00000400, -+ IR_DEVICE = 0x00000800, -+ EEPROM_DEVICE = 0x00001000, -+ NOISE_FILTER = 0x00002000, -+ LNx_DEVICE = 0x00004000, -+ STREAM_DEVICE = 0x00010000, -+ CONFIGSPACE_DEVICE = 0x80000000 -+}; -+ -+struct saa716x_decoder_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_decoder_info { -+ struct saa716x_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_gpio_hdr { -+ u8 size; -+ u8 pins; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_gpio_info { -+ struct saa716x_gpio_hdr gpio_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_video_decoder_hdr { -+ u8 size; -+ u8 video_port0; -+ u8 video_port1; -+ u8 video_port2; -+ u8 vbi_port_id; -+ u8 video_port_type; -+ u8 vbi_port_type; -+ u8 encoder_port_type; -+ u8 video_output; -+ u8 vbi_output; -+ u8 encoder_output; -+ u8 ext_data; -+}; -+ -+struct saa716x_video_decoder_info { -+ struct saa716x_video_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_audio_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 output; -+ u8 ext_data; -+}; -+ -+struct saa716x_audio_decoder_info { -+ struct saa716x_audio_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_evsrc_hdr { -+ u8 size; -+ u8 master_devid; -+ u16 condition_id; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_evsrc_info { -+ struct saa716x_evsrc_hdr evsrc_hdr; -+ u8 *ext_data; -+}; -+ -+enum saa716x_input_pair_type { -+ TUNER_SIF = 0x00, -+ TUNER_LINE = 0x01, -+ TUNER_SPDIF = 0x02, -+ TUNER_NONE = 0x03, -+ CVBS_LINE = 0x04, -+ CVBS_SPDIF = 0x05, -+ CVBS_NONE = 0x06, -+ YC_LINE = 0x07, -+ YC_SPDIF = 0x08, -+ YC_NONE = 0x09, -+ YPbPr_LINE = 0x0a, -+ YPbPr_SPDIF = 0x0b, -+ YPbPr_NONE = 0x0c, -+ NO_LINE = 0x0d, -+ NO_SPDIF = 0x0e, -+ RGB_LINE = 0x0f, -+ RGB_SPDIF = 0x10, -+ RGB_NONE = 0x11 -+}; -+ -+struct saa716x_xbar_pair_info { -+ u8 pair_input_type; -+ u8 video_input_id; -+ u8 audio_input_id; -+}; -+ -+struct saa716x_xbar_hdr { -+ u8 size; -+ u8 pair_inputs; -+ u8 pair_route_default; -+ u8 ext_data; -+}; -+ -+struct saa716x_xbar_info { -+ struct saa716x_xbar_hdr xbar_hdr; -+ struct saa716x_xbar_pair_info *pair_info; -+ u8 *ext_data; -+}; -+ -+struct saa716x_tuner_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_tuner_info { -+ struct saa716x_tuner_hdr tuner_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_pll_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_pll_info { -+ struct saa716x_pll_hdr pll_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_channel_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 ext_data; -+}; -+ -+struct saa716x_channel_decoder_info { -+ struct saa716x_channel_decoder_hdr channel_dec_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_encoder_hdr { -+ u8 size; -+ u8 stream_port0; -+ u8 stream_port1; -+ u8 ext_data; -+}; -+ -+struct saa716x_encoder_info { -+ struct saa716x_encoder_hdr encoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_ir_hdr { -+ u8 size; -+ u8 ir_caps; -+ u8 ext_data; -+}; -+ -+struct saa716x_ir_info { -+ struct saa716x_ir_hdr ir_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_eeprom_hdr { -+ u8 size; -+ u8 rel_device; -+ u8 ext_data; -+}; -+ -+struct saa716x_eeprom_info { -+ struct saa716x_eeprom_hdr eeprom_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_filter_hdr { -+ u8 size; -+ u8 video_decoder; -+ u8 audio_decoder; -+ u8 event_source; -+ u8 ext_data; -+}; -+ -+struct saa716x_filter_info { -+ struct saa716x_filter_hdr filter_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_streamdev_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_streamdev_info { -+ struct saa716x_streamdev_hdr streamdev_hdr; -+ u8 *ext_data; -+}; -+ -+extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); -+extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ROM_H */ -diff --git a/drivers/media/common/saa716x/saa716x_spi.c b/drivers/media/common/saa716x/saa716x_spi.c -new file mode 100644 -index 0000000..8859454 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi.c -@@ -0,0 +1,313 @@ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_spi_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#if 0 // not needed atm -+int saa716x_spi_irqevent(struct saa716x_dev *saa716x) -+{ -+ u32 stat, mask; -+ -+ BUG_ON(saa716x == NULL); -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; -+ if ((!stat && !mask)) -+ return -1; -+ -+ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+#endif -+ -+void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ int i; -+ u32 value; -+ int rounds; -+ -+ for (i = 0; i < length; i++) { -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ rounds = 0; -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ rounds++; -+ } -+ } -+} -+EXPORT_SYMBOL_GPL(saa716x_spi_write); -+ -+#if 0 // not needed atm -+static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) -+{ -+ u32 stat; -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); -+ -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); -+ -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); -+ -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); -+ -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); -+ -+ *status = stat; -+ -+ return 0; -+} -+ -+#define SPI_CYCLE_TIMEOUT 100 -+ -+static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) -+{ -+ u32 i, status = 0; -+ -+ /* write data and wait for completion */ -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { -+ msleep(10); -+ saa716x_spi_status(saa716x, &status); -+#if 0 -+ if (status & SPI_TRANSFER_FLAG) { -+ data = SAA716x_EPRD(SPI, SPI_DATA); -+ return 0; -+ } -+#endif -+ if (status & (SPI_WRITE_COLLISSION | -+ SPI_READ_OVERRUN | -+ SPI_MODE_FAULT | -+ SPI_SLAVE_ABORT)) -+ -+ return -EIO; -+ } -+ -+ return -EIO; -+} -+ -+#if 0 -+static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ struct saa716x_spi_config *config = saa716x->spi_config; -+ u32 gpio_mask; -+ int ret = 0; -+ -+ // protect against multiple access -+ spin_lock(&saa716x->gpio_lock); -+ -+ // configure the module -+ saa716x_spi_config(saa716x); -+ -+ // check input -+ -+ // change polarity of GPIO if active high -+ if (config->active_hi) { -+ select = 1; -+ release = 0; -+ } -+ -+ // configure GPIO, first set output register to low selected level -+ saa716x_gpio_write(saa716x, gpio, select); -+ -+ // set mode register to register controlled (0) -+ gpio_mask = (1 << gpio); -+ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); -+ -+ // configure bit as output (0) -+ saa716x_gpio_ctl(saa716x, gpio_mask, 0); -+ -+ // wait at least 500ns before sending a byte -+ msleep(1); -+ -+ // send command -+ for (i = 0; i < dwCommandSize; i++) { -+ ucData = 0; -+// dwStatus = TransferData(pucCommand[i], &ucData); -+ ret = saa716x_spi_xfer(saa716x); -+ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); -+ -+ /* If command length > 1, disable CS at the end of each command. -+ * But after the last command byte CS must be left active! -+ */ -+ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { -+ -+ saa716x_gpio_write(saa716x, gpio, release); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, select); -+ } -+ -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ -+ spin_unlock(&saa716x->spi_lock); -+ return ret; -+ } -+ -+ if (config->LSB_first) -+ dwTransferByte++; -+ else -+ dwTransferByte--; -+ } -+ -+// assume that the byte order is the same as the bit order -+ -+// send read address -+ -+// send data -+ -+// wait at least 500ns before releasing slave -+ -+// release GPIO pin -+ -+ // release spinlock -+ spin_unlock(&saa716x->gpio_lock); -+} -+#endif -+ -+#define MODEBITS (SPI_CPOL | SPI_CPHA) -+ -+static int saa716x_spi_setup(struct spi_device *spi) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ struct saa716x_spi_config *config = &saa716x->spi_config; -+ -+ u8 control = 0; -+ -+ if (spi->mode & ~MODEBITS) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", -+ spi->mode & ~MODEBITS); -+ -+ return -EINVAL; -+ } -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); -+ -+ control |= SPI_MODE_SELECT; /* SPI Master */ -+ -+ if (config->LSB_first) -+ control |= SPI_LSB_FIRST_ENABLE; -+ -+ if (config->clk_pol) -+ control |= SPI_CLOCK_POLARITY; -+ -+ if (config->clk_pha) -+ control |= SPI_CLOCK_PHASE; -+ -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); -+ -+ return 0; -+} -+ -+static void saa716x_spi_cleanup(struct spi_device *spi) -+{ -+ -+} -+ -+static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+#if 0 -+ if (saa716x_spi->run == QUEUE_STOPPED) { -+ spin_unlock_irqrestore(&saa716x_spi->lock, flags); -+ return -ESHUTDOWN; -+ } -+ -+ msg->actual_length = 0; -+ msg->status = -EINPROGRESS; -+ msg->state = START_STATE; -+ -+ list_add_tail(&msg->queue, &saa716x_spi->queue); -+ -+ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) -+ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); -+#endif -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+int saa716x_spi_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct spi_master *master; -+ struct saa716x_spi_state *saa716x_spi; -+ int ret; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); -+ if (master == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); -+ return -ENOMEM; -+ } -+ -+ saa716x_spi = spi_master_get_devdata(master); -+ saa716x_spi->master = master; -+ saa716x_spi->saa716x = saa716x; -+ saa716x->saa716x_spi = saa716x_spi; -+ -+ master->bus_num = pdev->bus->number; -+ master->num_chipselect = 1; /* TODO! use config */ -+ master->cleanup = saa716x_spi_cleanup; -+ master->setup = saa716x_spi_setup; -+ master->transfer = saa716x_spi_transfer; -+ -+ ret = spi_register_master(master); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); -+ goto err; -+ } -+err: -+ spi_master_put(master); -+ return ret; -+} -+EXPORT_SYMBOL(saa716x_spi_init); -+ -+void saa716x_spi_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; -+ -+ spi_unregister_master(saa716x_spi->master); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); -+} -+EXPORT_SYMBOL(saa716x_spi_exit); -+#endif -+ -diff --git a/drivers/media/common/saa716x/saa716x_spi.h b/drivers/media/common/saa716x/saa716x_spi.h -new file mode 100644 -index 0000000..0060c22 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi.h -@@ -0,0 +1,23 @@ -+#ifndef __SAA716x_SPI_H -+#define __SAA716x_SPI_H -+ -+struct saa716x_dev; -+ -+struct saa716x_spi_config { -+ u8 clk_count; -+ u8 clk_pol:1; -+ u8 clk_pha:1; -+ u8 LSB_first:1; -+}; -+ -+struct saa716x_spi_state { -+ struct spi_master *master; -+ struct saa716x_dev *saa716x; -+}; -+ -+extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); -+ -+extern int saa716x_spi_init(struct saa716x_dev *saa716x); -+extern void saa716x_spi_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_SPI_H */ -diff --git a/drivers/media/common/saa716x/saa716x_spi_reg.h b/drivers/media/common/saa716x/saa716x_spi_reg.h -new file mode 100644 -index 0000000..c51abce ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_spi_reg.h -@@ -0,0 +1,27 @@ -+#ifndef __SAA716x_SPI_REG_H -+#define __SAA716x_SPI_REG_H -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_SPI_REG_H */ -diff --git a/drivers/media/common/saa716x/saa716x_vip.c b/drivers/media/common/saa716x/saa716x_vip.c -new file mode 100644 -index 0000000..4cd4c81 ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip.c -@@ -0,0 +1,23 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_vip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_vipint_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ -+ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+} -+EXPORT_SYMBOL_GPL(saa716x_vipint_disable); -+ -+void saa716x_vip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); -+ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); -+} -+EXPORT_SYMBOL_GPL(saa716x_vip_disable); -diff --git a/drivers/media/common/saa716x/saa716x_vip.h b/drivers/media/common/saa716x/saa716x_vip.h -new file mode 100644 -index 0000000..55c6a1a ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip.h -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_VIP_H -+#define __SAA716x_VIP_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); -+extern void saa716x_vip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_VIP_H */ -diff --git a/drivers/media/common/saa716x/saa716x_vip_reg.h b/drivers/media/common/saa716x/saa716x_vip_reg.h -new file mode 100644 -index 0000000..2d773bd ---- /dev/null -+++ b/drivers/media/common/saa716x/saa716x_vip_reg.h -@@ -0,0 +1,127 @@ -+#ifndef __SAA716x_VIP_REG_H -+#define __SAA716x_VIP_REG_H -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+#endif /* __SAA716x_VIP_REG_H */ -diff --git a/drivers/media/dvb-frontends/ds3103.h b/drivers/media/dvb-frontends/ds3103.h -new file mode 100644 -index 0000000..e52740c ---- /dev/null -+++ b/drivers/media/dvb-frontends/ds3103.h -@@ -0,0 +1,47 @@ -+/* -+ Montage Technology DS3103 - DVBS/S2 Demodulator driver -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef DS3103_H -+#define DS3103_H -+ -+#include -+ -+struct ds3103_config { -+ /* the demodulator's i2c address */ -+ u8 demod_address; -+ u8 ci_mode; -+ /* Set device param to start dma */ -+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); -+ /* Hook for Lock LED */ -+ void (*set_lock_led)(struct dvb_frontend *fe, int offon); -+}; -+ -+#if defined(CONFIG_DVB_DS3103) || \ -+ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c); -+#else -+static inline -+struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_DS3103 */ -+#endif /* DS3103_H */ -diff --git a/drivers/media/dvb-frontends/ts2022.h b/drivers/media/dvb-frontends/ts2022.h -new file mode 100644 -index 0000000..c894edb ---- /dev/null -+++ b/drivers/media/dvb-frontends/ts2022.h -@@ -0,0 +1,51 @@ -+ /* -+ Driver for Montage TS2022 DVBS/S2 Silicon tuner -+ -+ Copyright (C) 2012 Tomazzo Muzumici -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+ */ -+ -+#ifndef __DVB_TS2022_H__ -+#define __DVB_TS2022_H__ -+ -+#include -+#include "dvb_frontend.h" -+ -+/** -+ * Attach a ts2022 tuner to the supplied frontend structure. -+ * -+ * @param fe Frontend to attach to. -+ * @param addr i2c address of the tuner. -+ * @param i2c i2c adapter to use. -+ * @return FE pointer on success, NULL on failure. -+ */ -+#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ -+ && defined(MODULE)) -+extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, -+ struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, -+ int addr, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_TS2022 */ -+ -+#endif /* __DVB_TS2022_H__ */ -diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h -index 880e684..edd728c 100644 ---- a/include/uapi/linux/dvb/osd.h -+++ b/include/uapi/linux/dvb/osd.h -@@ -141,4 +141,20 @@ typedef struct osd_cap_s { - #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) - #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) - -+typedef struct osd_raw_cmd_s { -+ const void __user *cmd_data; -+ int cmd_len; -+ void __user *result_data; -+ int result_len; -+} osd_raw_cmd_t; -+ -+typedef struct osd_raw_data_s { -+ const void __user *data_buffer; -+ int data_length; -+ int data_handle; -+} osd_raw_data_t; -+ -+#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) -+#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) -+ - #endif diff --git a/packages/linux/patches/4.0.5/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch b/packages/linux/patches/4.0.5/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch deleted file mode 100644 index 4fe58e69b3..0000000000 --- a/packages/linux/patches/4.0.5/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 56ca3555ed8e0f5fd741477fd23497f5455c3f53 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Tue, 22 Apr 2014 15:58:50 +0300 -Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and after close() - -adapted to 3.15 - -From a6024295fd3290a8c9c5519a03316081ee82378a Mon Sep 17 00:00:00 2001 -From: Anssi Hannula -Date: Sat, 16 Feb 2013 17:42:46 +0200 -Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and - after close() - -Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) start -transmitting an empty audio stream as soon as PIN_OUT and AC_DIG1_ENABLE -are enabled. - -Since commit 6169b673618bf0b2518ce413b54925782a603f06 ("ALSA: hda - -Always turn on pins for HDMI/DP") this happens at first open() time, and -will continue even after close(). - -Additionally, some codecs (at least Intel PantherPoint HDMI) currently -continue transmitting HDMI audio even after close() in case some actual -audio was output after open() (this happens regardless of PIN_OUT). - -Empty HDMI audio transmission when not intended has the effect that a -possible HDMI audio sink/receiver may prefer the empty HDMI audio stream -over an actual audio stream on its S/PDIF inputs. - -To avoid the issue before first prepare(), set stream format to 0 on -codec initialization. 0 is not a valid format value for HDMI and will -prevent the audio stream from being output. - -Additionally, at close() time, make sure that the stream is cleaned up. -This will ensure that the format is reset to 0 at that time, preventing -audio from being output in that case. - -Thanks to OpenELEC developers and users for their help in investigating -this issue on the affected NVIDIA "ION2" hardware. Testing of the final -version on NVIDIA ION2 was done by OpenELEC user "MrXIII". Testing on -Intel PantherPoint was done by myself. - -Signed-off-by: Anssi Hannula -Cc: stable@vger.kernel.org ---- - sound/pci/hda/patch_hdmi.c | 14 ++++++++++++++ - 1 files changed, 14 insertions(+), 0 deletions(-) - -diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c -index 0cb5b89..e92f24f 100644 ---- a/sound/pci/hda/patch_hdmi.c -+++ b/sound/pci/hda/patch_hdmi.c -@@ -1698,6 +1698,14 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) - if (err < 0) - return err; - -+ /* -+ * Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) -+ * start transmitting an empty audio stream as soon as PIN_OUT and -+ * AC_DIG1_ENABLE are enabled, which happens at open() time. -+ * To avoid that, set format to 0, which is not valid for HDMI. -+ */ -+ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); -+ - if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) - spec->cvt_nids[spec->num_cvts] = cvt_nid; - spec->num_cvts++; -@@ -1823,6 +1831,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, - int pinctl; - - if (hinfo->nid) { -+ /* -+ * Make sure no empty audio is output after this point by -+ * setting stream format to 0, which is not valid for HDMI. -+ */ -+ __snd_hda_codec_cleanup_stream(codec, hinfo->nid, 1); -+ - cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); - if (snd_BUG_ON(cvt_idx < 0)) - return -EINVAL; --- -1.7.2.5 - diff --git a/packages/linux/patches/4.0.5/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/4.0.5/linux-995-CX24120-13Z_frontend.patch deleted file mode 100644 index 41d0f1d9d2..0000000000 --- a/packages/linux/patches/4.0.5/linux-995-CX24120-13Z_frontend.patch +++ /dev/null @@ -1,1577 +0,0 @@ -http://patchwork.linuxtv.org/patch/10575/ -modified for 3.7.10 - -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400 -@@ -91,6 +91,8 @@ - int feedcount; - int pid_filtering; - int fullts_streaming_state; -+ /* the stream will be activated by an externally (by the fe for example) */ -+ int need_external_stream_control; - - /* bus specific callbacks */ - flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, -@@ -177,6 +179,8 @@ - struct dvb_demux_feed *dvbdmxfeed, int onoff); - void flexcop_hw_filter_init(struct flexcop_device *fc); - -+extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff); -+ - void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); - - void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400 -@@ -12,6 +12,7 @@ - #include "cx24113.h" - #include "cx24123.h" - #include "isl6421.h" -+#include "cx24120.h" - #include "mt352.h" - #include "bcm3510.h" - #include "nxt200x.h" -@@ -26,6 +27,15 @@ - #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ - (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) - -+#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120) -+static int flexcop_fe_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, char* name) -+{ -+ struct flexcop_device *fc = fe->dvb->priv; -+ return request_firmware(fw, name, fc->dev); -+} -+#endif -+ - /* lnb control */ - #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) - static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -@@ -445,13 +455,6 @@ - - /* AirStar ATSC 1st generation */ - #if FE_SUPPORTED(BCM3510) --static int flexcop_fe_request_firmware(struct dvb_frontend *fe, -- const struct firmware **fw, char* name) --{ -- struct flexcop_device *fc = fe->dvb->priv; -- return request_firmware(fw, name, fc->dev); --} -- - static struct bcm3510_config air2pc_atsc_first_gen_config = { - .demod_address = 0x0f, - .request_firmware = flexcop_fe_request_firmware, -@@ -619,10 +622,40 @@ - #define cablestar2_attach NULL - #endif - -+/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */ -+#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421) -+static const struct cx24120_config skystar2_rev3_3_cx24120_config = { -+ .i2c_addr = 0x55, -+ .request_firmware = flexcop_fe_request_firmware, -+}; -+ -+static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) -+{ -+// struct dvb_frontend_ops *ops; -+ -+ fc->fe = dvb_attach(cx24120_attach, -+ &skystar2_rev3_3_cx24120_config, i2c); -+ if (fc->fe == NULL) return 0; -+ fc->dev_type = FC_SKYS2_REV33; -+ fc->fc_i2c_adap[2].no_base_addr = 1; -+ if ( (dvb_attach(isl6421_attach, fc->fe, -+ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0, false) == NULL) ) { -+ err("ISL6421 could NOT be attached!"); -+ return 0; -+ } -+ info("ISL6421 successfully attached."); -+// ops = &fc->fe->ops; -+ return 1; -+} -+#else -+#define skystarS2_rev33_attach NULL -+#endif -+ - static struct { - flexcop_device_type_t type; - int (*attach)(struct flexcop_device *, struct i2c_adapter *); - } flexcop_frontends[] = { -+ { FC_SKYS2_REV33, skystarS2_rev33_attach }, - { FC_SKY_REV27, skystar2_rev27_attach }, - { FC_SKY_REV28, skystar2_rev28_attach }, - { FC_SKY_REV26, skystar2_rev26_attach }, -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400 -@@ -11,6 +11,12 @@ - deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); - } - -+void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff) -+{ -+ struct flexcop_device *fc = fe->dvb->priv; -+ flexcop_rcv_data_ctrl(fc, onoff); -+} -+ - void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) - { - flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); -@@ -199,6 +205,7 @@ - - /* if it was the first or last feed request change the stream-status */ - if (fc->feedcount == onoff) { -+ if (!fc->need_external_stream_control) - flexcop_rcv_data_ctrl(fc, onoff); - if (fc->stream_control) /* device specific stream control */ - fc->stream_control(fc, onoff); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400 -@@ -56,6 +56,7 @@ - [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", - [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", - [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", -+ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3", - }; - - static const char *flexcop_bus_names[] = { -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400 -@@ -24,6 +24,7 @@ - FC_SKY_REV26, - FC_SKY_REV27, - FC_SKY_REV28, -+ FC_SKYS2_REV33, - } flexcop_device_type_t; - - typedef enum { -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig ---- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 -@@ -3,6 +3,7 @@ - depends on DVB_CORE && I2C - depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB - default y -+ select DVB_CX24120 if !DVB_FE_CUSTOMISE - select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT - select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400 -@@ -0,0 +1,1053 @@ -+/* -+ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver -+ Version 0.0.4a 03.04.2012 -+ -+ Copyright (C) 2009 Sergey Tyurin -+ Updated 2012 by Jannis Achstetter -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "dvb_frontend.h" -+#include "cx24120.h" -+#include "cx24120_const.h" -+ -+//========================== -+#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \ -+ printk(args); } } while (0) -+#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \ -+ printk(args); } while (0) -+#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \ -+ printk(args); } while (0) -+//========================== -+ -+static int cx24120_debug=0; -+static int reg_debug=0; -+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware"); -+module_param(cx24120_debug, int, 0644); -+MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)"); -+ -+// ############################## -+struct cx24120_state { -+ struct i2c_adapter *i2c; -+ const struct cx24120_config *config; -+ struct dvb_frontend frontend; -+ u8 need_set_mpeg_out; -+ u8 attached; -+ u8 dvb_s2_mode; -+ u8 cold_init; -+}; -+// ##################################### -+// #### Command message to firmware #### -+struct cx24120_cmd { // total size = 36 -+ u8 id; // [00] - message id -+ u8 arg[30]; // [04] - message first byte -+ u8 len; // [34] - message lengh or first registers to read -+ u8 reg; // [35] - number of registers to read -+}; -+ -+//=================================================================== -+static int cx24120_readreg(struct cx24120_state *state, u8 reg) -+{ -+ int ret; -+ u8 buf = 0; -+ struct i2c_msg msg[] = { -+ { .addr = state->config->i2c_addr, -+ .flags = 0, -+ .len = 1, -+ .buf = ® }, -+ -+ { .addr = state->config->i2c_addr, -+ .flags = I2C_M_RD, -+ .len = 1, -+ .buf = &buf } -+ }; -+ ret = i2c_transfer(state->i2c, msg, 2); -+ if (ret != 2) { -+ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret); -+ return ret; -+ } -+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf); -+ return buf; -+} // end cx24120_readreg -+//=================================================================== -+static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) -+{ -+ u8 buf[] = { reg, data }; -+ struct i2c_msg msg = { -+ .addr = state->config->i2c_addr, -+ .flags = 0, -+ .buf = buf, -+ .len = 2 }; -+ int ret; -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ if (ret != 1) { -+ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data); -+ return ret; -+ } -+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data); -+ return 0; -+} // end cx24120_writereg -+//=================================================================== -+static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr) -+{ -+ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */ -+ struct i2c_msg msg = { -+ .addr = state->config->i2c_addr, -+ .flags = 0, -+ .buf = buf, -+ .len = len }; -+ int ret; -+ -+ do { -+ buf[0] = reg; -+ msg.len = len > 4 ? 4 : len; -+ memcpy(&buf[1], values, msg.len); -+ len -= msg.len; // data length revers counter -+ values += msg.len; // incr data pointer -+ if (incr) reg += msg.len; -+ msg.len++; /* don't forget the addr byte */ -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ if (ret != 1) { -+ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); -+ return ret; -+ } -+ if (reg_debug) { -+ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages -+ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug -+ reg, buf[1], buf[2], buf[3], buf[4]); -+ } -+ } -+ } while (len); -+ return 0; -+} // end cx24120_writeregN -+//=================================================================== -+static struct dvb_frontend_ops cx24120_ops; -+//=================================================================== -+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c) -+{ -+ struct cx24120_state *state = NULL; -+ int demod_rev; -+ -+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n"); -+ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n"); -+ state = kzalloc(sizeof(struct cx24120_state), -+ GFP_KERNEL); -+ if (state == NULL) { -+ err("### Unable to allocate memory for cx24120_state structure. :(\n"); -+ goto error; -+ } -+ /* setup the state */ -+ state->config = config; -+ state->i2c = i2c; -+ /* check if the demod is present and has proper type */ -+ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION); -+ switch (demod_rev) { -+ case 0x07: -+ info("Demod CX24120 rev. 0x07 detected.\n"); -+ break; -+ case 0x05: -+ info("Demod CX24120 rev. 0x05 detected.\n"); -+ break; -+ default: -+ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev); -+ goto error; -+ } -+ /* create dvb_frontend */ -+ state->attached = 0x10; // set attached flag -+ state->cold_init=0; -+ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n"); -+ return &state->frontend; -+ -+error: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach -+//=================================================================== -+static int cx24120_test_rom(struct cx24120_state *state) -+{ -+ int err, ret; -+ err = cx24120_readreg(state, 0xFD); -+ if (err & 4 ) -+ { -+ ret = cx24120_readreg(state, 0xDF) & 0xFE; -+ err = cx24120_writereg(state, 0xDF, ret); -+ } -+ return err; -+} // end cx24120_test_rom -+//=================================================================== -+static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) | -+ (cx24120_readreg(state, CX24120_REG_QUALITY_L)); -+ dbginfo("read SNR index = %d\n", *snr); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr -+//=================================================================== -+static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word -+ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word -+ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word -+ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word -+ dbginfo("read BER index = %d\n", *ber); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber -+//=================================================================== -+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd); -+//=================================================================== -+static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag) -+{ -+ u8 tristate; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ??? -+ cmd.arg[0] = 1; -+ cmd.arg[1] = 0; -+ tristate = flag ? 0 : (u8)(-1); -+ cmd.arg[2] = tristate; -+ cmd.arg[3] = 1; -+ cmd.len = 4; -+ -+ if(flag) dbginfo("MPEG output DISABLED\n"); -+ else dbginfo("MPEG output ENABLED\n"); -+ -+ return cx24120_message_send(state, &cmd); -+} // end cx24120_msg_mpeg_output_global_config -+//=================================================================== -+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd) -+{ -+ u8 xxzz; -+ u32 msg_cmd_mask; -+ int ret, ficus; -+ -+ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled? -+ // if yes: -+ xxzz = cmd->id - 0x11; // look for specific message id -+ if ( xxzz <= 0x13 ) { -+ msg_cmd_mask = 1 << xxzz; -+ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output -+ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b -+ cx24120_msg_mpeg_output_global_config(state, 0); -+ msleep(100); -+ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag -+ } -+ } -+ } -+ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target -+ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data -+ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end -+ -+ ficus = 1000; -+ while ( cx24120_readreg(state, 0x1F)) { // is command done??? -+ msleep(1); -+ if( !(--ficus)) { -+ err("Too long waiting 'done' state from reg(0x1F). :(\n"); -+ return -EREMOTEIO; -+ } -+ } -+ dbginfo("Successfully send message 0x%02x\n", cmd->id); -+ -+ if ( cmd->reg > 30 ) { -+ err("Too much registers to read. cmd->reg = %d", cmd->reg); -+ return -EREMOTEIO; -+ } -+ ficus = 0; -+ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read -+ while ( ficus < cmd->reg ){ // starts from reg No cmd->len -+ // number of registers to read is cmd->reg -+ // and write results starts from cmd->arg[0]. -+ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1)); -+ ++ficus; -+ } -+ } -+ return 0; -+} // end cx24120_message_send -+//=================================================================== -+static int cx24120_set_frontend(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ u32 srate, freq; -+ fe_code_rate_t fec; -+ fe_spectral_inversion_t inversion; -+ u8 smbr1, smbr2; -+ int ret; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs -+ cmd.len = 15; -+ -+ freq = p->frequency; -+ srate = p->symbol_rate; -+ fec = p->fec_inner; -+ inversion = p->inversion; -+ -+ // check symbol rate -+ if ( srate > 31000000 ) { // if symbol rate > 31 000 -+ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp -+ smbr2 = (-(srate < 31000001) & 6) + 4; // edi -+ } else { -+ smbr1 = 3; -+ smbr2 = 6; -+ } -+ -+ ret = cx24120_writereg(state, 0xE6, smbr1); -+ ret = cx24120_readreg(state, 0xF0); -+ ret &= 0xFFFFFFF0; -+ ret |= smbr2; -+ ret = cx24120_writereg(state, 0xF0, ret); -+ -+ cmd.arg[0] = 0; // CMD_TUNER_REQUEST -+ -+ // Frequency -+ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */ -+ cmd.arg[2] = (freq & 0x00FF00) >> 8; -+ cmd.arg[3] = (freq & 0x0000FF); -+ -+ // Symbol Rate -+ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8; -+ cmd.arg[5] = ((srate/1000) & 0x00FF); -+ -+ // Inversion -+ if ( inversion ) { -+ if ( inversion == 1 ) cmd.arg[6] = 4; -+ else cmd.arg[6] = 0x0C; -+ } else { -+ cmd.arg[6] = 0; -+ } -+ -+ // FEC -+ switch ( fec ) // fec = p->u.qpsk.fec_inner -+ { -+ case 1: // FEC_1_2 -+ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset -+ case 2: // FEC_2_3 -+ cmd.arg[7] = 0x2F; break; -+ case 3: // FEC_3_4 -+ cmd.arg[7] = 0x30; break; -+ case 5: // FEC_5_6 -+ cmd.arg[7] = 0x31; break; -+ case 7: // FEC_7_8 -+ cmd.arg[7] = 0x32; break; -+ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9, -+ // FEC_AUTO, FEC_3_5, FEC_9_10 -+ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode -+ cmd.arg[7] = 0; -+ cmd.arg[11] = 0; -+ } else { -+ cmd.arg[7] = 0x2E; -+ cmd.arg[11] = 0xAC; -+ } -+ break; -+ } -+ cmd.arg[8] = 0x13; -+ cmd.arg[9] = 0x88; -+ cmd.arg[10] = 0; -+ cmd.arg[12] = smbr2; -+ cmd.arg[13] = smbr1; -+ cmd.arg[14] = 0; -+ -+ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ????? -+ -+ return cx24120_message_send(state, &cmd); -+ -+} -+EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend -+//=================================================================== -+void cx24120_message_fill(struct cx24120_cmd *cmd, -+ u8 msg_id, -+ u8 *msg_addr, -+ u8 msg_len, -+ u8 num_regs) -+{ -+ cmd->id = msg_id; -+ memcpy(&cmd->arg[0], msg_addr, msg_len); -+ cmd->len = msg_len; -+ cmd->reg = num_regs; -+} // end cx24120_message_fill -+//=================================================================== -+static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int result, sigstr_h, sigstr_l; -+ -+ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/); -+ -+ if( !(cx24120_message_send(state, &cmd)) ) { -+ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8; -+ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L ); -+ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l)); -+ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF; -+ dbginfo("Signal strength= 0x%x\n", *signal_strength); -+ result = 0; -+ } else { -+ err("error reading signal strength\n"); -+ result = -EREMOTEIO; -+ } -+ return result; -+} -+EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength -+//=================================================================== -+static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num, -+ struct cx24120_skystar2_mpeg_config *config_msg) -+{ -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id -+ cmd.len = 7; -+ cmd.arg[0] = num; // sequental number - can be 0,1,2 -+ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) | -+ ((config_msg->x1 >> 1) & 0x01); -+ cmd.arg[2] = 0x05; -+ cmd.arg[3] = 0x02; -+ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01); -+ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F); -+ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */ -+ -+ return cx24120_message_send(state, &cmd); -+} // end cx24120_msg_mpeg_output_config -+//=================================================================== -+static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_DISEQC_BURST; -+ cmd.arg[0] = 0x00; -+ if (burst) -+ cmd.arg[1] = 0x01; -+ dbginfo("burst sent.\n"); -+ -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst -+//=================================================================== -+static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ dbginfo("cmd(0x23,4) - tone = %d\n", tone); -+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { -+ err("Invalid tone=%d\n", tone); -+ return -EINVAL; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_SETTONE; // 0x23 -+ cmd.len = 4; -+ if (!tone) -+ cmd.arg[3] = 0x01; -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone -+//=================================================================== -+static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_SETVOLTAGE; // -+ cmd.len = 2; -+ if (!(voltage - 1)) -+ cmd.arg[1] = 0x01; -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage -+//=================================================================== -+static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int back_count; -+ -+ dbginfo("Start sending diseqc sequence===============\n"); -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_DISEQC_MSG1; // 0x20 -+ cmd.len = 11; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x00; -+ cmd.arg[2] = 0x03; -+ cmd.arg[3] = 0x16; -+ cmd.arg[4] = 0x28; -+ cmd.arg[5] = 0x01; -+ cmd.arg[6] = 0x01; -+ cmd.arg[7] = 0x14; -+ cmd.arg[8] = 0x19; -+ cmd.arg[9] = 0x14; -+ cmd.arg[10] = 0x1E; -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("send 1st message(0x%x) filed==========\n", cmd.id); -+ return -EREMOTEIO; -+ } -+ cmd.id = CMD_DISEQC_MSG2; // 0x21 -+ cmd.len = d->msg_len + 6; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x01; -+ cmd.arg[2] = 0x02; -+ cmd.arg[3] = 0x00; -+ cmd.arg[4] = 0x00; -+ cmd.arg[5] = d->msg_len; -+ -+ memcpy(&cmd.arg[6], &d->msg, d->msg_len); -+ -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("send 2d message(0x%x) filed========\n", cmd.id); -+ return -EREMOTEIO; -+ } -+ back_count = 100; -+ do { -+ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) { -+ dbginfo("diseqc sequence sent success==========.\n"); -+ return 0; -+ } -+ msleep(5); -+ --back_count; -+ } while ( back_count ); -+ err("Too long waiting for diseqc.=============\n"); -+ return -ETIMEDOUT; -+} -+EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg -+//=================================================================== -+static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int ret, clock_seq_num, GettedFEC; -+ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id; -+ -+ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A -+ dbginfo("status = 0x%x\n", ret); -+ *status = 0; -+ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL; -+ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER; -+ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC); -+ -+ if ( ret & CX24120_HAS_LOCK ) { // 0x08 -+ *status |= FE_HAS_LOCK; -+ if ( state->need_set_mpeg_out & 1 ) { // just tuned??? -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_CLOCK_READ; -+ cmd.arg[0] = 0x00; -+ cmd.len = 1; // cmd.reg != 0, so it is first register to read -+ cmd.reg = 6; // number of registers to read (0x01-0x06) -+ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result -+ // 0x02-0x07 -+ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14 -+ GettedFEC = ret; // 0x0d= 13 -+ dbginfo("Get FEC: %d\n", ret); -+ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2? -+ switch (ret-4) { -+ case 0: -+ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only -+ case 1: -+ case 8: -+ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only -+ case 2: -+ case 9: -+ mode_code = 0x02; goto mode_8PSK; // FEC_2_3 -+ case 3: -+ case 10: -+ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+ -+ case 4: -+ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only -+ case 5: -+ case 11: -+ mode_code = 0x05; goto mode_8PSK; // FEC_5_6 -+ case 6: -+ case 12: -+ mode_code = 0x08; goto mode_8PSK; // FEC_8_9 -+ case 7: -+ case 13: -+ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only -+ default: -+ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4); -+ mode_code = 0x01; // set like for mode 0 -+ mode_8PSK: -+ if ( ret > 11 ) { // 14 -+ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag -+ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code); -+ } else { -+ mode_QPSK: -+ mode_8PSK_flag = 0x00; -+ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4); -+ } -+ break; -+ } // end switch -+ } // end if dvb_s2_mode // dvb-s2 -+ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S -+ switch ( ret - 2 ) { -+ case 0: -+ mode_code = 2; break; // FEC_2_3 -+ case 1: -+ mode_code = 3; break; // FEC_3_4 -+ case 2: -+ mode_code = 4; break; // FEC_4_5 -+ case 3: -+ mode_code = 5; break; // FEC_5_6 -+ case 4: -+ mode_code = 6; break; // FEC_6_7 -+ case 5: -+ mode_code = 7; break; // FEC_7_8 -+ default: -+ mode_code = 1;break; // FEC_1_2 -+ } -+ mode_8PSK_flag = 0; -+ } // end of switch for dvb-s -+ -+ attached_flag = 0x10; -+ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner -+ attached_flag = 0; -+ ret = 0; -+ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2 -+ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ??? -+ // bit 4 bit 5 bit 0 bit 3 -+ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible, -+ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag -+ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5 -+ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n", -+ clock_id, mode_8PSK_flag, mode_code); -+ -+ clock_seq_num = 0; -+ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) || -+ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) || -+ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) ) -+ { -+ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num, -+ * clock_ratios_table[clock_seq_num].ratio_id, -+ * clock_ratios_table[clock_seq_num].mode_xPSK, -+ * clock_ratios_table[clock_seq_num].fec_mode); -+ */ -+ ++clock_seq_num; -+ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) { -+ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n"); -+ goto settings_end; -+ } -+ } -+ //############################### -+ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n", -+ GettedFEC, -+ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early -+ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16 -+ clock_seq_num, -+ clock_ratios_table[clock_seq_num].m_rat, -+ clock_ratios_table[clock_seq_num].n_rat, -+ clock_ratios_table[clock_seq_num].rate); -+ //############################### -+ cmd.id = CMD_CLOCK_SET; -+ cmd.len = 10; -+ cmd.reg = 0; -+ cmd.arg[0] = 0; -+ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner -+ -+ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF; -+ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF; -+ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF; -+ -+ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF; -+ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF; -+ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF; -+ -+ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF; -+ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF; -+ -+ cx24120_message_send(state, &cmd); -+ -+ settings_end: -+ msleep(200); -+ cx24120_msg_mpeg_output_global_config(state, 1); -+ state->dvb_s2_mode |= 0x02; // set mpeg flag -+ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag -+ } -+ } -+ } -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status -+//=================================================================== -+int cx24120_init(struct dvb_frontend *fe) -+{ -+ const struct firmware *fw; -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ u8 ret, ret_EA, reg1, fL, fH; -+ u32 vco, xtal_khz; -+ u64 inv_vco, res, xxyyzz; -+ int reset_result; -+ -+ if( state->cold_init ) return 0; -+ -+ ret = cx24120_writereg(state, 0xEA, 0x00); -+ ret = cx24120_test_rom(state); -+ ret = cx24120_readreg(state, 0xFB) & 0xFE; -+ ret = cx24120_writereg(state, 0xFB, ret); -+ ret = cx24120_readreg(state, 0xFC) & 0xFE; -+ ret = cx24120_writereg(state, 0xFC, ret); -+ ret = cx24120_writereg(state, 0xC3, 0x04); -+ ret = cx24120_writereg(state, 0xC4, 0x04); -+ ret = cx24120_writereg(state, 0xCE, 0x00); -+ ret = cx24120_writereg(state, 0xCF, 0x00); -+ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE; -+ ret = cx24120_writereg(state, 0xEA, ret_EA); -+ ret = cx24120_writereg(state, 0xEB, 0x0C); -+ ret = cx24120_writereg(state, 0xEC, 0x06); -+ ret = cx24120_writereg(state, 0xED, 0x05); -+ ret = cx24120_writereg(state, 0xEE, 0x03); -+ ret = cx24120_writereg(state, 0xEF, 0x05); -+ ret = cx24120_writereg(state, 0xF3, 0x03); -+ ret = cx24120_writereg(state, 0xF4, 0x44); -+ -+ reg1 = 0xF0; -+ do { -+ cx24120_writereg(state, reg1, 0x04); -+ cx24120_writereg(state, reg1 - 10, 0x02); -+ ++reg1; -+ } while ( reg1 != 0xF3 ); -+ -+ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01)); -+ reg1 = 0xC5; -+ do { -+ ret = cx24120_writereg(state, reg1, 0x00); -+ ret = cx24120_writereg(state, reg1 + 1, 0x00); -+ reg1 += 2; -+ } while ( reg1 != 0xCB ); -+ -+ ret = cx24120_writereg(state, 0xE4, 0x03); -+ ret = cx24120_writereg(state, 0xEB, 0x0A); -+ -+ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE); -+ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE); -+ if (ret) { -+ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret); -+ return ret; -+ } -+ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n", -+ (int)fw->size, // firmware_size in bytes u32* -+ fw->data[0], // fw 1st byte -+ fw->data[1], // fw 2d byte -+ fw->data[fw->size - 2], // fw before last byte -+ fw->data[fw->size - 1]); // fw last byte -+ -+ ret = cx24120_test_rom(state); -+ ret = cx24120_readreg(state, 0xFB) & 0xFE; -+ ret = cx24120_writereg(state, 0xFB, ret); -+ ret = cx24120_writereg(state, 0xE0, 0x76); -+ ret = cx24120_writereg(state, 0xF7, 0x81); -+ ret = cx24120_writereg(state, 0xF8, 0x00); -+ ret = cx24120_writereg(state, 0xF9, 0x00); -+ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00); -+ ret = cx24120_writereg(state, 0xF7, 0xC0); -+ ret = cx24120_writereg(state, 0xE0, 0x00); -+ ret = (fw->size - 2) & 0x00FF; -+ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a -+ ret = ((fw->size - 2) >> 8) & 0x00FF; -+ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf -+ ret = cx24120_writereg(state, 0xF7, 0x00); -+ ret = cx24120_writereg(state, 0xDC, 0x00); -+ ret = cx24120_writereg(state, 0xDC, 0x07); -+ msleep(500); -+ -+ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware -+ if ( ret == fw->data[fw->size - 1] ) { -+ dbginfo("Firmware uploaded successfully\n"); -+ reset_result = 0; -+ } else { -+ err("Firmware upload failed. Last byte returned=0x%x\n", ret ); -+ reset_result = -EREMOTEIO; -+ } -+ ret = cx24120_writereg(state, 0xDC, 0x00); -+ release_firmware(fw); -+ if (reset_result) -+ return reset_result; -+ -+ //================== Start tuner -+ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error tuner start! :(\n"); -+ return -EREMOTEIO; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_VCO_SET; // 0x10 -+ cmd.len = 12; -+ -+ // ###################### -+ // Calc VCO -+ xtal_khz = 10111; -+ xxyyzz = 0x400000000ULL; // 17179869184 -+ vco = xtal_khz * 10 * 4; // 404440 -+ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE -+ res = xxyyzz % vco; // 66864 = 0x010530 -+ -+ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco; -+ -+ fH = (inv_vco >> 8) & 0xFF; -+ fL = (inv_vco) & 0xFF; -+ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH); -+ // ###################### -+ -+ cmd.arg[0] = 0x06; -+ cmd.arg[1] = 0x2B; -+ cmd.arg[2] = 0xD8; -+ cmd.arg[3] = fH; // 0xA5 -+ cmd.arg[4] = fL; // 0xEE -+ cmd.arg[5] = 0x03; -+ cmd.arg[6] = 0x9D; -+ cmd.arg[7] = 0xFC; -+ cmd.arg[8] = 0x06; -+ cmd.arg[9] = 0x03; -+ cmd.arg[10] = 0x27; -+ cmd.arg[11] = 0x7F; -+ -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error set VCO! :(\n"); -+ return -EREMOTEIO; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ // set bandwidth -+ cmd.id = CMD_BANDWIDTH; // 0x15 -+ cmd.len = 12; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x00; -+ cmd.arg[2] = 0x00; -+ cmd.arg[3] = 0x00; -+ cmd.arg[4] = 0x05; -+ cmd.arg[5] = 0x02; -+ cmd.arg[6] = 0x02; -+ cmd.arg[7] = 0x00; -+ cmd.arg[8] = 0x05; -+ cmd.arg[9] = 0x02; -+ cmd.arg[10] = 0x02; -+ cmd.arg[11] = 0x00; -+ -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("Error set bandwidth! :(\n"); -+ return -EREMOTEIO; -+ } -+ ret = cx24120_readreg(state, 0xBA); -+ if ( ret > 3) { -+ dbginfo("Reset-readreg 0xBA: %x\n", ret); -+ err("Error intitilizing tuner! :(\n"); -+ return -EREMOTEIO; -+ } -+ dbginfo("Tuner initialized correctly.\n"); -+ -+ ret = cx24120_writereg(state, 0xEB, 0x0A); -+ if (cx24120_msg_mpeg_output_global_config(state, 0) || -+ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) || -+ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) || -+ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) ) -+ { -+ err("Error initilizing mpeg output. :(\n"); -+ return -EREMOTEIO; -+ } else { -+ cmd.id = 0x3C; // 60 -+ cmd.len = 0x03; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x10; -+ cmd.arg[2] = 0x10; -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error sending final init message. :(\n"); -+ return -EREMOTEIO; -+ } -+ } -+ state->cold_init=1; -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_init); // end cx24120_reset -+//=================================================================== -+static int cx24120_tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct cx24120_state *state = fe->demodulator_priv; -+ int delay_cnt, sd_idx = 0; -+ fe_status_t status; -+ -+ if (re_tune) { -+ -+// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n", -+// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate); -+ -+ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) { -+ ++sd_idx; -+ } -+ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay); -+ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2 -+ dbginfo("trying DVB-S =================\n"); -+ cx24120_set_frontend(fe); -+ -+ delay_cnt = symrates_pairs[sd_idx].delay; -+ dbginfo("Wait for LOCK for DVB-S =================\n"); -+ while (delay_cnt >= 0) { -+ cx24120_read_status(fe, &status); -+ if (status & FE_HAS_LOCK) { -+ dbginfo("DVB-S LOCKED================\n"); -+ break; -+ } -+ msleep(100); -+ delay_cnt -=100; -+ } -+ dbginfo("Waiting finished - NO lock for DVB-S =================\n"); -+ -+ cx24120_read_status(fe, &status); -+ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S -+ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n"); -+ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ? -+ p->fec_inner = FEC_AUTO; -+ cx24120_set_frontend(fe); -+ delay_cnt = symrates_pairs[sd_idx].delay; -+ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n"); -+ while (delay_cnt >= 0) { -+ cx24120_read_status(fe, &status); -+ if (status & FE_HAS_LOCK) { -+ dbginfo("DVB-S2 LOCKED++++++++++++++++\n"); -+ break; -+ } -+ msleep(100); -+ delay_cnt -=100; -+ } -+ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n"); -+ } -+ } -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune -+//=================================================================== -+static int cx24120_get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+EXPORT_SYMBOL(cx24120_get_algo); -+//=================================================================== -+static int cx24120_sleep(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_sleep); -+//=================================================================== -+/*static int cx24120_wakeup(struct dvb_frontend *fe) -+ * { -+ * return 0; -+ * } -+ * EXPORT_SYMBOL(cx24120_wakeup); -+ */ -+//=================================================================== -+static int cx24120_get_frontend(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_get_frontend); -+//=================================================================== -+static void cx24120_release(struct dvb_frontend *fe) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ dbginfo("Clear state structure\n"); -+ kfree(state); -+} -+EXPORT_SYMBOL(cx24120_release); -+//=================================================================== -+static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) | -+ cx24120_readreg(state, CX24120_REG_UCB_L); -+ dbginfo("Blocks = %d\n", *ucblocks); -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_ucblocks); -+// ######################################################################################## -+static struct dvb_frontend_ops cx24120_ops = { -+ -+ .delsys = { SYS_DVBS2 }, -+ .info = { -+ .name = "Conexant CX24120/CX24118", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ -+ .frequency_tolerance = 5000, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 45000000, -+ .caps = // 0x500006ff -+ FE_CAN_INVERSION_AUTO | //0x00 000 001 -+ FE_CAN_FEC_1_2 | //0x00 000 002 -+ FE_CAN_FEC_2_3 | //0x00 000 004 -+ FE_CAN_FEC_3_4 | //0x00 000 008 -+ FE_CAN_FEC_4_5 | //0x00 000 010 -+ FE_CAN_FEC_5_6 | //0x00 000 020 -+ FE_CAN_FEC_6_7 | //0x00 000 040 -+ FE_CAN_FEC_7_8 | //0x00 000 080 -+ FE_CAN_FEC_AUTO | //0x00 000 200 -+ FE_CAN_QPSK | //0x00 000 400 -+//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */ -+ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */ -+ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */ -+ }, //sum=50 000 6FF -+ .release = cx24120_release, -+ -+ .init = cx24120_init, -+ .sleep = cx24120_sleep, -+ -+ .tune = cx24120_tune, -+ .get_frontend_algo = cx24120_get_algo, -+ .set_frontend = cx24120_set_frontend, -+ -+ .get_frontend = cx24120_get_frontend, -+ .read_status = cx24120_read_status, -+ .read_ber = cx24120_read_ber, -+ .read_signal_strength = cx24120_read_signal_strength, -+ .read_snr = cx24120_read_snr, -+ .read_ucblocks = cx24120_read_ucblocks, -+ -+ .diseqc_send_master_cmd = cx24120_send_diseqc_msg, -+ -+ .diseqc_send_burst = cx24120_diseqc_send_burst, -+ .set_tone = cx24120_set_tone, -+ .set_voltage = cx24120_set_voltage, -+}; -+//=================================================================== -+MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)"); -+MODULE_AUTHOR("Sergey Tyurin"); -+MODULE_LICENSE("GPL"); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400 -@@ -0,0 +1,259 @@ -+/* -+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver -+ * DVBS/S2 Satellite demod/tuner driver static definitins -+ * -+ * Copyright (C) 2009 Sergey Tyurin -+ * Updated 2012 by Jannis Achstetter -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw" -+ -+// ############################## -+// ### cx24120 i2c registers ### -+#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register: -+#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc. -+#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result -+ -+#define CX24120_REG_FECMODE (0x39) // FEC status -+#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ... -+#define CX24120_REG_QUALITY_H (0x40) // SNR high byte -+#define CX24120_REG_QUALITY_L (0x41) // SNR low byte -+ -+#define CX24120_REG_BER_HH (0x47) // BER high byte of high word -+#define CX24120_REG_BER_HL (0x48) // BER low byte of high word -+#define CX24120_REG_BER_LH (0x49) // BER high byte of low word -+#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word -+ -+#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ??? -+#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte -+ -+#define CX24120_REG_UCB_H (0x50) // UCB high byte -+#define CX24120_REG_UCB_L (0x51) // UCB low byte -+ -+#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5 -+ -+// ############################## -+/* Command messages */ -+enum command_message_id { -+ CMD_VCO_SET = 0x10, // cmdlen = 12; -+ CMD_TUNEREQUEST = 0x11, // cmd.len = 15; -+ -+ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4; -+ CMD_MPEG_INIT = 0x14, // cmd.len = 7; -+ CMD_BANDWIDTH = 0x15, // cmd.len = 12; -+ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06 -+ CMD_CLOCK_SET = 0x17, // cmd.len = 10; -+ -+ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11; -+ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6; -+ CMD_SETVOLTAGE = 0x22, // cmd.len = 2; -+ CMD_SETTONE = 0x23, // cmd.len = 4; -+ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!! -+ -+ CMD_READ_SNR = 0x1A, // Read signal strength -+ CMD_START_TUNER = 0x1B, // ??? -+ -+ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03; -+}; -+// ############################## -+/* signal status */ -+#define CX24120_HAS_SIGNAL (0x01) -+#define CX24120_HAS_CARRIER (0x02) -+#define CX24120_HAS_VITERBI (0x04) -+#define CX24120_HAS_LOCK (0x08) -+#define CX24120_HAS_UNK1 (0x10) -+#define CX24120_HAS_UNK2 (0x20) -+#define CX24120_STATUS_MASK (0x0f) -+#define CX24120_SIGNAL_MASK (0xc0) -+ -+static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 }; -+static u8 cx24120_msg_read_sigstr[] = {0,0}; -+ -+static struct cx24120_skystar2_mpeg_config { -+ u8 x1; -+ u8 x2; -+ u8 x3; -+} initial_mpeg_config = { -+ 0xA1, // 10100001 -+ 0x76, // 01110110 -+ 0x07, // 00000111 -+}; -+ -+static struct cx24120_symrate_delay { -+ u32 symrate; -+ u32 delay; -+} symrates_pairs[] = { -+ { 3000000, 15000 }, -+ { 6000000, 10000 }, -+ { 8000000, 5000 }, -+ { 10000000, 2000 }, -+ {0x0FFFFFFFF, 400 }, -+}; -+ -+static struct cx24120_clock_ratios_table { -+ u32 ratio_id; -+ u32 mode_xPSK; -+ u32 fec_mode; -+ u32 m_rat; -+ u32 n_rat; -+ u32 rate; -+} clock_ratios_table[] = { -+{ 21 , 0 , 1 , 770068 , 763515 , 258 }, -+{ 21 , 0 , 100 , 97409 , 80370 , 310 }, -+{ 21 , 0 , 2 , 137293 , 101802 , 345 }, -+{ 21 , 0 , 3 , 4633447 , 3054060 , 388 }, -+{ 21 , 0 , 4 , 2472041 , 1527030 , 414 }, -+{ 21 , 0 , 5 , 85904 , 50901 , 432 }, -+{ 21 , 0 , 8 , 2751229 , 1527030 , 461 }, -+{ 21 , 0 , 101 , 1392872 , 763515 , 467 }, -+{ 21 , 99 , 100 , 1850771 , 1019430 , 464 }, -+{ 21 , 99 , 2 , 137293 , 67962 , 517 }, -+{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 21 , 99 , 5 , 85904 , 33981 , 647 }, -+{ 21 , 99 , 8 , 2751229 , 1019430 , 690 }, -+{ 21 , 99 , 101 , 1392872 , 509715 , 699 }, -+{ 29 , 0 , 1 , 770068 , 782127 , 252 }, -+{ 29 , 0 , 100 , 1850771 , 1564254 , 302 }, -+{ 29 , 0 , 2 , 686465 , 521418 , 337 }, -+{ 29 , 0 , 3 , 4633447 , 3128508 , 379 }, -+{ 29 , 0 , 4 , 2472041 , 1564254 , 404 }, -+{ 29 , 0 , 5 , 429520 , 260709 , 421 }, -+{ 29 , 0 , 8 , 2751229 , 1564254 , 450 }, -+{ 29 , 0 , 101 , 1392872 , 782127 , 455 }, -+{ 29 , 99 , 100 , 1850771 , 1043118 , 454 }, -+{ 29 , 99 , 2 , 686465 , 347706 , 505 }, -+{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 29 , 99 , 5 , 429520 , 173853 , 632 }, -+{ 29 , 99 , 8 , 2751229 , 1043118 , 675 }, -+{ 29 , 99 , 101 , 1392872 , 521559 , 683 }, -+{ 17 , 0 , 1 , 766052 , 763515 , 256 }, -+{ 17 , 0 , 100 , 96901 , 80370 , 308 }, -+{ 17 , 0 , 2 , 136577 , 101802 , 343 }, -+{ 17 , 0 , 3 , 4609283 , 3054060 , 386 }, -+{ 17 , 0 , 4 , 2459149 , 1527030 , 412 }, -+{ 17 , 0 , 5 , 85456 , 50901 , 429 }, -+{ 17 , 0 , 8 , 2736881 , 1527030 , 458 }, -+{ 17 , 0 , 101 , 1385608 , 763515 , 464 }, -+{ 17 , 99 , 100 , 1841119 , 1019430 , 462 }, -+{ 17 , 99 , 2 , 136577 , 67962 , 514 }, -+{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 17 , 99 , 5 , 85456 , 33981 , 643 }, -+{ 17 , 99 , 8 , 2736881 , 1019430 , 687 }, -+{ 17 , 99 , 101 , 1385608 , 509715 , 695 }, -+{ 25 , 0 , 1 , 766052 , 782127 , 250 }, -+{ 25 , 0 , 100 , 1841119 , 1564254 , 301 }, -+{ 25 , 0 , 2 , 682885 , 521418 , 335 }, -+{ 25 , 0 , 3 , 4609283 , 3128508 , 377 }, -+{ 25 , 0 , 4 , 2459149 , 1564254 , 402 }, -+{ 25 , 0 , 5 , 427280 , 260709 , 419 }, -+{ 25 , 0 , 8 , 2736881 , 1564254 , 447 }, -+{ 25 , 0 , 101 , 1385608 , 782127 , 453 }, -+{ 25 , 99 , 100 , 1841119 , 1043118 , 451 }, -+{ 25 , 99 , 2 , 682885 , 347706 , 502 }, -+{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 25 , 99 , 5 , 427280 , 173853 , 629 }, -+{ 25 , 99 , 8 , 2736881 , 1043118 , 671 }, -+{ 25 , 99 , 101 , 1385608 , 521559 , 680 }, -+{ 5 , 0 , 1 , 273088 , 254505 , 274 }, -+{ 5 , 0 , 100 , 17272 , 13395 , 330 }, -+{ 5 , 0 , 2 , 24344 , 16967 , 367 }, -+{ 5 , 0 , 3 , 410788 , 254505 , 413 }, -+{ 5 , 0 , 4 , 438328 , 254505 , 440 }, -+{ 5 , 0 , 5 , 30464 , 16967 , 459 }, -+{ 5 , 0 , 8 , 487832 , 254505 , 490 }, -+{ 5 , 0 , 101 , 493952 , 254505 , 496 }, -+{ 5 , 99 , 100 , 328168 , 169905 , 494 }, -+{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD -+{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 5 , 99 , 5 , 30464 , 11327 , 688 }, -+{ 5 , 99 , 8 , 487832 , 169905 , 735 }, -+{ 5 , 99 , 101 , 493952 , 169905 , 744 }, -+{ 13 , 0 , 1 , 273088 , 260709 , 268 }, -+{ 13 , 0 , 100 , 328168 , 260709 , 322 }, -+{ 13 , 0 , 2 , 121720 , 86903 , 358 }, -+{ 13 , 0 , 3 , 410788 , 260709 , 403 }, -+{ 13 , 0 , 4 , 438328 , 260709 , 430 }, -+{ 13 , 0 , 5 , 152320 , 86903 , 448 }, -+{ 13 , 0 , 8 , 487832 , 260709 , 479 }, -+{ 13 , 0 , 101 , 493952 , 260709 , 485 }, -+{ 13 , 99 , 100 , 328168 , 173853 , 483 }, -+{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk -+{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 13 , 99 , 5 , 152320 , 57951 , 672 }, -+{ 13 , 99 , 8 , 487832 , 173853 , 718 }, -+{ 13 , 99 , 101 , 493952 , 173853 , 727 }, -+{ 1 , 0 , 1 , 815248 , 763515 , 273 }, -+{ 1 , 0 , 100 , 51562 , 40185 , 328 }, -+{ 1 , 0 , 2 , 72674 , 50901 , 365 }, -+{ 1 , 0 , 3 , 1226323 , 763515 , 411 }, -+{ 1 , 0 , 4 , 1308538 , 763515 , 438 }, -+{ 1 , 0 , 5 , 90944 , 50901 , 457 }, -+{ 1 , 0 , 8 , 1456322 , 763515 , 488 }, -+{ 1 , 0 , 101 , 1474592 , 763515 , 494 }, -+{ 1 , 99 , 100 , 979678 , 509715 , 492 }, -+{ 1 , 99 , 2 , 72674 , 33981 , 547 }, -+{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2 -+{ 1 , 99 , 5 , 90944 , 33981 , 685 }, -+{ 1 , 99 , 8 , 1456322 , 509715 , 731 }, -+{ 1 , 99 , 101 , 1474592 , 509715 , 740 }, -+{ 9 , 0 , 1 , 815248 , 782127 , 266 }, -+{ 9 , 0 , 100 , 979678 , 782127 , 320 }, -+{ 9 , 0 , 2 , 363370 , 260709 , 356 }, -+{ 9 , 0 , 3 , 1226323 , 782127 , 401 }, -+{ 9 , 0 , 4 , 1308538 , 782127 , 428 }, -+{ 9 , 0 , 5 , 454720 , 260709 , 446 }, -+{ 9 , 0 , 8 , 1456322 , 782127 , 476 }, -+{ 9 , 0 , 101 , 1474592 , 782127 , 482 }, -+{ 9 , 99 , 100 , 979678 , 521559 , 480 }, -+{ 9 , 99 , 2 , 363370 , 173853 , 535 }, -+{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 9 , 99 , 5 , 454720 , 173853 , 669 }, -+{ 9 , 99 , 8 , 1456322 , 521559 , 714 }, -+{ 9 , 99 , 101 , 1474592 , 521559 , 723 }, -+{ 18 , 0 , 1 , 535 , 588 , 233 }, -+{ 18 , 0 , 2 , 1070 , 882 , 311 }, -+{ 18 , 0 , 6 , 3210 , 2058 , 399 }, -+{ 16 , 0 , 1 , 763 , 816 , 239 }, -+{ 16 , 0 , 2 , 1526 , 1224 , 319 }, -+{ 16 , 0 , 3 , 2289 , 1632 , 359 }, -+{ 16 , 0 , 5 , 3815 , 2448 , 399 }, -+{ 16 , 0 , 7 , 5341 , 3264 , 419 }, -+{ 22 , 0 , 1 , 535 , 588 , 233 }, -+{ 22 , 0 , 2 , 1070 , 882 , 311 }, -+{ 22 , 0 , 6 , 3210 , 2058 , 399 }, -+{ 20 , 0 , 1 , 143429 , 152592 , 241 }, -+{ 20 , 0 , 2 , 286858 , 228888 , 321 }, -+{ 20 , 0 , 3 , 430287 , 305184 , 361 }, -+{ 20 , 0 , 5 , 717145 , 457776 , 401 }, -+{ 20 , 0 , 7 , 1004003 , 610368 , 421 }, -+{ 2 , 0 , 1 , 584 , 588 , 254 }, -+{ 2 , 0 , 2 , 1169 , 882 , 339 }, -+{ 2 , 0 , 6 , 3507 , 2058 , 436 }, -+{ 0 , 0 , 1 , 812 , 816 , 255 }, -+{ 0 , 0 , 2 , 1624 , 1224 , 340 }, -+{ 0 , 0 , 3 , 2436 , 1632 , 382 }, -+{ 0 , 0 , 5 , 4060 , 2448 , 425 }, -+{ 0 , 0 , 7 , 5684 , 3264 , 446 }, -+{ 6 , 0 , 1 , 584 , 588 , 254 }, -+{ 6 , 0 , 2 , 1168 , 882 , 339 }, -+{ 6 , 0 , 6 , 3504 , 2058 , 436 }, -+{ 4 , 0 , 1 , 152592 , 152592 , 256 }, -+{ 4 , 0 , 2 , 305184 , 228888 , 341 }, -+{ 4 , 0 , 3 , 457776 , 305184 , 384 }, -+{ 4 , 0 , 5 , 762960 , 457776 , 427 }, -+{ 4 , 0 , 7 , 1068144 , 610368 , 448 }, -+}; -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400 -@@ -0,0 +1,59 @@ -+/* -+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver -+ * -+ * Copyright (C) 2008 Patrick Boettcher -+ * Copyright (C) 2009 Sergey Tyurin -+ * Updated 2012 by Jannis Achstetter -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef CX24120_H -+#define CX24120_H -+ -+#include -+ -+struct firmware; -+struct dvb_frontend; -+struct i2c_adapter; -+ -+struct cx24120_config -+{ -+ u8 i2c_addr; -+ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name); -+ void (*stream_control)(struct dvb_frontend *fe, u8 onoff); -+}; -+ -+#if defined(CONFIG_DVB_CX24120) || \ -+ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, -+ struct i2c_adapter *i2c); -+extern int cx24120_reset(struct dvb_frontend *fe); -+#else -+static inline -+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+static inline int cx24120_reset(struct dvb_frontend *fe) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return -ENODEV; -+} -+#endif -+ -+#endif -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig ---- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400 -@@ -4,6 +4,13 @@ - comment "Multistandard (satellite) frontends" - depends on DVB_CORE - -+config DVB_CX24120 -+ tristate "Conexant CX24120 based" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend. -+ - config DVB_STB0899 - tristate "STB0899 based" - depends on DVB_CORE && I2C -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile ---- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400 -@@ -19,6 +19,10 @@ - obj-$(CONFIG_DVB_CX22700) += cx22700.o - obj-$(CONFIG_DVB_S5H1432) += s5h1432.o - obj-$(CONFIG_DVB_CX24110) += cx24110.o -+ -+# inserted by Custler -+obj-$(CONFIG_DVB_CX24120) += cx24120.o -+ - obj-$(CONFIG_DVB_TDA8083) += tda8083.o - obj-$(CONFIG_DVB_L64781) += l64781.o - obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o diff --git a/packages/linux/patches/4.0.5/linux-999-i915-use-legacy-turbo.patch b/packages/linux/patches/4.0.5/linux-999-i915-use-legacy-turbo.patch deleted file mode 100644 index 1dc049701b..0000000000 --- a/packages/linux/patches/4.0.5/linux-999-i915-use-legacy-turbo.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 89973c56cefd075a0209d63f87ecfbbe7245d100 Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Fri, 6 Mar 2015 17:26:41 +0100 -Subject: [PATCH] i915_irq: enable legacy turbo - ---- - 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 b051a23..5cceebf 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -4340,12 +4340,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) && !IS_CHERRYVIEW(dev_priv)) -- /* WaGsvRC0ResidencyMethod:vlv */ -- dev_priv->pm_rps_events = 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; - - setup_timer(&dev_priv->gpu_error.hangcheck_timer, - i915_hangcheck_elapsed, --- -1.9.1 - diff --git a/packages/linux/patches/4.0.5/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/linux/patches/4.0.5/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch deleted file mode 100644 index 16ac49bee6..0000000000 --- a/packages/linux/patches/4.0.5/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c314d9af9d774c052bea324e1a140ccdba0ca070 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Tue, 8 Apr 2014 14:02:53 +0300 -Subject: [PATCH] pm: disable async suspend/resume by default - ---- - kernel/power/main.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kernel/power/main.c b/kernel/power/main.c -index 1d1bf63..361db93 100644 ---- a/kernel/power/main.c -+++ b/kernel/power/main.c -@@ -46,7 +46,7 @@ int pm_notifier_call_chain(unsigned long val) - } - - /* If set, devices may be suspended and resumed asynchronously. */ --int pm_async_enabled = 1; -+int pm_async_enabled = 0; - - static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) --- -1.7.2.5 - diff --git a/packages/linux/patches/4.0.5/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch b/packages/linux/patches/4.0.5/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch deleted file mode 100644 index b3eb8b34b0..0000000000 --- a/packages/linux/patches/4.0.5/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 57f0b99ca9a2db948fa70988c447553683368be1 Mon Sep 17 00:00:00 2001 -From: Nell Hardcastle -Date: Thu, 29 May 2014 22:06:50 -0700 -Subject: [PATCH] eMMC: Don't initialize partitions on RPMB flagged areas. - -Prevents a lot of pointless hanging at boot on some devices. ---- - drivers/mmc/card/block.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 4409d79..56df902 100644 ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -2254,7 +2254,7 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) - return 0; - - for (idx = 0; idx < card->nr_parts; idx++) { -- if (card->part[idx].size) { -+ if (card->part[idx].size && !(card->part[idx].area_type & MMC_BLK_DATA_AREA_RPMB)) { - ret = mmc_blk_alloc_part(card, md, - card->part[idx].part_cfg, - card->part[idx].size >> 9, --- -1.7.10.4 - diff --git a/packages/linux/patches/4.0.5/linux-999.10-amd-limited-color-range.patch b/packages/linux/patches/4.0.5/linux-999.10-amd-limited-color-range.patch deleted file mode 100644 index ab70b1d2ce..0000000000 --- a/packages/linux/patches/4.0.5/linux-999.10-amd-limited-color-range.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 37dfde26fbb38bdfb1f3b7d72444132f021020f5 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 23 Feb 2015 10:11:49 -0500 -Subject: [PATCH 1/2] drm/radeon: add an output_csc property - -This adds the drm property for output csc (e.g., -transform of output display colorspace). Currently -only common ones (TV RGB, BT.601, BT.709) are supported, -but bypass and tv rgb are really the only useful ones at -the moment. Additionally we could expose a user adjustable -matrix in the future. - -This commit just adds the property. The hw support will -be added in subsequent patches. - -bug: -https://bugs.freedesktop.org/show_bug.cgi?id=83226 - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++++++ - drivers/gpu/drm/radeon/radeon_mode.h | 9 +++++++++ - 2 files changed, 22 insertions(+) - -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index 1021169..b6ed51a 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -1379,6 +1379,13 @@ static struct drm_prop_enum_list radeon_dither_enum_list[] = - { RADEON_FMT_DITHER_ENABLE, "on" }, - }; - -+static struct drm_prop_enum_list radeon_output_csc_enum_list[] = -+{ { RADEON_OUTPUT_CSC_BYPASS, "bypass" }, -+ { RADEON_OUTPUT_CSC_TVRGB, "tvrgb" }, -+ { RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" }, -+ { RADEON_OUTPUT_CSC_YCBCR709, "ycbcr709" }, -+}; -+ - static int radeon_modeset_create_props(struct radeon_device *rdev) - { - int sz; -@@ -1441,6 +1448,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) - "dither", - radeon_dither_enum_list, sz); - -+ sz = ARRAY_SIZE(radeon_output_csc_enum_list); -+ rdev->mode_info.output_csc_property = -+ drm_property_create_enum(rdev->ddev, 0, -+ "output_csc", -+ radeon_output_csc_enum_list, sz); -+ - return 0; - } - -diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h -index f78087a..49f4c9d 100644 ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -85,6 +85,13 @@ enum radeon_hpd_id { - RADEON_HPD_NONE = 0xff, - }; - -+enum radeon_output_csc { -+ RADEON_OUTPUT_CSC_BYPASS = 0, -+ RADEON_OUTPUT_CSC_TVRGB = 1, -+ RADEON_OUTPUT_CSC_YCBCR601 = 2, -+ RADEON_OUTPUT_CSC_YCBCR709 = 3, -+}; -+ - #define RADEON_MAX_I2C_BUS 16 - - /* radeon gpio-based i2c -@@ -255,6 +262,8 @@ struct radeon_mode_info { - struct drm_property *audio_property; - /* FMT dithering */ - struct drm_property *dither_property; -+ /* Output CSC */ -+ struct drm_property *output_csc_property; - /* hardcoded DFP edid from BIOS */ - struct edid *bios_hardcoded_edid; - int bios_hardcoded_edid_size; --- -1.8.3.1 - -From 2ed0abe27e4358d39b5c3fc2800478c5cafa59d8 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 23 Feb 2015 10:59:36 -0500 -Subject: [PATCH 2/2] drm/radeon: implement output csc property for DCE5+ - -Implement the property for DCE5+ asics. Older asics -require a slightly more complex process. - -bug: -https://bugs.freedesktop.org/show_bug.cgi?id=83226 - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/atombios_crtc.c | 6 ++++ - drivers/gpu/drm/radeon/radeon_connectors.c | 52 ++++++++++++++++++++++++++++++ - drivers/gpu/drm/radeon/radeon_display.c | 2 +- - drivers/gpu/drm/radeon/radeon_mode.h | 2 ++ - 4 files changed, 61 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c -index ed644a4..7d827cb 100644 ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -2066,6 +2066,12 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, - radeon_crtc->connector = NULL; - return false; - } -+ if (radeon_crtc->encoder) { -+ struct radeon_encoder *radeon_encoder = -+ to_radeon_encoder(radeon_crtc->encoder); -+ -+ radeon_crtc->output_csc = radeon_encoder->output_csc; -+ } - if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) - return false; - if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) -diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c -index 27def67..0a371a1 100644 ---- a/drivers/gpu/drm/radeon/radeon_connectors.c -+++ b/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -725,6 +725,30 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct - radeon_property_change_mode(&radeon_encoder->base); - } - -+ if (property == rdev->mode_info.output_csc_property) { -+ if (connector->encoder) -+ radeon_encoder = to_radeon_encoder(connector->encoder); -+ else { -+ struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; -+ radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); -+ } -+ -+ if (radeon_encoder->output_csc == val) -+ return 0; -+ -+ radeon_encoder->output_csc = val; -+ -+ if (connector->encoder->crtc) { -+ struct drm_crtc *crtc = connector->encoder->crtc; -+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -+ -+ radeon_crtc->output_csc = radeon_encoder->output_csc; -+ -+ (*crtc_funcs->load_lut)(crtc); -+ } -+ } -+ - return 0; - } - -@@ -1872,6 +1896,10 @@ radeon_add_atom_connector(struct drm_device *dev, - drm_object_attach_property(&radeon_connector->base.base, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_NONE); -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - break; - case DRM_MODE_CONNECTOR_DVII: - case DRM_MODE_CONNECTOR_DVID: -@@ -1904,6 +1932,10 @@ radeon_add_atom_connector(struct drm_device *dev, - drm_object_attach_property(&radeon_connector->base.base, - rdev->mode_info.audio_property, - RADEON_AUDIO_AUTO); -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - - subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = true; -@@ -1950,6 +1982,10 @@ radeon_add_atom_connector(struct drm_device *dev, - drm_object_attach_property(&radeon_connector->base.base, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_NONE); -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; -@@ -1972,6 +2008,10 @@ radeon_add_atom_connector(struct drm_device *dev, - drm_object_attach_property(&radeon_connector->base.base, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_NONE); -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - connector->interlace_allowed = true; -@@ -2023,6 +2063,10 @@ radeon_add_atom_connector(struct drm_device *dev, - rdev->mode_info.load_detect_property, - 1); - } -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - connector->interlace_allowed = true; - if (connector_type == DRM_MODE_CONNECTOR_DVII) - connector->doublescan_allowed = true; -@@ -2068,6 +2112,10 @@ radeon_add_atom_connector(struct drm_device *dev, - rdev->mode_info.audio_property, - RADEON_AUDIO_AUTO); - } -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = true; - if (connector_type == DRM_MODE_CONNECTOR_HDMIB) -@@ -2116,6 +2164,10 @@ radeon_add_atom_connector(struct drm_device *dev, - rdev->mode_info.audio_property, - RADEON_AUDIO_AUTO); - } -+ if (ASIC_IS_DCE5(rdev)) -+ drm_object_attach_property(&radeon_connector->base.base, -+ rdev->mode_info.output_csc_property, -+ RADEON_OUTPUT_CSC_BYPASS); - connector->interlace_allowed = true; - /* in theory with a DP to VGA converter... */ - connector->doublescan_allowed = false; -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index b6ed51a..4d26443 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -154,7 +154,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) - (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) | - NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS))); - WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset, -- (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) | -+ (NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) | - NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS))); - /* XXX match this to the depth of the crtc fmt block, move to modeset? */ - WREG32(0x6940 + radeon_crtc->crtc_offset, 0); -diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h -index 49f4c9d..60043bf 100644 ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -366,6 +366,7 @@ struct radeon_crtc { - u32 wm_low; - u32 wm_high; - struct drm_display_mode hw_mode; -+ enum radeon_output_csc output_csc; - }; - - struct radeon_encoder_primary_dac { -@@ -459,6 +460,7 @@ struct radeon_encoder { - bool is_ext_encoder; - u16 caps; - struct radeon_audio_funcs *audio; -+ enum radeon_output_csc output_csc; - }; - - struct radeon_connector_atom_dig { --- -1.8.3.1 - From fa52ef5143dd4fbf29c8d451d42ca2ab033d2ee2 Mon Sep 17 00:00:00 2001 From: Jonas Nyrup Date: Sun, 21 Jun 2015 00:30:57 +0200 Subject: [PATCH 14/29] add required space to conditional --- config/noobs/partition_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/noobs/partition_setup.sh b/config/noobs/partition_setup.sh index 7f6ace2da7..85048a2aef 100755 --- a/config/noobs/partition_setup.sh +++ b/config/noobs/partition_setup.sh @@ -40,7 +40,7 @@ md5sumCheck() { ) } -if [ -z $part1 -o -z $part2 -o -z $id1 -o -z $id2]; then +if [ -z $part1 -o -z $part2 -o -z $id1 -o -z $id2 ]; then echo "error: part1, part2, id1 or id2 not specified" echo "actual values:" echo "part1:" $part1 From bfd3b42f96ffc9f474cbd4846f4f7f2038365eb3 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 22 Jun 2015 11:01:42 +0300 Subject: [PATCH 15/29] linux: update to linux-4.1 --- packages/linux/package.mk | 4 ++-- .../patches/{4.1-rc8 => 4.1}/linux-003-no_dev_console.patch | 0 .../{4.1-rc8 => 4.1}/linux-051-ouya_controller_support.patch | 0 .../{4.1-rc8 => 4.1}/linux-052-XBOX_remote_support.patch | 0 .../{4.1-rc8 => 4.1}/linux-053-spinelplus-remote-0.2.patch | 0 ...n_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 0 .../linux-056-add_Adaptec_eHome_Infrared_Receiver.patch | 0 ...-Removed-MCE-customer-code-restriction-in-rc6-decode.patch | 0 ...inux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch | 0 ...linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch | 0 .../{4.1-rc8 => 4.1}/linux-062-imon_pad_ignore_diagonal.patch | 0 .../linux-203-stb0899_enable_low_symbol_rate.patch | 0 .../linux-212-mantis_stb0899_faster_lock.patch | 0 .../patches/{4.1-rc8 => 4.1}/linux-221-ngene-octopus.patch | 0 .../{4.1-rc8 => 4.1}/linux-222-stb0899_signal_quality.patch | 0 .../linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch | 0 .../{4.1-rc8 => 4.1}/linux-224-STK1160-addFramescaling.patch | 0 .../linux-227-ds3000-invalid-symbol-rate.patch | 0 .../patches/{4.1-rc8 => 4.1}/linux-706-Sitecom-N300.patch | 0 .../linux-950-saa716x_PCIe_interface_chipset.patch | 0 ...0.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch | 0 .../{4.1-rc8 => 4.1}/linux-995-CX24120-13Z_frontend.patch | 0 .../{4.1-rc8 => 4.1}/linux-999-i915-use-legacy-turbo.patch | 0 ...9.02-0001-pm-disable-async-suspend-resume-by-default.patch | 0 ...eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch | 0 25 files changed, 2 insertions(+), 2 deletions(-) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-003-no_dev_console.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-051-ouya_controller_support.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-052-XBOX_remote_support.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-053-spinelplus-remote-0.2.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-062-imon_pad_ignore_diagonal.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-203-stb0899_enable_low_symbol_rate.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-212-mantis_stb0899_faster_lock.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-221-ngene-octopus.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-222-stb0899_signal_quality.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-224-STK1160-addFramescaling.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-227-ds3000-invalid-symbol-rate.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-706-Sitecom-N300.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-950-saa716x_PCIe_interface_chipset.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-995-CX24120-13Z_frontend.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-999-i915-use-legacy-turbo.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch (100%) rename packages/linux/patches/{4.1-rc8 => 4.1}/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch (100%) diff --git a/packages/linux/package.mk b/packages/linux/package.mk index 5a3c688cad..ccaaa62f4c 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -40,8 +40,8 @@ case "$LINUX" in PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET imx6-status-led imx6-soc-fan" ;; *) - PKG_VERSION="4.1-rc8" - PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/testing/$PKG_NAME-$PKG_VERSION.tar.xz" + PKG_VERSION="4.1" + PKG_URL="http://www.kernel.org/pub/linux/kernel/v4.x/$PKG_NAME-$PKG_VERSION.tar.xz" ;; esac diff --git a/packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch b/packages/linux/patches/4.1/linux-003-no_dev_console.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-003-no_dev_console.patch rename to packages/linux/patches/4.1/linux-003-no_dev_console.patch diff --git a/packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch b/packages/linux/patches/4.1/linux-051-ouya_controller_support.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-051-ouya_controller_support.patch rename to packages/linux/patches/4.1/linux-051-ouya_controller_support.patch diff --git a/packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch b/packages/linux/patches/4.1/linux-052-XBOX_remote_support.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-052-XBOX_remote_support.patch rename to packages/linux/patches/4.1/linux-052-XBOX_remote_support.patch diff --git a/packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/4.1/linux-053-spinelplus-remote-0.2.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-053-spinelplus-remote-0.2.patch rename to packages/linux/patches/4.1/linux-053-spinelplus-remote-0.2.patch diff --git a/packages/linux/patches/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/4.1/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch rename to packages/linux/patches/4.1/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch diff --git a/packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch b/packages/linux/patches/4.1/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch rename to packages/linux/patches/4.1/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch diff --git a/packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/4.1/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch rename to packages/linux/patches/4.1/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch diff --git a/packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch b/packages/linux/patches/4.1/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch rename to packages/linux/patches/4.1/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch diff --git a/packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/4.1/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch rename to packages/linux/patches/4.1/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch diff --git a/packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch b/packages/linux/patches/4.1/linux-062-imon_pad_ignore_diagonal.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-062-imon_pad_ignore_diagonal.patch rename to packages/linux/patches/4.1/linux-062-imon_pad_ignore_diagonal.patch diff --git a/packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch b/packages/linux/patches/4.1/linux-203-stb0899_enable_low_symbol_rate.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-203-stb0899_enable_low_symbol_rate.patch rename to packages/linux/patches/4.1/linux-203-stb0899_enable_low_symbol_rate.patch diff --git a/packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch b/packages/linux/patches/4.1/linux-212-mantis_stb0899_faster_lock.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-212-mantis_stb0899_faster_lock.patch rename to packages/linux/patches/4.1/linux-212-mantis_stb0899_faster_lock.patch diff --git a/packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch b/packages/linux/patches/4.1/linux-221-ngene-octopus.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-221-ngene-octopus.patch rename to packages/linux/patches/4.1/linux-221-ngene-octopus.patch diff --git a/packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch b/packages/linux/patches/4.1/linux-222-stb0899_signal_quality.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-222-stb0899_signal_quality.patch rename to packages/linux/patches/4.1/linux-222-stb0899_signal_quality.patch diff --git a/packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch b/packages/linux/patches/4.1/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch rename to packages/linux/patches/4.1/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch diff --git a/packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch b/packages/linux/patches/4.1/linux-224-STK1160-addFramescaling.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-224-STK1160-addFramescaling.patch rename to packages/linux/patches/4.1/linux-224-STK1160-addFramescaling.patch diff --git a/packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch b/packages/linux/patches/4.1/linux-227-ds3000-invalid-symbol-rate.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-227-ds3000-invalid-symbol-rate.patch rename to packages/linux/patches/4.1/linux-227-ds3000-invalid-symbol-rate.patch diff --git a/packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch b/packages/linux/patches/4.1/linux-706-Sitecom-N300.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-706-Sitecom-N300.patch rename to packages/linux/patches/4.1/linux-706-Sitecom-N300.patch diff --git a/packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/4.1/linux-950-saa716x_PCIe_interface_chipset.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-950-saa716x_PCIe_interface_chipset.patch rename to packages/linux/patches/4.1/linux-950-saa716x_PCIe_interface_chipset.patch diff --git a/packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch b/packages/linux/patches/4.1/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch rename to packages/linux/patches/4.1/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch diff --git a/packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/4.1/linux-995-CX24120-13Z_frontend.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-995-CX24120-13Z_frontend.patch rename to packages/linux/patches/4.1/linux-995-CX24120-13Z_frontend.patch diff --git a/packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch b/packages/linux/patches/4.1/linux-999-i915-use-legacy-turbo.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-999-i915-use-legacy-turbo.patch rename to packages/linux/patches/4.1/linux-999-i915-use-legacy-turbo.patch diff --git a/packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/linux/patches/4.1/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch rename to packages/linux/patches/4.1/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch diff --git a/packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch b/packages/linux/patches/4.1/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch similarity index 100% rename from packages/linux/patches/4.1-rc8/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch rename to packages/linux/patches/4.1/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch From 53b012df496918295221b7466ef967453e3284b3 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 22 Jun 2015 12:03:06 +0300 Subject: [PATCH 16/29] vdr-plugin-vnsiserver: update to 1c63a8a --- packages/multimedia/vdr-plugin-vnsiserver/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/multimedia/vdr-plugin-vnsiserver/package.mk b/packages/multimedia/vdr-plugin-vnsiserver/package.mk index 22de8b57ef..dc0ea06a02 100644 --- a/packages/multimedia/vdr-plugin-vnsiserver/package.mk +++ b/packages/multimedia/vdr-plugin-vnsiserver/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="vdr-plugin-vnsiserver" -PKG_VERSION="a7b0670" +PKG_VERSION="1c63a8a" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 4113491e8609607ea028396dc38ec9b2f8fb5a7b Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Wed, 24 Jun 2015 14:43:22 +0300 Subject: [PATCH 17/29] linux: fix TechnoTrend S2-4600 DVB-S received The TT S2-4600 USB receiver is broken in kernel 4.1 (fixed in 4.2) and will not tune correctly when certain applications (such as vdr) are being used. This patch backports the fix from 4.2 to 4.1 and can be removed when kernel 4.1 is no longer used. --- .../4.1/linux-228-fix-tt-s2-4600.patch | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 packages/linux/patches/4.1/linux-228-fix-tt-s2-4600.patch diff --git a/packages/linux/patches/4.1/linux-228-fix-tt-s2-4600.patch b/packages/linux/patches/4.1/linux-228-fix-tt-s2-4600.patch new file mode 100644 index 0000000000..b3ab7ad94c --- /dev/null +++ b/packages/linux/patches/4.1/linux-228-fix-tt-s2-4600.patch @@ -0,0 +1,63 @@ +diff -urN a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c +--- a/drivers/media/usb/dvb-usb/dw2102.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/usb/dvb-usb/dw2102.c 2015-06-24 14:36:13.236830491 +0300 +@@ -117,8 +117,13 @@ + + struct dw2102_state { + u8 initialized; ++ u8 last_lock; + struct i2c_client *i2c_client_tuner; ++ ++ /* fe hook functions*/ + int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v); ++ int (*fe_read_status)(struct dvb_frontend *fe, ++ fe_status_t *status); + }; + + /* debug */ +@@ -928,8 +933,6 @@ + break; + else + mac[i] = ibuf[0]; +- +- debug_dump(mac, 6, printk); + } + + return 0; +@@ -1001,6 +1004,23 @@ + i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); + } + ++static int tt_s2_4600_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct dvb_usb_adapter *d = ++ (struct dvb_usb_adapter *)(fe->dvb->priv); ++ struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; ++ int ret; ++ ++ ret = st->fe_read_status(fe, status); ++ ++ /* resync slave fifo when signal change from unlock to lock */ ++ if ((*status & FE_HAS_LOCK) && (!st->last_lock)) ++ su3000_streaming_ctrl(d, 1); ++ ++ st->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0; ++ return ret; ++} ++ + static struct stv0299_config sharp_z0194a_config = { + .demod_address = 0x68, + .inittab = sharp_z0194a_inittab, +@@ -1553,6 +1573,12 @@ + + state->i2c_client_tuner = client; + ++ /* hook fe: need to resync the slave fifo when signal locks */ ++ state->fe_read_status = adap->fe_adap[0].fe->ops.read_status; ++ adap->fe_adap[0].fe->ops.read_status = tt_s2_4600_read_status; ++ ++ state->last_lock = 0; ++ + return 0; + } + From c42b43fa9cd9391ce0d3ffd9cb575ba219868aaa Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Wed, 24 Jun 2015 18:54:36 +0300 Subject: [PATCH 18/29] linux: add patch for Hauppauge HVR-2205/2215/2255 support This patch adds support for the Hauppauge HVR-2205/2255 PCIe dual tuners. These are backported from kernel 4.2, so the patch is unnecessary after we move on from kernel 4.1. --- ...inux-229-hauppauge-hvr-2205-and-2255.patch | 618 ++++++++++++++++++ 1 file changed, 618 insertions(+) create mode 100644 packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch diff --git a/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch b/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch new file mode 100644 index 0000000000..f625401e07 --- /dev/null +++ b/packages/linux/patches/4.1/linux-229-hauppauge-hvr-2205-and-2255.patch @@ -0,0 +1,618 @@ +diff -urN a/drivers/media/pci/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c +--- a/drivers/media/pci/saa7164/saa7164-cards.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-cards.c 2015-06-24 18:39:26.842373718 +0300 +@@ -30,6 +30,7 @@ + * attached I2C devices, so we can simplify the virtual i2c mechansms + * and keep the -i2c.c implementation clean. + */ ++#define REGLEN_0bit 0 + #define REGLEN_8bit 1 + #define REGLEN_16bit 2 + +@@ -499,6 +500,144 @@ + .i2c_reg_len = REGLEN_8bit, + } }, + }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2255proto] = { ++ .name = "Hauppauge WinTV-HVR2255(proto)", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x27, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xb2 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x24, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x26, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0x1c >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2255] = { ++ .name = "Hauppauge WinTV-HVR2255", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x28, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xb2 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x25, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x27, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "LGDT3306-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0x1c >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, ++ [SAA7164_BOARD_HAUPPAUGE_HVR2205] = { ++ .name = "Hauppauge WinTV-HVR2205", ++ .porta = SAA7164_MPEG_DVB, ++ .portb = SAA7164_MPEG_DVB, ++ .portc = SAA7164_MPEG_ENCODER, ++ .portd = SAA7164_MPEG_ENCODER, ++ .porte = SAA7164_MPEG_VBI, ++ .portf = SAA7164_MPEG_VBI, ++ .chiprev = SAA7164_CHIP_REV3, ++ .unit = {{ ++ .id = 0x28, ++ .type = SAA7164_UNIT_EEPROM, ++ .name = "4K EEPROM", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xa0 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x04, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_0, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x06, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "SI2168-1", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xc8 >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ }, { ++ .id = 0x25, ++ .type = SAA7164_UNIT_TUNER, ++ .name = "SI2157-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_1, ++ .i2c_bus_addr = 0xc0 >> 1, ++ .i2c_reg_len = REGLEN_0bit, ++ }, { ++ .id = 0x27, ++ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, ++ .name = "SI2168-2", ++ .i2c_bus_nr = SAA7164_I2C_BUS_2, ++ .i2c_bus_addr = 0xcc >> 1, ++ .i2c_reg_len = REGLEN_8bit, ++ } }, ++ }, + }; + const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards); + +@@ -546,6 +685,21 @@ + .subvendor = 0x0070, + .subdevice = 0x8953, + .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5, ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf111, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255, ++ /* Prototype card left here for documenation purposes. ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255proto, ++ */ ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf123, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205, ++ }, { ++ .subvendor = 0x0070, ++ .subdevice = 0xf120, ++ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205, + }, + }; + const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids); +@@ -594,12 +748,26 @@ + case SAA7164_BOARD_HAUPPAUGE_HVR2250: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: + /* ++ HVR2200 / HVR2250 + GPIO 2: s5h1411 / tda10048-1 demod reset + GPIO 3: s5h1411 / tda10048-2 demod reset + GPIO 7: IRBlaster Zilog reset + */ + ++ /* HVR2255 ++ * GPIO 2: lgdg3306-1 demod reset ++ * GPIO 3: lgdt3306-2 demod reset ++ */ ++ ++ /* HVR2205 ++ * GPIO 2: si2168-1 demod reset ++ * GPIO 3: si2168-2 demod reset ++ */ ++ + /* Reset parts by going in and out of reset */ + saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2); + saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3); +@@ -647,6 +815,21 @@ + /* WinTV-HVR2200 (PCIe, Retail, half-height) + * DVB-T (TDA18271/TDA10048) and basic analog, no IR */ + break; ++ case 151009: ++ /* First production board rev B2I6 */ ++ /* WinTV-HVR2205 (PCIe, Retail, full-height bracket) ++ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */ ++ break; ++ case 151609: ++ /* First production board rev B2I6 */ ++ /* WinTV-HVR2205 (PCIe, Retail, half-height bracket) ++ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */ ++ break; ++ case 151061: ++ /* First production board rev B1I6 */ ++ /* WinTV-HVR2255 (PCIe, Retail, full-height bracket) ++ * ATSC/QAM (SI2157/LGDT3306) and basic analog, FM */ ++ break; + default: + printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n", + dev->name, tv.model); +@@ -676,6 +859,9 @@ + case SAA7164_BOARD_HAUPPAUGE_HVR2250: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: + case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: + hauppauge_eeprom(dev, &eeprom[0]); + break; + } +diff -urN a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c +--- a/drivers/media/pci/saa7164/saa7164-dvb.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-dvb.c 2015-06-24 18:42:30.090377859 +0300 +@@ -24,6 +24,9 @@ + #include "tda10048.h" + #include "tda18271.h" + #include "s5h1411.h" ++#include "si2157.h" ++#include "si2168.h" ++#include "lgdt3306a.h" + + #define DRIVER_NAME "saa7164" + +@@ -82,6 +85,64 @@ + .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, + }; + ++static struct lgdt3306a_config hauppauge_hvr2255a_config = { ++ .i2c_addr = 0xb2 >> 1, ++ .qam_if_khz = 4000, ++ .vsb_if_khz = 3250, ++ .deny_i2c_rptr = 1, /* Disabled */ ++ .spectral_inversion = 0, /* Disabled */ ++ .mpeg_mode = LGDT3306A_MPEG_SERIAL, ++ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, ++ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, ++ .xtalMHz = 25, /* 24 or 25 */ ++}; ++ ++static struct lgdt3306a_config hauppauge_hvr2255b_config = { ++ .i2c_addr = 0x1c >> 1, ++ .qam_if_khz = 4000, ++ .vsb_if_khz = 3250, ++ .deny_i2c_rptr = 1, /* Disabled */ ++ .spectral_inversion = 0, /* Disabled */ ++ .mpeg_mode = LGDT3306A_MPEG_SERIAL, ++ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, ++ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, ++ .xtalMHz = 25, /* 24 or 25 */ ++}; ++ ++static struct si2157_config hauppauge_hvr2255_tuner_config = { ++ .inversion = 1, ++}; ++ ++static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter, ++ struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg) ++{ ++ struct i2c_board_info bi; ++ struct i2c_client *tuner; ++ ++ cfg->fe = fe; ++ ++ memset(&bi, 0, sizeof(bi)); ++ ++ strlcpy(bi.type, "si2157", I2C_NAME_SIZE); ++ bi.platform_data = cfg; ++ bi.addr = addr8bit >> 1; ++ ++ request_module(bi.type); ++ ++ tuner = i2c_new_device(adapter, &bi); ++ if (tuner == NULL || tuner->dev.driver == NULL) ++ return -ENODEV; ++ ++ if (!try_module_get(tuner->dev.driver->owner)) { ++ i2c_unregister_device(tuner); ++ return -ENODEV; ++ } ++ ++ port->i2c_client_tuner = tuner; ++ ++ return 0; ++} ++ + static int saa7164_dvb_stop_port(struct saa7164_port *port) + { + struct saa7164_dev *dev = port->dev; +@@ -242,14 +303,16 @@ + if (!demux->dmx.frontend) + return -EINVAL; + +- mutex_lock(&dvb->lock); +- if (dvb->feeding++ == 0) { +- /* Start transport */ +- ret = saa7164_dvb_start_port(port); +- } +- mutex_unlock(&dvb->lock); +- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", +- __func__, port->nr, dvb->feeding); ++ if (dvb) { ++ mutex_lock(&dvb->lock); ++ if (dvb->feeding++ == 0) { ++ /* Start transport */ ++ ret = saa7164_dvb_start_port(port); ++ } ++ mutex_unlock(&dvb->lock); ++ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", ++ __func__, port->nr, dvb->feeding); ++ } + + return ret; + } +@@ -264,14 +327,16 @@ + + dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr); + +- mutex_lock(&dvb->lock); +- if (--dvb->feeding == 0) { +- /* Stop transport */ +- ret = saa7164_dvb_stop_streaming(port); +- } +- mutex_unlock(&dvb->lock); +- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", +- __func__, port->nr, dvb->feeding); ++ if (dvb) { ++ mutex_lock(&dvb->lock); ++ if (--dvb->feeding == 0) { ++ /* Stop transport */ ++ ret = saa7164_dvb_stop_streaming(port); ++ } ++ mutex_unlock(&dvb->lock); ++ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", ++ __func__, port->nr, dvb->feeding); ++ } + + return ret; + } +@@ -425,6 +490,7 @@ + struct saa7164_dev *dev = port->dev; + struct saa7164_buffer *b; + struct list_head *c, *n; ++ struct i2c_client *client; + + dprintk(DBGLVL_DVB, "%s()\n", __func__); + +@@ -443,6 +509,20 @@ + if (dvb->frontend == NULL) + return 0; + ++ /* remove I2C client for tuner */ ++ client = port->i2c_client_tuner; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ ++ /* remove I2C client for demodulator */ ++ client = port->i2c_client_demod; ++ if (client) { ++ module_put(client->dev.driver->owner); ++ i2c_unregister_device(client); ++ } ++ + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +@@ -462,6 +542,12 @@ + struct saa7164_dev *dev = port->dev; + struct saa7164_dvb *dvb = &port->dvb; + struct saa7164_i2c *i2c_bus = NULL; ++ struct si2168_config si2168_config; ++ struct si2157_config si2157_config; ++ struct i2c_adapter *adapter; ++ struct i2c_board_info info; ++ struct i2c_client *client_demod; ++ struct i2c_client *client_tuner; + int ret; + + dprintk(DBGLVL_DVB, "%s()\n", __func__); +@@ -528,6 +614,124 @@ + } + + break; ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto: ++ case SAA7164_BOARD_HAUPPAUGE_HVR2255: ++ i2c_bus = &dev->i2c_bus[2]; ++ ++ if (port->nr == 0) { ++ port->dvb.frontend = dvb_attach(lgdt3306a_attach, ++ &hauppauge_hvr2255a_config, &i2c_bus->i2c_adap); ++ } else { ++ port->dvb.frontend = dvb_attach(lgdt3306a_attach, ++ &hauppauge_hvr2255b_config, &i2c_bus->i2c_adap); ++ } ++ ++ if (port->dvb.frontend != NULL) { ++ ++ if (port->nr == 0) { ++ si2157_attach(port, &dev->i2c_bus[0].i2c_adap, ++ port->dvb.frontend, 0xc0, ++ &hauppauge_hvr2255_tuner_config); ++ } else { ++ si2157_attach(port, &dev->i2c_bus[1].i2c_adap, ++ port->dvb.frontend, 0xc0, ++ &hauppauge_hvr2255_tuner_config); ++ } ++ } ++ break; ++ case SAA7164_BOARD_HAUPPAUGE_HVR2205: ++ ++ if (port->nr == 0) { ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &port->dvb.frontend; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0xc8 >> 1; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap, ++ &info); ++ if (!client_demod || !client_demod->dev.driver) ++ goto frontend_detach; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = port->dvb.frontend; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0xc0 >> 1; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(&dev->i2c_bus[0].i2c_adap, ++ &info); ++ if (!client_tuner || !client_tuner->dev.driver) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_tuner = client_tuner; ++ } else { ++ /* attach frontend */ ++ memset(&si2168_config, 0, sizeof(si2168_config)); ++ si2168_config.i2c_adapter = &adapter; ++ si2168_config.fe = &port->dvb.frontend; ++ si2168_config.ts_mode = SI2168_TS_SERIAL; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2168", I2C_NAME_SIZE); ++ info.addr = 0xcc >> 1; ++ info.platform_data = &si2168_config; ++ request_module(info.type); ++ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap, ++ &info); ++ if (!client_demod || !client_demod->dev.driver) ++ goto frontend_detach; ++ ++ if (!try_module_get(client_demod->dev.driver->owner)) { ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_demod = client_demod; ++ ++ /* attach tuner */ ++ memset(&si2157_config, 0, sizeof(si2157_config)); ++ si2157_config.fe = port->dvb.frontend; ++ memset(&info, 0, sizeof(struct i2c_board_info)); ++ strlcpy(info.type, "si2157", I2C_NAME_SIZE); ++ info.addr = 0xc0 >> 1; ++ info.platform_data = &si2157_config; ++ request_module(info.type); ++ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, ++ &info); ++ if (!client_tuner || !client_tuner->dev.driver) { ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ if (!try_module_get(client_tuner->dev.driver->owner)) { ++ i2c_unregister_device(client_tuner); ++ module_put(client_demod->dev.driver->owner); ++ i2c_unregister_device(client_demod); ++ goto frontend_detach; ++ } ++ port->i2c_client_tuner = client_tuner; ++ } ++ ++ break; + default: + printk(KERN_ERR "%s: The frontend isn't supported\n", + dev->name); +@@ -548,5 +752,9 @@ + } + + return 0; ++ ++frontend_detach: ++ printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__); ++ return -1; + } + +diff -urN a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c +--- a/drivers/media/pci/saa7164/saa7164-encoder.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-encoder.c 2015-06-24 18:41:23.254376349 +0300 +@@ -721,13 +721,14 @@ + sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + +- cap->capabilities = ++ cap->device_caps = + V4L2_CAP_VIDEO_CAPTURE | +- V4L2_CAP_READWRITE | +- 0; ++ V4L2_CAP_READWRITE | ++ V4L2_CAP_TUNER; + +- cap->capabilities |= V4L2_CAP_TUNER; +- cap->version = 0; ++ cap->capabilities = cap->device_caps | ++ V4L2_CAP_VBI_CAPTURE | ++ V4L2_CAP_DEVICE_CAPS; + + return 0; + } +diff -urN a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h +--- a/drivers/media/pci/saa7164/saa7164.h 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164.h 2015-06-24 18:41:57.246377117 +0300 +@@ -83,6 +83,9 @@ + #define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8 + #define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9 + #define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2255proto 11 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2255 12 ++#define SAA7164_BOARD_HAUPPAUGE_HVR2205 13 + + #define SAA7164_MAX_UNITS 8 + #define SAA7164_TS_NUMBER_OF_LINES 312 +@@ -371,6 +374,8 @@ + + /* --- DVB Transport Specific --- */ + struct saa7164_dvb dvb; ++ struct i2c_client *i2c_client_demod; ++ struct i2c_client *i2c_client_tuner; + + /* --- Encoder/V4L related attributes --- */ + /* Encoder */ +@@ -459,6 +464,7 @@ + /* Interrupt status and ack registers */ + u32 int_status; + u32 int_ack; ++ bool msi; + + struct cmd cmds[SAA_CMD_MAX_MSG_UNITS]; + struct mutex lock; +diff -urN a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c +--- a/drivers/media/pci/saa7164/saa7164-vbi.c 2015-06-22 08:05:43.000000000 +0300 ++++ b/drivers/media/pci/saa7164/saa7164-vbi.c 2015-06-24 18:42:05.582377305 +0300 +@@ -660,13 +660,14 @@ + sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); + +- cap->capabilities = ++ cap->device_caps = + V4L2_CAP_VBI_CAPTURE | +- V4L2_CAP_READWRITE | +- 0; ++ V4L2_CAP_READWRITE | ++ V4L2_CAP_TUNER; + +- cap->capabilities |= V4L2_CAP_TUNER; +- cap->version = 0; ++ cap->capabilities = cap->device_caps | ++ V4L2_CAP_VIDEO_CAPTURE | ++ V4L2_CAP_DEVICE_CAPS; + + return 0; + } From 8b98f1222888a5a5f51e97e3a17d6003e2b1f627 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 22 Jun 2015 14:52:23 +0200 Subject: [PATCH 19/29] mpfr: update to mpfr-3.1.3 Signed-off-by: Stephan Raue --- packages/devel/mpfr/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devel/mpfr/package.mk b/packages/devel/mpfr/package.mk index 5707d19d96..8c89d94922 100644 --- a/packages/devel/mpfr/package.mk +++ b/packages/devel/mpfr/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="mpfr" -PKG_VERSION="3.1.2" +PKG_VERSION="3.1.3" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="LGPL" From e86ada4c70ec3f7f1045bb3ba2b4423d8d9c0dde Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 22 Jun 2015 16:03:16 +0200 Subject: [PATCH 20/29] bcm2835-driver: update to bcm2835-driver-8b9d7b8 Signed-off-by: Stephan Raue --- packages/graphics/bcm2835-driver/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphics/bcm2835-driver/package.mk b/packages/graphics/bcm2835-driver/package.mk index dd5e383227..6af9e03f5a 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="37600d5" +PKG_VERSION="8b9d7b8" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="nonfree" From fa0fb9fb10b15ca2e76d38317688c1818e56c4cd Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 22 Jun 2015 16:03:38 +0200 Subject: [PATCH 21/29] bcm2835-bootloader: update to bcm2835-bootloader-8b9d7b8 Signed-off-by: Stephan Raue --- packages/tools/bcm2835-bootloader/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tools/bcm2835-bootloader/package.mk b/packages/tools/bcm2835-bootloader/package.mk index cb06b872c8..9b2a3383eb 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="37600d5" +PKG_VERSION="8b9d7b8" PKG_REV="1" PKG_ARCH="arm" PKG_LICENSE="nonfree" From a719434fd349ae0bd1af4c9cd07d38667713a400 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 22 Jun 2015 16:04:05 +0200 Subject: [PATCH 22/29] libinput: update to libinput-0.18.0 Signed-off-by: Stephan Raue --- packages/wayland/libinput/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wayland/libinput/package.mk b/packages/wayland/libinput/package.mk index cf6275b00f..36aec31111 100644 --- a/packages/wayland/libinput/package.mk +++ b/packages/wayland/libinput/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="libinput" -PKG_VERSION="0.17.0" +PKG_VERSION="0.18.0" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From ef23bf30f530c28c33c89da50267d1fc4db77255 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 22 Jun 2015 16:04:26 +0200 Subject: [PATCH 23/29] curl: update to curl-7.43.0 Signed-off-by: Stephan Raue --- packages/web/curl/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/curl/package.mk b/packages/web/curl/package.mk index 632493e95e..b30d619a83 100644 --- a/packages/web/curl/package.mk +++ b/packages/web/curl/package.mk @@ -25,7 +25,7 @@ # there: http://forum.xbmc.org/showthread.php?tid=177557 PKG_NAME="curl" -PKG_VERSION="7.42.1" +PKG_VERSION="7.43.0" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="MIT" From d482931316f497d756ce24e9039c656cb7485aa9 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Fri, 26 Jun 2015 21:10:40 +0300 Subject: [PATCH 24/29] kodi: update to kodi-15.0-rc1-8f081c2 --- .../kodi-theme-Confluence/package.mk | 2 +- packages/mediacenter/kodi/package.mk | 2 +- .../kodi/patches/kodi-999.22-PR7280.patch | 1364 ----------------- 3 files changed, 2 insertions(+), 1366 deletions(-) delete mode 100644 packages/mediacenter/kodi/patches/kodi-999.22-PR7280.patch diff --git a/packages/mediacenter/kodi-theme-Confluence/package.mk b/packages/mediacenter/kodi-theme-Confluence/package.mk index dc13f3adda..86f90fdc6e 100644 --- a/packages/mediacenter/kodi-theme-Confluence/package.mk +++ b/packages/mediacenter/kodi-theme-Confluence/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="kodi-theme-Confluence" -PKG_VERSION="15.0-rc1-a248db2" +PKG_VERSION="15.0-rc1-8f081c2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi/package.mk b/packages/mediacenter/kodi/package.mk index 890874a28a..0d72df1834 100644 --- a/packages/mediacenter/kodi/package.mk +++ b/packages/mediacenter/kodi/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="kodi" -PKG_VERSION="15.0-rc1-a248db2" +PKG_VERSION="15.0-rc1-8f081c2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi/patches/kodi-999.22-PR7280.patch b/packages/mediacenter/kodi/patches/kodi-999.22-PR7280.patch deleted file mode 100644 index 0cfe4bbd31..0000000000 --- a/packages/mediacenter/kodi/patches/kodi-999.22-PR7280.patch +++ /dev/null @@ -1,1364 +0,0 @@ -From 224c1919ad3f68e23e817f41036687343f34aaae Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 12 Jun 2015 17:27:47 +0100 -Subject: [PATCH] [utils] Disable fast_memcpy which is slower than memcpy - -The default glibc memcpy is likely to be better tuned than this code -which hasn't been touched for four years. - -In a test with software video decode on Pi2 the skipped frames went -from 189 to 172 when fast_memcpy was disabled. ---- - Kodi.xcodeproj/project.pbxproj | 6 - - project/VS2010Express/XBMC.vcxproj | 4 - - project/VS2010Express/XBMC.vcxproj.filters | 3 - - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 1 - - xbmc/cores/VideoRenderers/RenderCapture.cpp | 7 +- - xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp | 33 +- - .../Video/libstagefrightICS/StageFrightVideo.cpp | 3 +- - xbmc/utils/Makefile.in | 2 - - xbmc/utils/fastmemcpy-arm.S | 528 --------------------- - xbmc/utils/fastmemcpy.c | 396 ---------------- - xbmc/utils/fastmemcpy.h | 35 -- - xbmc/utils/test/Makefile | 1 - - xbmc/utils/test/Testfastmemcpy.cpp | 39 -- - 13 files changed, 20 insertions(+), 1038 deletions(-) - delete mode 100644 xbmc/utils/fastmemcpy-arm.S - delete mode 100644 xbmc/utils/fastmemcpy.c - delete mode 100644 xbmc/utils/fastmemcpy.h - delete mode 100644 xbmc/utils/test/Testfastmemcpy.cpp - -diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj -index 395c4ea..ce5a7f7 100644 ---- a/Kodi.xcodeproj/project.pbxproj -+++ b/Kodi.xcodeproj/project.pbxproj -@@ -3192,7 +3192,6 @@ - F5E55B5D10741272006E788A /* DVDPlayerTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */; }; - F5E55B66107412DE006E788A /* GUIDialogTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B65107412DE006E788A /* GUIDialogTeletext.cpp */; }; - F5E55B7010741340006E788A /* Teletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B6E10741340006E788A /* Teletext.cpp */; }; -- F5E5697310803FC3006E788A /* fastmemcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E5697210803FC3006E788A /* fastmemcpy.c */; }; - F5E56BA61082A675006E788A /* PosixMountProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E56BA51082A675006E788A /* PosixMountProvider.cpp */; }; - F5EA02260F6DA990005C2EC5 /* CocoaPowerSyscall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5EA02200F6DA85C005C2EC5 /* CocoaPowerSyscall.cpp */; }; - F5EA02270F6DA9A5005C2EC5 /* PowerManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5EA021A0F6DA7E8005C2EC5 /* PowerManager.cpp */; }; -@@ -3632,7 +3631,6 @@ - 43348AAB1077486D00F859CF /* PlayerSelectionRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlayerSelectionRule.h; path = playercorefactory/PlayerSelectionRule.h; sourceTree = ""; }; - 436721A612D66A09002508E6 /* IAnnouncer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAnnouncer.h; sourceTree = ""; }; - 436B38F3106628850049AB3B /* EndianSwap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EndianSwap.h; sourceTree = ""; }; -- 43BF09DD1080D39300E25290 /* fastmemcpy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fastmemcpy.h; sourceTree = ""; }; - 43FAC87112D6349400F67914 /* IStorageProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IStorageProvider.h; sourceTree = ""; }; - 551C3A43175A12010051AAAD /* VDA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VDA.cpp; sourceTree = ""; }; - 551C3A44175A12010051AAAD /* VDA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VDA.h; sourceTree = ""; }; -@@ -5735,7 +5733,6 @@ - F5E55B6D10741340006E788A /* Teletext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Teletext.h; sourceTree = ""; }; - F5E55B6E10741340006E788A /* Teletext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Teletext.cpp; sourceTree = ""; }; - F5E55B6F10741340006E788A /* TeletextDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TeletextDefines.h; sourceTree = ""; }; -- F5E5697210803FC3006E788A /* fastmemcpy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fastmemcpy.c; sourceTree = ""; }; - F5E56BA41082A675006E788A /* PosixMountProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PosixMountProvider.h; sourceTree = ""; }; - F5E56BA51082A675006E788A /* PosixMountProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PosixMountProvider.cpp; sourceTree = ""; }; - F5EA021A0F6DA7E8005C2EC5 /* PowerManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PowerManager.cpp; sourceTree = ""; }; -@@ -9202,8 +9199,6 @@ - DF529BAD1741697B00523FB4 /* Environment.h */, - E36C29E90DA72486001F0C9D /* Fanart.cpp */, - 6E97BDC30DA2B620003A2A89 /* Fanart.h */, -- F5E5697210803FC3006E788A /* fastmemcpy.c */, -- 43BF09DD1080D39300E25290 /* fastmemcpy.h */, - F5F244641110DC6B009126C6 /* FileOperationJob.cpp */, - F5F244631110DC6B009126C6 /* FileOperationJob.h */, - F5F245EC1112C9AB009126C6 /* FileUtils.cpp */, -@@ -10519,7 +10514,6 @@ - 43348AAE1077486D00F859CF /* PlayerCoreFactory.cpp in Sources */, - 43348AAF1077486D00F859CF /* PlayerSelectionRule.cpp in Sources */, - 7CAA20511079C8160096DE39 /* BaseRenderer.cpp in Sources */, -- F5E5697310803FC3006E788A /* fastmemcpy.c in Sources */, - 55D3604E1826CAB900DA66D2 /* OverlayRendererGUI.cpp in Sources */, - F5E56BA61082A675006E788A /* PosixMountProvider.cpp in Sources */, - 7CAA25351085963B0096DE39 /* PasswordManager.cpp in Sources */, -diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj -index 2d37c57..e8e8dce 100644 ---- a/project/VS2010Express/XBMC.vcxproj -+++ b/project/VS2010Express/XBMC.vcxproj -@@ -1439,10 +1439,6 @@ - true - true - -- -- true -- true -- - - - -diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters -index c858f32..cada31e 100644 ---- a/project/VS2010Express/XBMC.vcxproj.filters -+++ b/project/VS2010Express/XBMC.vcxproj.filters -@@ -2371,9 +2371,6 @@ - - utils\test - -- -- utils\test -- - - utils\test - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 2b64121..fdad7f0 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -31,7 +31,6 @@ - #include - #include "guilib/MatrixGLES.h" - #include "LinuxRendererGLES.h" --#include "utils/fastmemcpy.h" - #include "utils/MathUtils.h" - #include "utils/GLUtils.h" - #include "utils/log.h" -diff --git a/xbmc/cores/VideoRenderers/RenderCapture.cpp b/xbmc/cores/VideoRenderers/RenderCapture.cpp -index 603b68d..0456a27 100644 ---- a/xbmc/cores/VideoRenderers/RenderCapture.cpp -+++ b/xbmc/cores/VideoRenderers/RenderCapture.cpp -@@ -21,7 +21,6 @@ - #include "RenderCapture.h" - #include "utils/log.h" - #include "windowing/WindowingFactory.h" --#include "utils/fastmemcpy.h" - #include "settings/AdvancedSettings.h" - - CRenderCaptureBase::CRenderCaptureBase() -@@ -297,7 +296,7 @@ void CRenderCaptureGL::PboToBuffer() - - if (pboPtr) - { -- fast_memcpy(m_pixels, pboPtr, m_bufferSize); -+ memcpy(m_pixels, pboPtr, m_bufferSize); - SetState(CAPTURESTATE_DONE); - } - else -@@ -491,12 +490,12 @@ void CRenderCaptureDX::SurfaceToBuffer() - //if pitch is same, do a direct copy, otherwise copy one line at a time - if (lockedRect.Pitch == m_width * 4) - { -- fast_memcpy(m_pixels, lockedRect.pBits, m_width * m_height * 4); -+ memcpy(m_pixels, lockedRect.pBits, m_width * m_height * 4); - } - else - { - for (unsigned int y = 0; y < m_height; y++) -- fast_memcpy(m_pixels + y * m_width * 4, (uint8_t*)lockedRect.pBits + y * lockedRect.Pitch, m_width * 4); -+ memcpy(m_pixels + y * m_width * 4, (uint8_t*)lockedRect.pBits + y * lockedRect.Pitch, m_width * 4); - } - m_copySurface->UnlockRect(); - SetState(CAPTURESTATE_DONE); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp -index 56e68713..5f0e486 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp -@@ -22,7 +22,6 @@ - #include "DVDClock.h" - #include "cores/VideoRenderers/RenderManager.h" - #include "utils/log.h" --#include "utils/fastmemcpy.h" - #include "cores/FFmpeg.h" - #include "Util.h" - #ifdef HAS_DX -@@ -95,7 +94,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) - - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[0]; - d += pDst->iLineSize[0]; - } -@@ -107,7 +106,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) - d = pDst->data[1]; - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[1]; - d += pDst->iLineSize[1]; - } -@@ -116,7 +115,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) - d = pDst->data[2]; - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[2]; - d += pDst->iLineSize[2]; - } -@@ -131,13 +130,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) - int h = pImage->height; - if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) - { -- fast_memcpy(d, s, w*h); -+ memcpy(d, s, w*h); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[0]; - d += pImage->stride[0]; - } -@@ -148,13 +147,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) - h =(pImage->height >> pImage->cshift_y); - if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1])) - { -- fast_memcpy(d, s, w*h); -+ memcpy(d, s, w*h); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[1]; - d += pImage->stride[1]; - } -@@ -163,13 +162,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) - d = pImage->plane[2]; - if ((w==pSrc->iLineSize[2]) && ((unsigned int) pSrc->iLineSize[2]==pImage->stride[2])) - { -- fast_memcpy(d, s, w*h); -+ memcpy(d, s, w*h); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[2]; - d += pImage->stride[2]; - } -@@ -207,7 +206,7 @@ DVDVideoPicture* CDVDCodecUtils::ConvertToNV12Picture(DVDVideoPicture *pSrc) - uint8_t *d = pPicture->data[0]; - for (int y = 0; y < (int)pSrc->iHeight; y++) - { -- fast_memcpy(d, s, pSrc->iWidth); -+ memcpy(d, s, pSrc->iWidth); - s += pSrc->iLineSize[0]; - d += pPicture->iLineSize[0]; - } -@@ -298,13 +297,13 @@ bool CDVDCodecUtils::CopyNV12Picture(YV12Image* pImage, DVDVideoPicture *pSrc) - // Copy Y - if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) - { -- fast_memcpy(d, s, w*h); -+ memcpy(d, s, w*h); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[0]; - d += pImage->stride[0]; - } -@@ -317,13 +316,13 @@ bool CDVDCodecUtils::CopyNV12Picture(YV12Image* pImage, DVDVideoPicture *pSrc) - // Copy packed UV (width is same as for Y as it's both U and V components) - if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1])) - { -- fast_memcpy(d, s, w*h); -+ memcpy(d, s, w*h); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w); -+ memcpy(d, s, w); - s += pSrc->iLineSize[1]; - d += pImage->stride[1]; - } -@@ -342,13 +341,13 @@ bool CDVDCodecUtils::CopyYUV422PackedPicture(YV12Image* pImage, DVDVideoPicture - // Copy YUYV - if ((w * 2 == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) - { -- fast_memcpy(d, s, w*h*2); -+ memcpy(d, s, w*h*2); - } - else - { - for (int y = 0; y < h; y++) - { -- fast_memcpy(d, s, w*2); -+ memcpy(d, s, w*2); - s += pSrc->iLineSize[0]; - d += pImage->stride[0]; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp -index 019bc7a..d5ca74f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp -@@ -30,7 +30,6 @@ - #include "guilib/GraphicContext.h" - #include "DVDClock.h" - #include "utils/log.h" --#include "utils/fastmemcpy.h" - #include "threads/Thread.h" - #include "threads/Event.h" - #include "Application.h" -@@ -620,7 +619,7 @@ int CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts - return VC_ERROR; - } - -- fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes); -+ memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes); - frame->medbuf->set_range(0, demuxer_bytes); - frame->medbuf->meta_data()->clear(); - frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts); -diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in -index 438f025..dbd3db9 100644 ---- a/xbmc/utils/Makefile.in -+++ b/xbmc/utils/Makefile.in -@@ -17,8 +17,6 @@ SRCS += DatabaseUtils.cpp - SRCS += EndianSwap.cpp - SRCS += Environment.cpp - SRCS += Fanart.cpp --SRCS += fastmemcpy.c --SRCS += fastmemcpy-arm.S - SRCS += FileOperationJob.cpp - SRCS += FileUtils.cpp - SRCS += fstrcmp.c -diff --git a/xbmc/utils/fastmemcpy-arm.S b/xbmc/utils/fastmemcpy-arm.S -deleted file mode 100644 -index 6cb8b0c..0000000 ---- a/xbmc/utils/fastmemcpy-arm.S -+++ /dev/null -@@ -1,528 +0,0 @@ --/* -- * Copyright (C) 2008 The Android Open Source Project -- * All rights reserved. -- * -- * Copyright (C) 2011-2013 Team XBMC -- * http://xbmc.org -- * -- * This Program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2, or (at your option) -- * any later version. -- * -- * This Program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with XBMC; see the file COPYING. If not, see -- * . -- * -- */ --#if defined(__arm__) && !defined(TARGET_ANDROID) && !defined(TARGET_DARWIN_IOS) --#if defined(__ARM_NEON__) -- -- .text --#ifndef __APPLE__ -- .fpu neon -- .global fast_memcpy -- .type fast_memcpy, %function --#else -- .globl _fast_memcpy --#endif -- .align 4 -- --/* a prefetch distance of 4 cache-lines works best experimentally */ --#define CACHE_LINE_SIZE 64 --#define PREFETCH_DISTANCE (CACHE_LINE_SIZE*4) -- --#ifndef __APPLE__ -- .fnstart -- .save {r0, lr} --fast_memcpy: --#else --_fast_memcpy: --#endif -- stmfd sp!, {r0, lr} -- -- /* start preloading as early as possible */ -- pld [r1, #(CACHE_LINE_SIZE*0)] -- pld [r1, #(CACHE_LINE_SIZE*1)] -- -- /* do we have at least 16-bytes to copy (needed for alignment below) */ -- cmp r2, #16 -- blo 5f -- -- /* align destination to half cache-line for the write-buffer */ -- rsb r3, r0, #0 -- ands r3, r3, #0xF -- beq 0f -- -- /* copy up to 15-bytes (count in r3) */ -- sub r2, r2, r3 -- movs ip, r3, lsl #31 -- ldrmib lr, [r1], #1 -- strmib lr, [r0], #1 -- ldrcsb ip, [r1], #1 -- ldrcsb lr, [r1], #1 -- strcsb ip, [r0], #1 -- strcsb lr, [r0], #1 -- movs ip, r3, lsl #29 -- bge 1f -- // copies 4 bytes, destination 32-bits aligned -- vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! -- vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]! --1: bcc 2f -- // copies 8 bytes, destination 64-bits aligned -- vld1.8 {d0}, [r1]! -- vst1.8 {d0}, [r0, :64]! --2: -- --0: /* preload immediately the next cache line, which we may need */ -- pld [r1, #(CACHE_LINE_SIZE*0)] -- pld [r1, #(CACHE_LINE_SIZE*1)] -- -- /* make sure we have at least 64 bytes to copy */ -- subs r2, r2, #64 -- blo 2f -- -- /* preload all the cache lines we need. -- * NOTE: the number of pld below depends on PREFETCH_DISTANCE, -- * ideally would would increase the distance in the main loop to -- * avoid the goofy code below. In practice this doesn't seem to make -- * a big difference. -- */ -- pld [r1, #(CACHE_LINE_SIZE*2)] -- pld [r1, #(CACHE_LINE_SIZE*3)] -- pld [r1, #(PREFETCH_DISTANCE)] -- --1: /* The main loop copies 64 bytes at a time */ -- vld1.8 {d0 - d3}, [r1]! -- vld1.8 {d4 - d7}, [r1]! -- pld [r1, #(PREFETCH_DISTANCE)] -- subs r2, r2, #64 -- vst1.8 {d0 - d3}, [r0, :128]! -- vst1.8 {d4 - d7}, [r0, :128]! -- bhs 1b -- --2: /* fix-up the remaining count and make sure we have >= 32 bytes left */ -- add r2, r2, #64 -- subs r2, r2, #32 -- blo 4f -- --3: /* 32 bytes at a time. These cache lines were already preloaded */ -- vld1.8 {d0 - d3}, [r1]! -- subs r2, r2, #32 -- vst1.8 {d0 - d3}, [r0, :128]! -- bhs 3b -- --4: /* less than 32 left */ -- add r2, r2, #32 -- tst r2, #0x10 -- beq 5f -- // copies 16 bytes, 128-bits aligned -- vld1.8 {d0, d1}, [r1]! -- vst1.8 {d0, d1}, [r0, :128]! -- --5: /* copy up to 15-bytes (count in r2) */ -- movs ip, r2, lsl #29 -- bcc 1f -- vld1.8 {d0}, [r1]! -- vst1.8 {d0}, [r0]! --1: bge 2f -- vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! -- vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]! --2: movs ip, r2, lsl #31 -- ldrmib r3, [r1], #1 -- ldrcsb ip, [r1], #1 -- ldrcsb lr, [r1], #1 -- strmib r3, [r0], #1 -- strcsb ip, [r0], #1 -- strcsb lr, [r0], #1 -- -- ldmfd sp!, {r0, lr} -- bx lr --#ifndef __APPLE__ -- .fnend --#endif -- --#else /* __ARM_ARCH__ < 7 */ -- -- -- .text -- --#ifndef __APPLE__ -- .global fast_memcpy -- .type fast_memcpy, %function --#else -- .globl _fast_memcpy --#endif -- .align 4 -- -- /* -- * Optimized memcpy() for ARM. -- * -- * note that memcpy() always returns the destination pointer, -- * so we have to preserve R0. -- */ -- --#ifndef __APPLE__ --fast_memcpy: --#else --_fast_memcpy: --#endif -- /* The stack must always be 64-bits aligned to be compliant with the -- * ARM ABI. Since we have to save R0, we might as well save R4 -- * which we can use for better pipelining of the reads below -- */ --#ifndef __APPLE__ -- .fnstart -- .save {r0, r4, lr} --#endif -- stmfd sp!, {r0, r4, lr} -- /* Making room for r5-r11 which will be spilled later */ -- .pad #28 -- sub sp, sp, #28 -- -- // preload the destination because we'll align it to a cache line -- // with small writes. Also start the source "pump". -- //PLD (r0, #0) -- //PLD (r1, #0) -- //PLD (r1, #32) -- -- /* it simplifies things to take care of len<4 early */ -- cmp r2, #4 -- blo copy_last_3_and_return -- -- /* compute the offset to align the source -- * offset = (4-(src&3))&3 = -src & 3 -- */ -- rsb r3, r1, #0 -- ands r3, r3, #3 -- beq src_aligned -- -- /* align source to 32 bits. We need to insert 2 instructions between -- * a ldr[b|h] and str[b|h] because byte and half-word instructions -- * stall 2 cycles. -- */ -- movs r12, r3, lsl #31 -- sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */ -- ldrmib r3, [r1], #1 -- ldrcsb r4, [r1], #1 -- ldrcsb r12,[r1], #1 -- strmib r3, [r0], #1 -- strcsb r4, [r0], #1 -- strcsb r12,[r0], #1 -- --src_aligned: -- -- /* see if src and dst are aligned together (congruent) */ -- eor r12, r0, r1 -- tst r12, #3 -- bne non_congruent -- -- /* Use post-incriment mode for stm to spill r5-r11 to reserved stack -- * frame. Don't update sp. -- */ -- stmea sp, {r5-r11} -- -- /* align the destination to a cache-line */ -- rsb r3, r0, #0 -- ands r3, r3, #0x1C -- beq congruent_aligned32 -- cmp r3, r2 -- andhi r3, r2, #0x1C -- -- /* conditionnaly copies 0 to 7 words (length in r3) */ -- movs r12, r3, lsl #28 -- ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ -- ldmmiia r1!, {r8, r9} /* 8 bytes */ -- stmcsia r0!, {r4, r5, r6, r7} -- stmmiia r0!, {r8, r9} -- tst r3, #0x4 -- ldrne r10,[r1], #4 /* 4 bytes */ -- strne r10,[r0], #4 -- sub r2, r2, r3 -- --congruent_aligned32: -- /* -- * here source is aligned to 32 bytes. -- */ -- --cached_aligned32: -- subs r2, r2, #32 -- blo less_than_32_left -- -- /* -- * We preload a cache-line up to 64 bytes ahead. On the 926, this will -- * stall only until the requested world is fetched, but the linefill -- * continues in the the background. -- * While the linefill is going, we write our previous cache-line -- * into the write-buffer (which should have some free space). -- * When the linefill is done, the writebuffer will -- * start dumping its content into memory -- * -- * While all this is going, we then load a full cache line into -- * 8 registers, this cache line should be in the cache by now -- * (or partly in the cache). -- * -- * This code should work well regardless of the source/dest alignment. -- * -- */ -- -- // Align the preload register to a cache-line because the cpu does -- // "critical word first" (the first word requested is loaded first). -- bic r12, r1, #0x1F -- add r12, r12, #64 -- --1: ldmia r1!, { r4-r11 } -- //PLD (r12, #64) -- subs r2, r2, #32 -- -- // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi -- // for ARM9 preload will not be safely guarded by the preceding subs. -- // When it is safely guarded the only possibility to have SIGSEGV here -- // is because the caller overstates the length. -- ldrhi r3, [r12], #32 /* cheap ARM9 preload */ -- stmia r0!, { r4-r11 } -- bhs 1b -- -- add r2, r2, #32 -- -- -- -- --less_than_32_left: -- /* -- * less than 32 bytes left at this point (length in r2) -- */ -- -- /* skip all this if there is nothing to do, which should -- * be a common case (if not executed the code below takes -- * about 16 cycles) -- */ -- tst r2, #0x1F -- beq 1f -- -- /* conditionnaly copies 0 to 31 bytes */ -- movs r12, r2, lsl #28 -- ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ -- ldmmiia r1!, {r8, r9} /* 8 bytes */ -- stmcsia r0!, {r4, r5, r6, r7} -- stmmiia r0!, {r8, r9} -- movs r12, r2, lsl #30 -- ldrcs r3, [r1], #4 /* 4 bytes */ -- ldrmih r4, [r1], #2 /* 2 bytes */ -- strcs r3, [r0], #4 -- strmih r4, [r0], #2 -- tst r2, #0x1 -- ldrneb r3, [r1] /* last byte */ -- strneb r3, [r0] -- -- /* we're done! restore everything and return */ --1: ldmfd sp!, {r5-r11} -- ldmfd sp!, {r0, r4, lr} -- bx lr -- -- /********************************************************************/ -- --non_congruent: -- /* -- * here source is aligned to 4 bytes -- * but destination is not. -- * -- * in the code below r2 is the number of bytes read -- * (the number of bytes written is always smaller, because we have -- * partial words in the shift queue) -- */ -- cmp r2, #4 -- blo copy_last_3_and_return -- -- /* Use post-incriment mode for stm to spill r5-r11 to reserved stack -- * frame. Don't update sp. -- */ -- stmea sp, {r5-r11} -- -- /* compute shifts needed to align src to dest */ -- rsb r5, r0, #0 -- and r5, r5, #3 /* r5 = # bytes in partial words */ -- mov r12, r5, lsl #3 /* r12 = right */ -- rsb lr, r12, #32 /* lr = left */ -- -- /* read the first word */ -- ldr r3, [r1], #4 -- sub r2, r2, #4 -- -- /* write a partial word (0 to 3 bytes), such that destination -- * becomes aligned to 32 bits (r5 = nb of words to copy for alignment) -- */ -- movs r5, r5, lsl #31 -- strmib r3, [r0], #1 -- movmi r3, r3, lsr #8 -- strcsb r3, [r0], #1 -- movcs r3, r3, lsr #8 -- strcsb r3, [r0], #1 -- movcs r3, r3, lsr #8 -- -- cmp r2, #4 -- blo partial_word_tail -- -- /* Align destination to 32 bytes (cache line boundary) */ --1: tst r0, #0x1c -- beq 2f -- ldr r5, [r1], #4 -- sub r2, r2, #4 -- orr r4, r3, r5, lsl lr -- mov r3, r5, lsr r12 -- str r4, [r0], #4 -- cmp r2, #4 -- bhs 1b -- blo partial_word_tail -- -- /* copy 32 bytes at a time */ --2: subs r2, r2, #32 -- blo less_than_thirtytwo -- -- /* Use immediate mode for the shifts, because there is an extra cycle -- * for register shifts, which could account for up to 50% of -- * performance hit. -- */ -- -- cmp r12, #24 -- beq loop24 -- cmp r12, #8 -- beq loop8 -- --loop16: -- ldr r12, [r1], #4 --1: mov r4, r12 -- ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} -- //PLD (r1, #64) -- subs r2, r2, #32 -- ldrhs r12, [r1], #4 -- orr r3, r3, r4, lsl #16 -- mov r4, r4, lsr #16 -- orr r4, r4, r5, lsl #16 -- mov r5, r5, lsr #16 -- orr r5, r5, r6, lsl #16 -- mov r6, r6, lsr #16 -- orr r6, r6, r7, lsl #16 -- mov r7, r7, lsr #16 -- orr r7, r7, r8, lsl #16 -- mov r8, r8, lsr #16 -- orr r8, r8, r9, lsl #16 -- mov r9, r9, lsr #16 -- orr r9, r9, r10, lsl #16 -- mov r10, r10, lsr #16 -- orr r10, r10, r11, lsl #16 -- stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} -- mov r3, r11, lsr #16 -- bhs 1b -- b less_than_thirtytwo -- --loop8: -- ldr r12, [r1], #4 --1: mov r4, r12 -- ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} -- //PLD (r1, #64) -- subs r2, r2, #32 -- ldrhs r12, [r1], #4 -- orr r3, r3, r4, lsl #24 -- mov r4, r4, lsr #8 -- orr r4, r4, r5, lsl #24 -- mov r5, r5, lsr #8 -- orr r5, r5, r6, lsl #24 -- mov r6, r6, lsr #8 -- orr r6, r6, r7, lsl #24 -- mov r7, r7, lsr #8 -- orr r7, r7, r8, lsl #24 -- mov r8, r8, lsr #8 -- orr r8, r8, r9, lsl #24 -- mov r9, r9, lsr #8 -- orr r9, r9, r10, lsl #24 -- mov r10, r10, lsr #8 -- orr r10, r10, r11, lsl #24 -- stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} -- mov r3, r11, lsr #8 -- bhs 1b -- b less_than_thirtytwo -- --loop24: -- ldr r12, [r1], #4 --1: mov r4, r12 -- ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} -- //PLD (r1, #64) -- subs r2, r2, #32 -- ldrhs r12, [r1], #4 -- orr r3, r3, r4, lsl #8 -- mov r4, r4, lsr #24 -- orr r4, r4, r5, lsl #8 -- mov r5, r5, lsr #24 -- orr r5, r5, r6, lsl #8 -- mov r6, r6, lsr #24 -- orr r6, r6, r7, lsl #8 -- mov r7, r7, lsr #24 -- orr r7, r7, r8, lsl #8 -- mov r8, r8, lsr #24 -- orr r8, r8, r9, lsl #8 -- mov r9, r9, lsr #24 -- orr r9, r9, r10, lsl #8 -- mov r10, r10, lsr #24 -- orr r10, r10, r11, lsl #8 -- stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} -- mov r3, r11, lsr #24 -- bhs 1b -- -- --less_than_thirtytwo: -- /* copy the last 0 to 31 bytes of the source */ -- rsb r12, lr, #32 /* we corrupted r12, recompute it */ -- add r2, r2, #32 -- cmp r2, #4 -- blo partial_word_tail -- --1: ldr r5, [r1], #4 -- sub r2, r2, #4 -- orr r4, r3, r5, lsl lr -- mov r3, r5, lsr r12 -- str r4, [r0], #4 -- cmp r2, #4 -- bhs 1b -- --partial_word_tail: -- /* we have a partial word in the input buffer */ -- movs r5, lr, lsl #(31-3) -- strmib r3, [r0], #1 -- movmi r3, r3, lsr #8 -- strcsb r3, [r0], #1 -- movcs r3, r3, lsr #8 -- strcsb r3, [r0], #1 -- -- /* Refill spilled registers from the stack. Don't update sp. */ -- ldmfd sp, {r5-r11} -- --copy_last_3_and_return: -- movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */ -- ldrmib r2, [r1], #1 -- ldrcsb r3, [r1], #1 -- ldrcsb r12,[r1] -- strmib r2, [r0], #1 -- strcsb r3, [r0], #1 -- strcsb r12,[r0] -- -- /* we're done! restore sp and spilled registers and return */ -- add sp, sp, #28 -- ldmfd sp!, {r0, r4, lr} -- bx lr --#ifndef __APPLE__ -- .fnend --#endif -- --#endif /* __ARM_ARCH__ < 7 */ --#endif -- --#if defined(__linux__) && defined(__ELF__) --/* we don't need an executable stack */ --.section .note.GNU-stack,"",%progbits --#endif -diff --git a/xbmc/utils/fastmemcpy.c b/xbmc/utils/fastmemcpy.c -deleted file mode 100644 -index ec9019a..0000000 ---- a/xbmc/utils/fastmemcpy.c -+++ /dev/null -@@ -1,396 +0,0 @@ --/* -- * fastmemcpy.h : fast memcpy routines -- ***************************************************************************** -- * $Id: fastmemcpy.h 13905 2006-01-12 23:10:04Z dionoea $ -- * -- * Authors: various Linux kernel hackers -- * various MPlayer hackers -- * Nick Kurshev -- * -- * Copyright (C) 2011-2013 Team XBMC -- * http://xbmc.org -- * -- * This Program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2, or (at your option) -- * any later version. -- * -- * This Program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with XBMC; see the file COPYING. If not, see -- * . -- * -- */ --#if !defined(TARGET_WINDOWS) && !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__mips__) --#define HAVE_MMX2 --#define HAVE_SSE -- --/* -- aclib - advanced C library ;) -- This file contains functions which improve and expand standard C-library --*/ --#include -- --#define BLOCK_SIZE 4096 --#define CONFUSION_FACTOR 0 --/*Feel free to fine-tune the above 2, it might be possible to get some speedup with them :)*/ -- --/*#define STATISTICS*/ -- --#ifndef HAVE_SSE2 --/* -- P3 processor has only one SSE decoder so can execute only 1 sse insn per -- cpu clock, but it has 3 mmx decoders (include load/store unit) -- and executes 3 mmx insns per cpu clock. -- P4 processor has some chances, but after reading: -- http://www.emulators.com/pentium4.htm -- I have doubts. Anyway SSE2 version of this code can be written better. --*/ --#undef HAVE_SSE --#endif -- -- --/* -- This part of code was taken by me from Linux-2.4.3 and slightly modified --for MMX, MMX2, SSE instruction set. I have done it since linux uses page aligned --blocks but mplayer uses weakly ordered data and original sources can not --speedup them. Only using PREFETCHNTA and MOVNTQ together have effect! -- -->From IA-32 Intel Architecture Software Developer's Manual Volume 1, -- --Order Number 245470: --"10.4.6. Cacheability Control, Prefetch, and Memory Ordering Instructions" -- --Data referenced by a program can be temporal (data will be used again) or --non-temporal (data will be referenced once and not reused in the immediate --future). To make efficient use of the processor's caches, it is generally --desirable to cache temporal data and not cache non-temporal data. Overloading --the processor's caches with non-temporal data is sometimes referred to as --"polluting the caches". --The non-temporal data is written to memory with Write-Combining semantics. -- --The PREFETCHh instructions permits a program to load data into the processor --at a suggested cache level, so that it is closer to the processors load and --store unit when it is needed. If the data is already present in a level of --the cache hierarchy that is closer to the processor, the PREFETCHh instruction --will not result in any data movement. --But we should you PREFETCHNTA: Non-temporal data fetch data into location --close to the processor, minimizing cache pollution. -- --The MOVNTQ (store quadword using non-temporal hint) instruction stores --packed integer data from an MMX register to memory, using a non-temporal hint. --The MOVNTPS (store packed single-precision floating-point values using --non-temporal hint) instruction stores packed floating-point data from an --XMM register to memory, using a non-temporal hint. -- --The SFENCE (Store Fence) instruction controls write ordering by creating a --fence for memory store operations. This instruction guarantees that the results --of every store instruction that precedes the store fence in program order is --globally visible before any store instruction that follows the fence. The --SFENCE instruction provides an efficient way of ensuring ordering between --procedures that produce weakly-ordered data and procedures that consume that --data. -- --If you have questions please contact with me: Nick Kurshev: nickols_k@mail.ru. --*/ -- --/* 3dnow memcpy support from kernel 2.4.2 */ --/* by Pontscho/fresh!mindworkz */ -- --#if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX ) -- --#undef HAVE_MMX1 --#if defined(HAVE_MMX) && !defined(HAVE_MMX2) && !defined(HAVE_3DNOW) && !defined(HAVE_SSE) --/* means: mmx v.1. Note: Since we added alignment of destinition it speedups -- of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus -- standard (non MMX-optimized) version. -- Note: on K6-2+ it speedups memory copying upto 25% and -- on K7 and P3 about 500% (5 times). */ --#define HAVE_MMX1 --#endif -- -- --#undef HAVE_K6_2PLUS --#if !defined( HAVE_MMX2) && defined( HAVE_3DNOW) --#define HAVE_K6_2PLUS --#endif -- --/* for small memory blocks (<256 bytes) this version is faster */ --#define small_memcpy(to,from,n)\ --{\ --register unsigned long int dummy;\ --__asm__ __volatile__(\ -- "rep; movsb"\ -- :"=&D"(to), "=&S"(from), "=&c"(dummy)\ --/* It's most portable way to notify compiler */\ --/* that edi, esi and ecx are clobbered in asm block. */\ --/* Thanks to A'rpi for hint!!! */\ -- :"0" (to), "1" (from),"2" (n)\ -- : "memory");\ --} -- --#ifdef HAVE_SSE --#define MMREG_SIZE 16 --#else --#define MMREG_SIZE 64 /*8*/ --#endif -- --/* Small defines (for readability only) ;) */ --#ifdef HAVE_K6_2PLUS --#define PREFETCH "prefetch" --/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ --#define EMMS "femms" --#else --#define PREFETCH "prefetchnta" --#define EMMS "emms" --#endif -- --#ifdef HAVE_MMX2 --#define MOVNTQ "movntq" --#else --#define MOVNTQ "movq" --#endif -- --#ifdef HAVE_MMX1 --#define MIN_LEN 0x800 /* 2K blocks */ --#else --#define MIN_LEN 0x40 /* 64-byte blocks */ --#endif -- --void * fast_memcpy(void * to, const void * from, size_t len) --{ -- void *retval; -- size_t i; -- retval = to; --#ifdef STATISTICS -- { -- static int freq[33]; -- static int t=0; -- int i; -- for(i=0; len>(1<= MIN_LEN) -- { -- register unsigned long int delta; -- /* Align destinition to MMREG_SIZE -boundary */ -- delta = ((unsigned long int)to)&(MMREG_SIZE-1); -- if(delta) -- { -- delta=MMREG_SIZE-delta; -- len -= delta; -- small_memcpy(to, from, delta); -- } -- i = len >> 6; /* len/64 */ -- len&=63; -- /* -- This algorithm is top effective when the code consequently -- reads and writes blocks which have size of cache line. -- Size of cache line is processor-dependent. -- It will, however, be a minimum of 32 bytes on any processors. -- It would be better to have a number of instructions which -- perform reading and writing to be multiple to a number of -- processor's decoders, but it's not always possible. -- */ --#ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */ -- if(((unsigned long)from) & 15) -- /* if SRC is misaligned */ -- for(; i>0; i--) -- { -- __asm__ __volatile__ ( -- PREFETCH" 320(%0)\n" -- "movups (%0), %%xmm0\n" -- "movups 16(%0), %%xmm1\n" -- "movups 32(%0), %%xmm2\n" -- "movups 48(%0), %%xmm3\n" -- "movntps %%xmm0, (%1)\n" -- "movntps %%xmm1, 16(%1)\n" -- "movntps %%xmm2, 32(%1)\n" -- "movntps %%xmm3, 48(%1)\n" -- :: "r" (from), "r" (to) : "memory"); -- ((const unsigned char *)from)+=64; -- ((unsigned char *)to)+=64; -- } -- else -- /* -- Only if SRC is aligned on 16-byte boundary. -- It allows to use movaps instead of movups, which required data -- to be aligned or a general-protection exception (#GP) is generated. -- */ -- for(; i>0; i--) -- { -- __asm__ __volatile__ ( -- PREFETCH" 320(%0)\n" -- "movaps (%0), %%xmm0\n" -- "movaps 16(%0), %%xmm1\n" -- "movaps 32(%0), %%xmm2\n" -- "movaps 48(%0), %%xmm3\n" -- "movntps %%xmm0, (%1)\n" -- "movntps %%xmm1, 16(%1)\n" -- "movntps %%xmm2, 32(%1)\n" -- "movntps %%xmm3, 48(%1)\n" -- :: "r" (from), "r" (to) : "memory"); -- ((const unsigned char *)from)+=64; -- ((unsigned char *)to)+=64; -- } --#else -- /* Align destination at BLOCK_SIZE boundary */ -- for(; ((ptrdiff_t)to & (BLOCK_SIZE-1)) && i>0; i--) -- { -- __asm__ __volatile__ ( --#ifndef HAVE_MMX1 -- PREFETCH" 320(%0)\n" --#endif -- "movq (%0), %%mm0\n" -- "movq 8(%0), %%mm1\n" -- "movq 16(%0), %%mm2\n" -- "movq 24(%0), %%mm3\n" -- "movq 32(%0), %%mm4\n" -- "movq 40(%0), %%mm5\n" -- "movq 48(%0), %%mm6\n" -- "movq 56(%0), %%mm7\n" -- MOVNTQ" %%mm0, (%1)\n" -- MOVNTQ" %%mm1, 8(%1)\n" -- MOVNTQ" %%mm2, 16(%1)\n" -- MOVNTQ" %%mm3, 24(%1)\n" -- MOVNTQ" %%mm4, 32(%1)\n" -- MOVNTQ" %%mm5, 40(%1)\n" -- MOVNTQ" %%mm6, 48(%1)\n" -- MOVNTQ" %%mm7, 56(%1)\n" -- :: "r" (from), "r" (to) : "memory"); -- from = (const void *) (((const unsigned char *)from)+64); -- to = (void *) (((unsigned char *)to)+64); -- } -- --/* printf(" %p %p\n", (ptrdiff_t)from&1023, (ptrdiff_t)to&1023); */ -- /* Pure Assembly cuz gcc is a bit unpredictable ;) */ --# if 0 -- if(i>=BLOCK_SIZE/64) -- asm volatile( -- "xorl %%eax, %%eax \n\t" -- ".balign 16 \n\t" -- "1: \n\t" -- "movl (%0, %%eax), %%ebx \n\t" -- "movl 32(%0, %%eax), %%ebx \n\t" -- "movl 64(%0, %%eax), %%ebx \n\t" -- "movl 96(%0, %%eax), %%ebx \n\t" -- "addl $128, %%eax \n\t" -- "cmpl %3, %%eax \n\t" -- " jb 1b \n\t" -- -- "xorl %%eax, %%eax \n\t" -- -- ".balign 16 \n\t" -- "2: \n\t" -- "movq (%0, %%eax), %%mm0\n" -- "movq 8(%0, %%eax), %%mm1\n" -- "movq 16(%0, %%eax), %%mm2\n" -- "movq 24(%0, %%eax), %%mm3\n" -- "movq 32(%0, %%eax), %%mm4\n" -- "movq 40(%0, %%eax), %%mm5\n" -- "movq 48(%0, %%eax), %%mm6\n" -- "movq 56(%0, %%eax), %%mm7\n" -- MOVNTQ" %%mm0, (%1, %%eax)\n" -- MOVNTQ" %%mm1, 8(%1, %%eax)\n" -- MOVNTQ" %%mm2, 16(%1, %%eax)\n" -- MOVNTQ" %%mm3, 24(%1, %%eax)\n" -- MOVNTQ" %%mm4, 32(%1, %%eax)\n" -- MOVNTQ" %%mm5, 40(%1, %%eax)\n" -- MOVNTQ" %%mm6, 48(%1, %%eax)\n" -- MOVNTQ" %%mm7, 56(%1, %%eax)\n" -- "addl $64, %%eax \n\t" -- "cmpl %3, %%eax \n\t" -- "jb 2b \n\t" -- --#if CONFUSION_FACTOR > 0 -- /* a few percent speedup on out of order executing CPUs */ -- "movl %5, %%eax \n\t" -- "2: \n\t" -- "movl (%0), %%ebx \n\t" -- "movl (%0), %%ebx \n\t" -- "movl (%0), %%ebx \n\t" -- "movl (%0), %%ebx \n\t" -- "decl %%eax \n\t" -- " jnz 2b \n\t" --#endif -- -- "xorl %%eax, %%eax \n\t" -- "addl %3, %0 \n\t" -- "addl %3, %1 \n\t" -- "subl %4, %2 \n\t" -- "cmpl %4, %2 \n\t" -- " jae 1b \n\t" -- : "+r" (from), "+r" (to), "+r" (i) -- : "r" (BLOCK_SIZE), "i" (BLOCK_SIZE/64), "i" (CONFUSION_FACTOR) -- : "%eax", "%ebx" -- ); --#endif -- -- for(; i>0; i--) -- { -- __asm__ __volatile__ ( --#ifndef HAVE_MMX1 -- PREFETCH" 320(%0)\n" --#endif -- "movq (%0), %%mm0\n" -- "movq 8(%0), %%mm1\n" -- "movq 16(%0), %%mm2\n" -- "movq 24(%0), %%mm3\n" -- "movq 32(%0), %%mm4\n" -- "movq 40(%0), %%mm5\n" -- "movq 48(%0), %%mm6\n" -- "movq 56(%0), %%mm7\n" -- MOVNTQ" %%mm0, (%1)\n" -- MOVNTQ" %%mm1, 8(%1)\n" -- MOVNTQ" %%mm2, 16(%1)\n" -- MOVNTQ" %%mm3, 24(%1)\n" -- MOVNTQ" %%mm4, 32(%1)\n" -- MOVNTQ" %%mm5, 40(%1)\n" -- MOVNTQ" %%mm6, 48(%1)\n" -- MOVNTQ" %%mm7, 56(%1)\n" -- :: "r" (from), "r" (to) : "memory"); -- from = (const void *) (((const unsigned char *)from)+64); -- to = (void *) (((unsigned char *)to)+64); -- } -- --#endif /* Have SSE */ --#ifdef HAVE_MMX2 -- /* since movntq is weakly-ordered, a "sfence" -- * is needed to become ordered again. */ -- __asm__ __volatile__ ("sfence":::"memory"); --#endif --#ifndef HAVE_SSE -- /* enables to use FPU */ -- __asm__ __volatile__ (EMMS:::"memory"); --#endif -- } -- /* -- * Now do the tail of the block -- */ -- if(len) small_memcpy(to, from, len); -- return retval; --} -- -- --#endif /* #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX ) */ -- --#endif -diff --git a/xbmc/utils/fastmemcpy.h b/xbmc/utils/fastmemcpy.h -deleted file mode 100644 -index 43f5904..0000000 ---- a/xbmc/utils/fastmemcpy.h -+++ /dev/null -@@ -1,35 +0,0 @@ --/* -- * Copyright (C) 2005-2013 Team XBMC -- * http://xbmc.org -- * -- * This Program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2, or (at your option) -- * any later version. -- * -- * This Program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with XBMC; see the file COPYING. If not, see -- * . -- * -- */ --#pragma once -- --#ifdef __cplusplus --extern "C" { --#endif -- --#if !defined(TARGET_WINDOWS) && !defined(__ppc__) && !defined(__powerpc__) && !defined(__mips__) && !defined(TARGET_ANDROID) && !defined(TARGET_DARWIN_IOS) --void * fast_memcpy(void * to, const void * from, size_t len); --//#define fast_memcpy memcpy --#else --#define fast_memcpy memcpy --#endif -- --#ifdef __cplusplus --} --#endif -diff --git a/xbmc/utils/test/Makefile b/xbmc/utils/test/Makefile -index 8fa0526..3a467ad 100644 ---- a/xbmc/utils/test/Makefile -+++ b/xbmc/utils/test/Makefile -@@ -11,7 +11,6 @@ SRCS= \ - TestCryptThreading.cpp \ - TestDatabaseUtils.cpp \ - TestEndianSwap.cpp \ -- Testfastmemcpy.cpp \ - TestFileOperationJob.cpp \ - TestFileUtils.cpp \ - Testfstrcmp.cpp \ -diff --git a/xbmc/utils/test/Testfastmemcpy.cpp b/xbmc/utils/test/Testfastmemcpy.cpp -deleted file mode 100644 -index 93a9bb0..0000000 ---- a/xbmc/utils/test/Testfastmemcpy.cpp -+++ /dev/null -@@ -1,39 +0,0 @@ --/* -- * Copyright (C) 2005-2013 Team XBMC -- * http://xbmc.org -- * -- * This Program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2, or (at your option) -- * any later version. -- * -- * This Program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with XBMC; see the file COPYING. If not, see -- * . -- * -- */ -- --#include // TODO: This should go in fastmemcpy.h instead. --#include "utils/fastmemcpy.h" -- --#include "gtest/gtest.h" -- --static const char refdata[] = "\x01\x02\x03\x04\x05\x06\x07\x08" -- "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" -- "\x11\x12\x13\x14\x15\x16\x17\x18" -- "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" -- "\x21\x22\x23\x24\x25\x26\x27\x28" -- "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"; -- --TEST(Testfastmemcpy, General) --{ -- char vardata[sizeof(refdata)]; -- memset(vardata, 0, sizeof(vardata)); -- EXPECT_NE(nullptr, fast_memcpy(vardata, refdata, sizeof(refdata))); -- EXPECT_EQ(0, memcmp(refdata, vardata, sizeof(refdata))); --} From e02cfe25fbb35a5a5b140410f2c313a58b793971 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Fri, 26 Jun 2015 21:10:58 +0300 Subject: [PATCH 25/29] binary-addons: bump pvr.hts, pvr.vbox, pvr.wmc --- packages/mediacenter/kodi-binary-addons/pvr.hts/package.mk | 2 +- packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk | 2 +- packages/mediacenter/kodi-binary-addons/pvr.wmc/package.mk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/mediacenter/kodi-binary-addons/pvr.hts/package.mk b/packages/mediacenter/kodi-binary-addons/pvr.hts/package.mk index 61c3810ca1..2bfadbf50d 100644 --- a/packages/mediacenter/kodi-binary-addons/pvr.hts/package.mk +++ b/packages/mediacenter/kodi-binary-addons/pvr.hts/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="pvr.hts" -PKG_VERSION="98d93e7" +PKG_VERSION="cd7ca22" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk b/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk index 9c06ca67a6..0bdbd20959 100644 --- a/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk +++ b/packages/mediacenter/kodi-binary-addons/pvr.vbox/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="pvr.vbox" -PKG_VERSION="b8dff38" +PKG_VERSION="729feff" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/kodi-binary-addons/pvr.wmc/package.mk b/packages/mediacenter/kodi-binary-addons/pvr.wmc/package.mk index 3b4e96c9af..5c6a3e1c65 100644 --- a/packages/mediacenter/kodi-binary-addons/pvr.wmc/package.mk +++ b/packages/mediacenter/kodi-binary-addons/pvr.wmc/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="pvr.wmc" -PKG_VERSION="295b216" +PKG_VERSION="c04a2b6" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 9cc3cc7e00bbf958a2d44adbaa21a413f979eb8b Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 28 Jun 2015 13:55:19 +0200 Subject: [PATCH 26/29] bcm2835-driver: update to bcm2835-driver-df32073 Signed-off-by: Stephan Raue --- packages/graphics/bcm2835-driver/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphics/bcm2835-driver/package.mk b/packages/graphics/bcm2835-driver/package.mk index 6af9e03f5a..083126b787 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="8b9d7b8" +PKG_VERSION="df32073" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="nonfree" From 2daecc35b1d46cb8a4706cfd093033583a773478 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 28 Jun 2015 13:55:41 +0200 Subject: [PATCH 27/29] bcm2835-bootloader: update to bcm2835-bootloader-df32073 Signed-off-by: Stephan Raue --- packages/tools/bcm2835-bootloader/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tools/bcm2835-bootloader/package.mk b/packages/tools/bcm2835-bootloader/package.mk index 9b2a3383eb..96258cb564 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="8b9d7b8" +PKG_VERSION="df32073" PKG_REV="1" PKG_ARCH="arm" PKG_LICENSE="nonfree" From 863604e24143bfc2b344026fe65ec1b5aeac8c63 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 28 Jun 2015 13:56:10 +0200 Subject: [PATCH 28/29] projects/RPi*/patches/linux: update RPi support patches Signed-off-by: Stephan Raue --- .../patches/linux/linux-01-RPi_support.patch | 2453 +++++++++++++++-- .../patches/linux/linux-01-RPi_support.patch | 2453 +++++++++++++++-- 2 files changed, 4382 insertions(+), 524 deletions(-) diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index 0008aa8b30..a35c13d26b 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 8e2bdce040b3459de0954cb2f212dea47549131c Mon Sep 17 00:00:00 2001 +From e9ee97a62574359de01411f0c74e23856e359952 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 01/77] Main bcm2708/bcm2709 linux port +Subject: [PATCH 01/85] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -310,7 +310,7 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c new file mode 100644 -index 0000000..cd252fa +index 0000000..4868cd37 --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -0,0 +1,304 @@ @@ -611,7 +611,7 @@ index 0000000..cd252fa + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + armctrl_pm_register(base, irq_start, resume_sources); @@ -653,7 +653,7 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 -index 0000000..d6659b0 +index 0000000..a209c58 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -0,0 +1,622 @@ @@ -1164,7 +1164,7 @@ index 0000000..d6659b0 + +static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, +}; + @@ -3577,7 +3577,7 @@ index 0000000..e33265d +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c new file mode 100644 -index 0000000..19d0601 +index 0000000..d135620 --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -0,0 +1,801 @@ @@ -4120,7 +4120,7 @@ index 0000000..19d0601 + +static struct irqaction bcm2709_timer_irq = { + .name = "BCM2709 Timer Tick", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2709_timer_interrupt, +}; + @@ -7002,10 +7002,10 @@ index b5bedae..b0258e8 100644 mmc_pm_flag_t pm_caps; /* supported pm features */ -From aa090a771afa15310eb10d3209c190441f3ecefd Mon Sep 17 00:00:00 2001 +From 081ebd4ba394a354c03f7800b8d14519f165a0f9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Jun 2015 23:48:09 +0100 -Subject: [PATCH 02/77] power: Add power driver +Subject: [PATCH 02/85] power: Add power driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -7362,10 +7362,10 @@ index 0000000..bf22b26 + +#endif -From 9409d45ef7d82d4f0677ea1a16bb6e87d41ed8de Mon Sep 17 00:00:00 2001 +From ddd21104179e4df6cf77762b1a7f4dabe65cc808 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 Oct 2014 18:50:05 +0100 -Subject: [PATCH 03/77] Add bcm2708_gpio driver +Subject: [PATCH 03/85] Add bcm2708_gpio driver Signed-off-by: popcornmix @@ -7439,7 +7439,7 @@ index e7d5a29..5120994 100644 obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d6659b0..c606853 100644 +index a209c58..6c1c616 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -298,6 +298,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -7476,7 +7476,7 @@ index d6659b0..c606853 100644 int ret; diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c new file mode 100644 -index 0000000..c1e9254 +index 0000000..e33265d --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c @@ -0,0 +1,426 @@ @@ -7788,7 +7788,7 @@ index 0000000..c1e9254 + +static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, +}; + @@ -7930,7 +7930,7 @@ index 0000000..7965a97 + +#endif diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 19d0601..6060a0d 100644 +index d135620..b173422 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -329,6 +329,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -7995,10 +7995,10 @@ index 0000000..fb69624 + +#endif -From 4b9ec02bb6738a9c29f6308c55cbcab58c2c88a3 Mon Sep 17 00:00:00 2001 +From 8957f79b301a70ab625baa2f9a4c613f871c3f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 19:11:03 +0200 -Subject: [PATCH 04/77] mailbox: bcm2708: Add bcm2708-vcio +Subject: [PATCH 04/85] mailbox: bcm2708: Add bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -8629,10 +8629,10 @@ index 0000000..cc284ed + +#endif -From c921ec1cd21e8a8eb4e453834a205e9da5dff30a Mon Sep 17 00:00:00 2001 +From c1a8c5708161961f248f228d25da578e90fe127f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 05/77] Add dwc_otg driver +Subject: [PATCH 05/85] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -9253,7 +9253,7 @@ index 8dd26e1..eef4847 100644 + mov pc, r8 +ENDPROC(__FIQ_Branch) diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index cd252fa..74bacb3 100644 +index 4868cd37..0429225 100644 --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -54,8 +54,12 @@ static void armctrl_mask_irq(struct irq_data *d) @@ -9297,7 +9297,7 @@ index cd252fa..74bacb3 100644 return 0; } diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c606853..4455f34 100644 +index 6c1c616..1735b72 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -254,12 +254,23 @@ static struct resource bcm2708_usb_resources[] = { @@ -69906,10 +69906,10 @@ index 0000000..cdc9963 +test_main(); +0; -From 560486db654a651cebb107628426d1705ef4cc20 Mon Sep 17 00:00:00 2001 +From 2aced0ae5562b3dc60806a3ba2799af134732bdb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 06/77] bcm2708 watchdog driver +Subject: [PATCH 06/85] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -70346,10 +70346,10 @@ index 0000000..8a27d68 +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); -From 7014dbd386a6ce510bd6b9fa3a3fcfc2bd89d237 Mon Sep 17 00:00:00 2001 +From 4a64377d42fac96be299fd210b0eb0bc3ba159b2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 07/77] bcm2708 framebuffer driver +Subject: [PATCH 07/85] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73788,10 +73788,10 @@ index 3c14e43..7626beb6a 100644 +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 5efe288a95d60bd10a162be79442d04b6f1d4079 Mon Sep 17 00:00:00 2001 +From b04b39dfe4cb2a287062d3b81287d9a9bf80e91a Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 08/77] dmaengine: Add support for BCM2708 +Subject: [PATCH 08/85] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73907,7 +73907,7 @@ Without this field set properly we get playback issues with I2S cards. create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 4455f34..6b0b6c4 100644 +index 1735b72..1622300 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -234,6 +234,73 @@ static struct amba_device *amba_devs[] __initdata = { @@ -73993,7 +73993,7 @@ index 4455f34..6b0b6c4 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 6060a0d..86ebfbe 100644 +index b173422..fee17e2 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -244,6 +244,73 @@ static struct amba_device *amba_devs[] __initdata = { @@ -75559,10 +75559,10 @@ index 0000000..2310e34 + +#endif /* _PLAT_BCM2708_DMA_H */ -From be30ad8849aa9fd6ffbe6f8198a5af4bb62c465f Mon Sep 17 00:00:00 2001 +From 34e4aa2e25b49261e2aa9d17a1ce767a3dfb90cf Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 09/77] MMC: added alternative MMC driver +Subject: [PATCH 09/85] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75637,7 +75637,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6b0b6c4..5b10802 100644 +index 1622300..6257407 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -401,6 +401,34 @@ static struct platform_device bcm2708_gpio_device = { @@ -75686,7 +75686,7 @@ index 6b0b6c4..5b10802 100644 bcm2708_init_uart1(); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 86ebfbe..54c5444 100644 +index fee17e2..07750ed 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -421,6 +421,34 @@ static struct platform_device bcm2708_gpio_device = { @@ -77378,10 +77378,10 @@ index 0000000..b7c4883 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 81cff325dce6ba8765e23e542a219d3c9103a70b Mon Sep 17 00:00:00 2001 +From f1a7eefd17fbaf9335a5fdf6215d319b4042bb55 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 10/77] Adding bcm2835-sdhost driver, and an overlay to enable +Subject: [PATCH 10/85] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -79151,10 +79151,10 @@ index 0000000..eef8a24 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From 34fb9ba0190b9f9e18e6c136c64af8dcea23376d Mon Sep 17 00:00:00 2001 +From effb9e4dd94cc200500fb22061ede69047cceea7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 11/77] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 11/85] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix @@ -80479,10 +80479,10 @@ index 0000000..5325832 + +#endif /* VC_CMA_H */ -From 0e6896e85bf10d584b555ecae4b55f066a774b54 Mon Sep 17 00:00:00 2001 +From d83761e1a337d8eee9e9a196e23ceeefe51fff1e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 12/77] bcm2708: alsa sound driver +Subject: [PATCH 12/85] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -80539,7 +80539,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5b10802..06271df 100644 +index 6257407..df32241 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -429,6 +429,57 @@ struct platform_device bcm2835_emmc_device = { @@ -80610,7 +80610,7 @@ index 5b10802..06271df 100644 if (!use_dt) { for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 54c5444..0f875ff 100644 +index 07750ed..62c95cb 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -449,6 +449,57 @@ struct platform_device bcm2835_emmc_device = { @@ -83324,10 +83324,10 @@ index 0000000..af3e6eb + +#endif // _VC_AUDIO_DEFS_H_ -From b2b5ab24c875e79e1fbb55ae76dc5a914fe301d0 Mon Sep 17 00:00:00 2001 +From 53e9a31fe01ae9460b2361ec93a54bac888d8f5f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 13/77] bcm2708 vchiq driver +Subject: [PATCH 13/85] bcm2708 vchiq driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -83493,7 +83493,7 @@ vchiq: Change logging level for inbound data create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 06271df..86011af 100644 +index df32241..ecf0524 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -376,6 +376,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -83550,7 +83550,7 @@ index 2e7e1bb..69674e9 100644 /* diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 0f875ff..bc1ee1c 100644 +index 62c95cb..de9feaa 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -396,6 +396,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -96581,10 +96581,10 @@ index 0000000..b6bfa21 + return vchiq_build_time; +} -From 6290b45c0e5fa71d2131718d1b5770e7849aedeb Mon Sep 17 00:00:00 2001 +From 3f8c3cd61c11d730699b14ee1d64db95215487e8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 14/77] vc_mem: Add vc_mem driver +Subject: [PATCH 14/85] vc_mem: Add vc_mem driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -97590,10 +97590,10 @@ index 0000000..20a4753 + +#endif /* _VC_MEM_H */ -From e9ebded52208b6164753a82d268cd80e833e2737 Mon Sep 17 00:00:00 2001 +From 138483d8fb3cbfcad83b0c450e3c3eb2fca5a8de Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 15/77] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 15/85] vcsm: VideoCore shared memory service for BCM2835 Add experimental support for the VideoCore shared memory service. This allows user processes to allocate memory from VideoCore's @@ -102003,10 +102003,10 @@ index 0000000..0bfb42e +MODULE_DESCRIPTION("VideoCore SharedMemory Driver"); +MODULE_LICENSE("GPL v2"); -From 7f769de038003dcf3f6eff180e2e295888789dc2 Mon Sep 17 00:00:00 2001 +From 3b4d6cc19851307c0426fe31be9627558bb1b2cf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 16/77] Add hwrng (hardware random number generator) driver +Subject: [PATCH 16/85] Add hwrng (hardware random number generator) driver --- drivers/char/hw_random/Kconfig | 13 +++- @@ -102183,10 +102183,10 @@ index 0000000..340f004 +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); -From 68990b28334ea63cdc56bfe9663025dade9d7822 Mon Sep 17 00:00:00 2001 +From 8312a7efc6b5c8fe996e41f62adf6e9c71f7a5f8 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 17/77] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 17/85] 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 @@ -103039,10 +103039,10 @@ index 0000000..24563ec +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -From b359d4ff9144f1ee3f333eee7b49bab1c6d92c1f Mon Sep 17 00:00:00 2001 +From 4905ceea875bf96a9dbf4989347ed1d5e4e3875b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 18/77] Add cpufreq driver +Subject: [PATCH 18/85] Add cpufreq driver Signed-off-by: popcornmix --- @@ -103315,10 +103315,10 @@ index 0000000..6735da9 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 37e551cc949ea14042539b089e08df475bab0f59 Mon Sep 17 00:00:00 2001 +From 50ef992dbbc2e7e1c1a87a61b540c0b84f7cb3ee Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 19/77] Added hwmon/thermal driver for reporting core +Subject: [PATCH 19/85] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -103341,7 +103341,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 86011af..f2d9b03 100644 +index ecf0524..978aaff 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -505,6 +505,10 @@ static struct platform_device bcm2708_alsa_devices[] = { @@ -103365,7 +103365,7 @@ index 86011af..f2d9b03 100644 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index bc1ee1c..9631bdb 100644 +index de9feaa..0e5c8e3 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -525,6 +525,10 @@ static struct platform_device bcm2708_alsa_devices[] = { @@ -103615,10 +103615,10 @@ index 0000000..3bc80f1 + +module_platform_driver(bcm2835_thermal_driver); -From 4d5da3fa21e1d94e38644bf9a5493bb677854e42 Mon Sep 17 00:00:00 2001 +From 0e6c5417c62642c7481e57ce937007277fe31cfd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:41:33 +0100 -Subject: [PATCH 20/77] Add Chris Boot's spi driver. +Subject: [PATCH 20/85] Add Chris Boot's spi driver. spi: bcm2708: add device tree support @@ -103679,7 +103679,7 @@ index 4cbda0c..68e3706 100644 + Binds spidev driver to the SPI0 master endmenu diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f2d9b03..e3aa6fc 100644 +index 978aaff..31ad9da 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -34,6 +34,7 @@ @@ -103764,7 +103764,7 @@ index f2d9b03..e3aa6fc 100644 static void timer_set_mode(enum clock_event_mode mode, diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9631bdb..5fb99b6 100644 +index 0e5c8e3..6874633 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -34,6 +34,7 @@ @@ -104530,10 +104530,10 @@ index 0000000..041b5e2 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 75d6625177ee7e4746baf70b60380069d58231ba Mon Sep 17 00:00:00 2001 +From 68bec2f411f5f7ea1720f555cadc7a5c6c214934 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 21/77] Add Chris Boot's i2c driver +Subject: [PATCH 21/85] Add Chris Boot's i2c driver i2c-bcm2708: fixed baudrate @@ -104594,7 +104594,7 @@ i2c-bcm2708: When using DT, leave the GPIO setup to pinctrl create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e3aa6fc..efb3544 100644 +index 31ad9da..26be516 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -83,6 +83,7 @@ static unsigned uart_clock = UART0_CLOCK; @@ -104674,7 +104674,7 @@ index e3aa6fc..efb3544 100644 +module_param(vc_i2c_override, bool, 0644); +MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 5fb99b6..8017c50 100644 +index 6874633..50843df 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -85,6 +85,7 @@ static unsigned uart_clock = UART0_CLOCK; @@ -105334,10 +105334,10 @@ index 0000000..8773203 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 87711afd62feac0850e063b279057c91fe0aabbf Mon Sep 17 00:00:00 2001 +From f039d3ed041c0fd3267b149ef476638142535ef3 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 22/77] bcm2835: add v4l2 camera device +Subject: [PATCH 22/85] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -112664,10 +112664,10 @@ index 0000000..9d1d11e + +#endif /* MMAL_VCHIQ_H */ -From 0ecc87e37d9107eb533346a4a482bbf78920d16c Mon Sep 17 00:00:00 2001 +From 35af37046308a29d529e83d908c1fea9cd01a8a2 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 23 Jan 2015 14:48:55 +0000 -Subject: [PATCH 23/77] scripts/dtc: Update to upstream version with overlay +Subject: [PATCH 23/85] scripts/dtc: Update to upstream version with overlay patches --- @@ -117880,10 +117880,10 @@ index 54d4e904..d644002 100644 -#define DTC_VERSION "DTC 1.4.0-dirty" +#define DTC_VERSION "DTC 1.4.1-g36c70742" -From 4cccd63c16e3ef4e2a35144e2806d1d1c56bc381 Mon Sep 17 00:00:00 2001 +From 7b42e6d4640654b00e46f0b14a2f4d4f9979610e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 24/77] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 24/85] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -118368,10 +118368,10 @@ index 0000000..3dff948 + return (($val eq 'y') || ($val eq '1')); +} -From 780d72c0e43679ff58f9f3f005ef17a5fa79ee9f Mon Sep 17 00:00:00 2001 +From 23bd48a5f3cae21a2074ef421a675dfba54866de Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 25/77] fdt: Add support for the CONFIG_CMDLINE_EXTEND option +Subject: [PATCH 25/85] fdt: Add support for the CONFIG_CMDLINE_EXTEND option --- drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- @@ -118426,10 +118426,10 @@ index cde35c5d01..dd7fbfe 100644 pr_debug("Command line is: %s\n", (char*)data); -From 7ff1afbc6732a16d87c5640be8fec1de73a39770 Mon Sep 17 00:00:00 2001 +From 4c4001e3bc03206e4d87273ac410a719c7a128b4 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 26/77] BCM2708: Add core Device Tree support +Subject: [PATCH 26/85] BCM2708: Add core Device Tree support Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -122306,10 +122306,10 @@ index 0000000..66a98f6 + }; +}; -From 4bd17cf8893beb8fb36fe6e321abfe2bc091eb17 Mon Sep 17 00:00:00 2001 +From 5cbd38e967d11494dbf7d401bfcce0240a176f1f Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 27/77] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 27/85] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -122402,10 +122402,10 @@ index fb795c3..fa72af0 100644 #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -From 54459bf0dcbd9019a1bc98cdc77a5c37811c1be5 Mon Sep 17 00:00:00 2001 +From 9907bcbcbae0e355d82cbc29e4f9667fb6fadfac Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 30/77] Speed up console framebuffer imageblit function +Subject: [PATCH 30/85] 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 @@ -122614,10 +122614,10 @@ index a2bb276..436494f 100644 start_index, pitch_index); } else -From b78abfc78e582f82fda5e69816eaa97b1097c853 Mon Sep 17 00:00:00 2001 +From c50184c27d8c47aa92288d11c79ccbc193f91a74 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 31/77] Allow mac address to be set in smsc95xx +Subject: [PATCH 31/85] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -122708,10 +122708,10 @@ index 26423ad..e29a323 100644 if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, dev->net->dev_addr) == 0) { -From 468a5ebe451a5e3bc693fdbd67173f2fadb7d217 Mon Sep 17 00:00:00 2001 +From b579f8fd561c7347d6354d3f7fc6880ac6b49e7f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 32/77] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 32/85] 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 @@ -122741,7 +122741,7 @@ w1-gpio: Sort out the pullup/parasitic power tangle 7 files changed, 157 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index efb3544..c7b4b61 100644 +index 26be516..55d2889 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -36,6 +36,7 @@ @@ -122814,7 +122814,7 @@ index efb3544..c7b4b61 100644 module_param(vc_i2c_override, bool, 0644); MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8017c50..03e208b 100644 +index 50843df..0a5e4188 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -36,6 +36,7 @@ @@ -123109,10 +123109,10 @@ index d58594a..feae942 100644 unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From 00d8013737c9e736f70e04e07b761517559e495e Mon Sep 17 00:00:00 2001 +From 8828223a011c97121c5824e4a9056ebfdb178612 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 34/77] config: Enable CONFIG_MEMCG, but leave it disabled (due +Subject: [PATCH 34/85] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -123167,10 +123167,10 @@ index a04225d..a2ef8af 100644 /** -From 5e192d7296061c5d70da39b3fbd1eeedef467923 Mon Sep 17 00:00:00 2001 +From 9028029fe919c229779c848fd2a645bf02d2d959 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:33:38 +0100 -Subject: [PATCH 35/77] ASoC: Add support for BCM2708 +Subject: [PATCH 35/85] ASoC: Add support for BCM2708 This driver adds support for digital audio (I2S) for the BCM2708 SoC that is used by the @@ -124313,10 +124313,10 @@ index 0000000..6fdcbc1 + +#endif -From 355253cae3f2e9200926bfeb8d21646600d0768e Mon Sep 17 00:00:00 2001 +From 2cd4bdd8e03b8a9ce11d39741d5670d10b58f13e Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 36/77] ASoC: Add support for PCM5102A codec +Subject: [PATCH 36/85] ASoC: Add support for PCM5102A codec Some definitions to support the PCM5102A codec by Texas Instruments. @@ -124441,10 +124441,10 @@ index 0000000..126f1e9 +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From 49e137bd21361ad8f4439f35956ceab424013411 Mon Sep 17 00:00:00 2001 +From 214e3f42b42cc6512664e15c2e6d48c44397ff30 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:04:54 +0100 -Subject: [PATCH 37/77] BCM2708: Add I2S support to board file +Subject: [PATCH 37/85] BCM2708: Add I2S support to board file Adds the required initializations for I2S to the board file of mach-bcm2708. @@ -124464,7 +124464,7 @@ See: #1004 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c7b4b61..dc57983 100644 +index 55d2889..01f2de7 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -616,6 +616,28 @@ static struct platform_device bcm2835_thermal_device = { @@ -124533,10 +124533,10 @@ index a3b65dc..a515992 100644 for (i = 0; i <= 1; i++) { void __iomem *base; -From 5786483930fcb7863012d8bb81d1f73a67b258da Mon Sep 17 00:00:00 2001 +From 7cf3e108eda83b02d6dcf336c5e1842b36fab753 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 38/77] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 38/85] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -124685,10 +124685,10 @@ index 0000000..4b70b45 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 47d7a2a48fd4b2da2f9400de4307febe755b2ef2 Mon Sep 17 00:00:00 2001 +From 895fd13e0cf6dc5febf489837d068825db70d7ac Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:21:34 +0100 -Subject: [PATCH 39/77] BCM2708: Add HifiBerry DAC to board file +Subject: [PATCH 39/85] BCM2708: Add HifiBerry DAC to board file This adds the initalization of the HifiBerry DAC to the mach-bcm2708 board file. @@ -124699,7 +124699,7 @@ Signed-off-by: Florian Meier 1 file changed, 19 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index dc57983..ef7c48d 100644 +index 01f2de7..1d9b788 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -638,6 +638,20 @@ static struct platform_device bcm2708_i2s_device = { @@ -124736,10 +124736,10 @@ index dc57983..ef7c48d 100644 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; -From 403dc5c76505dd5813174532b2f032e52cbe06b8 Mon Sep 17 00:00:00 2001 +From e01a75a2784a659fbd297dc849a2e25ae120e35c Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 6 Dec 2013 20:50:28 +0100 -Subject: [PATCH 40/77] ASoC: BCM2708: Add support for RPi-DAC +Subject: [PATCH 40/85] ASoC: BCM2708: Add support for RPi-DAC This adds a machine driver for the RPi-DAC. @@ -124757,7 +124757,7 @@ Signed-off-by: Florian Meier create mode 100644 sound/soc/codecs/pcm1794a.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index ef7c48d..be27073 100644 +index 1d9b788..6d53beb 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125034,10 +125034,10 @@ index 0000000..b4eaa44 +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From 0418e9bd3eab8e21b5d69ed0b7899dd5a80263f1 Mon Sep 17 00:00:00 2001 +From 4250d743113025b72b841b0b801aee698d8761ef Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 41/77] ASoC: wm8804: Implement MCLK configuration options, add +Subject: [PATCH 41/85] 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 @@ -125077,10 +125077,10 @@ index 1e403f6..d4efa85 100644 #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ -From 82c2f5a297701240bf5a77611d2d93c041497246 Mon Sep 17 00:00:00 2001 +From bb771a22197d65ccab827fe36a8699d18b961693 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 42/77] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 42/85] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -125345,10 +125345,10 @@ index 0000000..92e9e46 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From df14e52cd5e411324c58e28ec158f503d4905dbb Mon Sep 17 00:00:00 2001 +From 6081cb2ed879b4e99cd91a36331460bf6ec2e3f0 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Thu, 16 Jan 2014 07:26:08 +0100 -Subject: [PATCH 43/77] BCM2708: Added support for HiFiBerry Digi board Board +Subject: [PATCH 43/85] BCM2708: Added support for HiFiBerry Digi board Board initalization by I2C Signed-off-by: Daniel Matuschek @@ -125357,7 +125357,7 @@ Signed-off-by: Daniel Matuschek 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index be27073..2a33663 100644 +index 6d53beb..a062d7f 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,21 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125395,10 +125395,10 @@ index be27073..2a33663 100644 bcm_register_device_dt(&snd_rpi_dac_device); bcm_register_device_dt(&snd_pcm1794a_codec_device); -From d8de9644604c68b7148b023608d70d8ac3bf466f Mon Sep 17 00:00:00 2001 +From 6d26e73e4afc0f00e514498776ff0e24d595f919 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Thu, 16 Jan 2014 07:36:35 +0100 -Subject: [PATCH 44/77] ASoC: wm8804: Set idle_bias_off to false Idle bias has +Subject: [PATCH 44/85] ASoC: wm8804: Set idle_bias_off to false Idle bias has been change to remove warning on driver startup Signed-off-by: Daniel Matuschek @@ -125420,10 +125420,10 @@ index d4efa85..f3f26a2 100644 .dapm_widgets = wm8804_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), -From 40f01186460630fa704c88adbefbc347e5e402e4 Mon Sep 17 00:00:00 2001 +From 76c18d6844de1ab292a34baf6c96566ba05db024 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 45/77] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 45/85] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -125440,7 +125440,7 @@ limit of 0dB for this control. create mode 100644 sound/soc/bcm/iqaudio-dac.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 2a33663..957504e 100644 +index a062d7f..a51a6168 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -681,6 +681,22 @@ static struct platform_device snd_pcm1794a_codec_device = { @@ -125631,10 +125631,10 @@ index 0000000..aff7377 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From 5d1014e6dfa91f7f4b07851eefaa0a8bc544fda8 Mon Sep 17 00:00:00 2001 +From 712b1f5ed46d64ace42306b175e84247ad466a86 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 46/77] vmstat: Workaround for issue where dirty page count +Subject: [PATCH 46/85] vmstat: Workaround for issue where dirty page count goes negative See: @@ -125661,10 +125661,10 @@ index 82e7db7..f87d16d 100644 static inline void __inc_zone_page_state(struct page *page, -From 462ac627ee409f190f5519727c80942afafd0d6d Mon Sep 17 00:00:00 2001 +From 8fe8c0d0126e286164be182add69b996012753b6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 47/77] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 47/85] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -125700,10 +125700,10 @@ index bfbe1be..a738b25 100644 ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From 6a68d9854eed6f1c5741aff8466cb5877deecd54 Mon Sep 17 00:00:00 2001 +From db5d9cfda38672c42a52574924297223f44ab568 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 48/77] Added support for HiFiBerry DAC+ +Subject: [PATCH 48/85] 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. @@ -125716,7 +125716,7 @@ a different codec chip (PCM5122), therefore a new driver is necessary. create mode 100644 sound/soc/bcm/hifiberry_dacplus.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 957504e..90459b8 100644 +index a51a6168..d421a89 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125914,10 +125914,10 @@ index 0000000..c63387b +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); +MODULE_LICENSE("GPL v2"); -From 1ca3777a5f3e17847136937e1bab1717281c73ca Mon Sep 17 00:00:00 2001 +From f929e0ea9b902ca56a57439ad326a7fe1bc190d2 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 49/77] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 49/85] 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. @@ -125947,7 +125947,7 @@ Some code to load the driver based on device-tree-overlays was missing. This is create mode 100644 sound/soc/codecs/tas5713.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 90459b8..785cf1a 100644 +index d421a89..363b9c5 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -681,6 +681,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { @@ -126786,10 +126786,10 @@ index 0000000..8f019e0 + +#endif /* _TAS5713_H */ -From 06c9b132b1340b495048f8814be13fe71b5cd77e Mon Sep 17 00:00:00 2001 +From 0d10a0439bbde5d1bf74427cb93a55a29ea7ec12 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Apr 2015 19:14:18 +0100 -Subject: [PATCH 50/77] bcm2708: Allow option card devices to be configured via +Subject: [PATCH 50/85] bcm2708: Allow option card devices to be configured via DT If the kernel is built with Device Tree support, and if a DT blob @@ -126814,10 +126814,10 @@ index 03fa1cb..c816526 100644 static struct platform_driver bcm2835_i2s_driver = { .probe = bcm2835_i2s_probe, -From a9fff3c9005e6658977bd5e7df92114e70e1f813 Mon Sep 17 00:00:00 2001 +From 8eaeacdeca7966b710fbdefad07bd3f0de14447c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 18:45:39 +0100 -Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards +Subject: [PATCH 51/85] Adding Device Tree support for some RPi audio cards --- arch/arm/mach-bcm2709/bcm2709.c | 143 ++++++++++++++++++++++++++++++++++++++ @@ -126829,7 +126829,7 @@ Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards 6 files changed, 232 insertions(+) diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 03e208b..2ae79d9 100644 +index 0a5e4188..57e1f3d 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -636,6 +636,115 @@ static struct platform_device bcm2835_thermal_device = { @@ -127180,10 +127180,10 @@ index 126f1e9..7c6598e 100644 }; -From 9518bd237c4fb516a0ec78f7ec81e5784f8425e0 Mon Sep 17 00:00:00 2001 +From 7dfce43c57cc203535e6098fcc1e8977d85ddeac Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Wed, 29 Oct 2014 23:30:30 -0700 -Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used +Subject: [PATCH 52/85] Added support to reserve/enable a GPIO pin to be used from pps-gpio module (LinuxPPS). Enable PPS modules in default config for RPi. @@ -127193,7 +127193,7 @@ Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used 2 files changed, 54 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 785cf1a..e42f5a5 100644 +index 363b9c5..74ec578 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -37,6 +37,7 @@ @@ -127256,7 +127256,7 @@ index 785cf1a..e42f5a5 100644 +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 2ae79d9..95223ff 100644 +index 57e1f3d..721559b 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -37,6 +37,7 @@ @@ -127319,10 +127319,10 @@ index 2ae79d9..95223ff 100644 +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -From 6831eded602a01774036cb24d3195dbbd51f9135 Mon Sep 17 00:00:00 2001 +From a3936496fcb450e52716292427b60570447b6b03 Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 53/77] Update ds1307 driver for device-tree support +Subject: [PATCH 53/85] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -127349,10 +127349,10 @@ index 4ffabb3..c6789a7 100644 .driver = { .name = "rtc-ds1307", -From 47ca2482bc03a888435d35139cd2f5989354ee1b Mon Sep 17 00:00:00 2001 +From eed1565f9cb449204057486a48c39f917c269fa1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 54/77] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 54/85] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -127463,10 +127463,10 @@ index 0000000..2ca2b98 +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); -From 38c278bba1388423ba1508d0712babb717685530 Mon Sep 17 00:00:00 2001 +From 494f12e28e415f895a337fcfcfe45cd530c1cc99 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Jun 2014 17:19:27 +0100 -Subject: [PATCH 55/77] bcm2709: Simplify and strip down IRQ handler +Subject: [PATCH 55/85] bcm2709: Simplify and strip down IRQ handler --- arch/arm/include/asm/entry-macro-multi.S | 2 + @@ -127685,10 +127685,10 @@ index d08591b..08d184c 100644 +1: get_irqnr_and_base r0, r2, r6, lr + .endm -From a69146643bae1215ab2860b9646f0f380bd3c50f Mon Sep 17 00:00:00 2001 +From 3e2b399180b8f5a0090134ba1889443945a13cf6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Feb 2015 11:17:53 +0000 -Subject: [PATCH 56/77] Fix LED "input" trigger implementation for 3.19 +Subject: [PATCH 56/85] Fix LED "input" trigger implementation for 3.19 --- drivers/leds/leds-gpio.c | 10 +++++++++- @@ -127775,10 +127775,10 @@ index 9a2b000..60accc5 100644 /* Set LED brightness level */ /* Must not sleep, use a workqueue if needed */ -From d8f6c527b14c125e58173e8bd0e7c6c59bab4919 Mon Sep 17 00:00:00 2001 +From 5c958120f03edcedf40ff2d07b825229d348d26b Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 57/77] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 57/85] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -127800,10 +127800,10 @@ index 8d908e3..7a1900d 100644 .can_sleep = false, }; -From bf8c97c74733237b219a22da649cb6cb7029615d Mon Sep 17 00:00:00 2001 +From 784bb9af1427a9b17cd6894cff2dc3c2eb8c4735 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 4 Feb 2015 10:02:24 +0000 -Subject: [PATCH 58/77] pinctrl-bcm2835: bcm2835_gpio_direction_output must set +Subject: [PATCH 58/85] pinctrl-bcm2835: bcm2835_gpio_direction_output must set the value --- @@ -127831,10 +127831,10 @@ index 7a1900d..62f85aa 100644 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -From 1262602778ac5adbe798e7ace41b22262a578fcf Mon Sep 17 00:00:00 2001 +From c885a17c2aee5d4f00b2dc950bcdadd3ed7bd7cb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 59/77] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 +Subject: [PATCH 59/85] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -127980,10 +127980,10 @@ index 62f85aa..c7cf266 100644 }, }; -From fd7e740e1c83bd550444192a8beff54ea5291c50 Mon Sep 17 00:00:00 2001 +From ead5cb2483b2fb0943121dfb69786e6ec1c20ced Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 60/77] pinctrl-bcm2835: Only request the interrupts listed in +Subject: [PATCH 60/85] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -128010,10 +128010,10 @@ index c7cf266..986779a 100644 pc->irq_data[i].irqgroup = i; -From c24fbfc7a5bc3c7cb35f51d0a40ad25b98a8a422 Mon Sep 17 00:00:00 2001 +From 15eff0b34d5eba282dfa1fc0303bb66f08d237ad Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 61/77] enc28j60: Add device tree compatible string and an +Subject: [PATCH 61/85] enc28j60: Add device tree compatible string and an overlay --- @@ -128047,10 +128047,10 @@ index b1b5f66..c6b6e1a 100644 .probe = enc28j60_probe, .remove = enc28j60_remove, -From 331cdec0de30933d5e7839f0e3def9b98d3fa968 Mon Sep 17 00:00:00 2001 +From 4c1fa7e5d19f7f006576def6cdf591c325d9a167 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 62/77] Add driver for rpi-proto +Subject: [PATCH 62/85] 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 @@ -128265,10 +128265,10 @@ index 0000000..c6e45a0 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From 2079392f1bde4f50d8c1ad65c2f7b52a6ff34848 Mon Sep 17 00:00:00 2001 +From 3a796c13d6cf8d6cd51170b34944b18d50f30bba Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Thu, 2 Apr 2015 12:22:55 +0100 -Subject: [PATCH 63/77] Add Device Tree support for RPi-DAC. +Subject: [PATCH 63/85] Add Device Tree support for RPi-DAC. --- sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ @@ -128343,10 +128343,10 @@ index b4eaa44..afe1b41 100644 }; -From 4725644a3f7c09811486c1324f9653e79ecbdcb7 Mon Sep 17 00:00:00 2001 +From 69754b2aaecf3eb2dd3bef6f68d7e7787a9dc6cc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 64/77] config: Add default configs +Subject: [PATCH 64/85] config: Add default configs --- arch/arm/configs/bcm2709_defconfig | 1204 ++++++++++++++++++++++++++++++++++++ @@ -130771,10 +130771,10 @@ index 0000000..6a41231 +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 7de29243d1ac891a526c77e17129d6e2d547361d Mon Sep 17 00:00:00 2001 +From c6ed3e60b55412cdf8e130053f600c05c3e1460a Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 65/77] smsx95xx: fix crimes against truesize +Subject: [PATCH 65/85] 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. @@ -130809,10 +130809,10 @@ index e29a323..aff63dc usbnet_skb_return(dev, ax_skb); } -From 4772a6e4cc3921cb41515b7b0a91ad646d1491aa Mon Sep 17 00:00:00 2001 +From ef3796d3a8cdb18963e2eeb04fa493abca03af14 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 66/77] smsc95xx: Disable turbo mode by default +Subject: [PATCH 66/85] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- @@ -130832,10 +130832,10 @@ index aff63dc..08a8a8c 100755 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From 9d1fbb7b2dbe16c506f54984c361a55d1b2603fb Mon Sep 17 00:00:00 2001 +From 831d4392562d46f0d9a55c755c1363b84832af2a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Apr 2015 19:30:22 +0100 -Subject: [PATCH 67/77] Add blk_pos parameter to mmc multi_io_quirk callback +Subject: [PATCH 67/85] Add blk_pos parameter to mmc multi_io_quirk callback --- drivers/mmc/card/block.c | 1 + @@ -130918,10 +130918,10 @@ index b0258e8..d3cdad9 100644 struct mmc_card; -From d8492b31751e7eda1b9b2c92dd381b5d7df1679d Mon Sep 17 00:00:00 2001 +From a20e01130fd949a90e5e91821edd63581e95cc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 29 Apr 2015 17:24:02 +0200 -Subject: [PATCH 68/77] bcm2835: bcm2835_defconfig +Subject: [PATCH 68/85] bcm2835: bcm2835_defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -132251,10 +132251,10 @@ index 31cb073..2e8a95a 100644 # CONFIG_XZ_DEC_ARM is not set # CONFIG_XZ_DEC_ARMTHUMB is not set -From 4e2ed4a7a7971ea763017bc6234d30cdc5bfb984 Mon Sep 17 00:00:00 2001 +From f06ed380a59b6b336820510c6716db5bd9928e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 23:00:15 +0200 -Subject: [PATCH 69/77] BCM270x_DT: Add mailbox bcm2708-vcio +Subject: [PATCH 69/85] BCM270x_DT: Add mailbox bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -132269,7 +132269,7 @@ Signed-off-by: Noralf Trønnes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e42f5a5..de2f93a 100644 +index 74ec578..5527d5c 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -870,7 +870,7 @@ void __init bcm2708_init(void) @@ -132282,7 +132282,7 @@ index e42f5a5..de2f93a 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 95223ff..350647a 100644 +index 721559b..4a00561 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -890,7 +890,7 @@ void __init bcm2709_init(void) @@ -132295,10 +132295,10 @@ index 95223ff..350647a 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); -From 2867da0a54803e6eb8e748b63a474877e16899b0 Mon Sep 17 00:00:00 2001 +From ad4a25a7e27ffac5b4f5b9eba60c8588ec2e04c1 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 70/77] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 70/85] rpi-ft5406: Add touchscreen driver for pi LCD display --- drivers/input/touchscreen/Kconfig | 7 + @@ -132615,10 +132615,10 @@ index cc284ed..d3ea839 100644 VCMSG_SET_CURSOR_STATE = 0x00008011, }; -From f794a0549b3a54cbe6dcfef3b37c421dda92d13a Mon Sep 17 00:00:00 2001 +From 4d11ea5e022aa484a8884a54d08bb5d3f26bed0b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 71/77] Improve __copy_to_user and __copy_from_user performance +Subject: [PATCH 71/85] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use optimised memcpy/memmove/memcmp/memset implementations. @@ -134142,10 +134142,10 @@ index 3e58d71..0622891 100644 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From 5787d557e062cdac5f3e19ccd60394dc6df38aab Mon Sep 17 00:00:00 2001 +From 961d37927bd0de6c86334892d19341f427a6d543 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 27 May 2015 17:22:15 +0100 -Subject: [PATCH 72/77] bcm2835-audio: Create the platform device if the DT +Subject: [PATCH 72/85] bcm2835-audio: Create the platform device if the DT node is disabled For backwards compatibility, allow the built-in ALSA driver to be enabled @@ -134157,7 +134157,7 @@ node in DT. 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index de2f93a..cfc4f13 100644 +index 5527d5c..937c2d3 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -898,8 +898,14 @@ void __init bcm2708_init(void) @@ -134178,7 +134178,7 @@ index de2f93a..cfc4f13 100644 bcm_register_device_dt(&bcm2708_spi_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 350647a..507ff52 100644 +index 4a00561..dec8043 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -918,8 +918,14 @@ void __init bcm2709_init(void) @@ -134199,10 +134199,10 @@ index 350647a..507ff52 100644 bcm_register_device_dt(&bcm2708_spi_device); -From 070a6f51cd5f81f635cfcccd3452ee5f252a7ee4 Mon Sep 17 00:00:00 2001 +From 729ca6d5fc85ce618d61af67f400d1f20ddd2fbd 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 73/77] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 73/85] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -134261,10 +134261,10 @@ index 70f2f39..f7fdacd 100644 static const char * const bcm2835_compat[] = { -From 3add74da14e27d18ef276f66c55a69e6dc014216 Mon Sep 17 00:00:00 2001 +From 9a645229a554cd9b0f211bd15310ceb4c61f32b2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Jun 2015 17:47:27 +0100 -Subject: [PATCH 74/77] platform: Add force_core command line setting to boot +Subject: [PATCH 74/85] platform: Add force_core command line setting to boot from a different core number --- @@ -134315,7 +134315,7 @@ index a366275..90805a6 100644 writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 507ff52..c5e51e8 100644 +index dec8043..fe71c50 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -96,6 +96,7 @@ static unsigned w1_gpio_pin = W1_GPIO; @@ -134335,112 +134335,2041 @@ index 507ff52..c5e51e8 100644 module_param(serial, uint, 0644); module_param(uart_clock, uint, 0644); -From a283be0c98260b1f29c8c46df7e8fb2a9cdaf5a8 Mon Sep 17 00:00:00 2001 +From 0733a658a5b233abd9da4157ab2bfd52ceebf404 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 18 Jun 2015 17:46:17 +0100 -Subject: [PATCH 75/77] mach-bcm270x: Enable the building of pinctrl-bcm2835 +Subject: [PATCH 75/85] mach-bcm270x: Enable the building of pinctrl-bcm2835 --- drivers/pinctrl/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index 6eadf04..ca6e1be 100644 +index 6eadf04..9119513 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o -+obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ - obj-$(CONFIG_ARCH_BCM) += bcm/ - obj-$(CONFIG_ARCH_BERLIN) += berlin/ - obj-y += freescale/ - -From fd08db11f15960c30449a5a2cb14d3ab7fd470ea Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 18 Jun 2015 18:06:28 +0100 -Subject: [PATCH 76/77] squash: Fix inconsistency in pinctrl Makefile patch - ---- - drivers/pinctrl/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index ca6e1be..9119513 100644 ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -38,7 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o - obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o - obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o - --obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ +obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += bcm/ obj-$(CONFIG_ARCH_BCM) += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-y += freescale/ -From 05376fce25aaab4f47182a5af04928bfa06f30d6 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 18 Jun 2015 19:53:58 +0100 -Subject: [PATCH 77/77] platform: squash: Remove IRQF_DISABLED +From 3c7dc45eee7c0339b72469bf6674e842385b7ab9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 19 Jun 2015 16:41:39 +0100 +Subject: [PATCH 76/85] BCM270X_DT: Document the i2s-mmap overlay --- - arch/arm/mach-bcm2708/armctrl.c | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2708/bcm2708_gpio.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) + arch/arm/boot/dts/overlays/README | 6 ++++++ + 1 file changed, 6 insertions(+) -diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index 74bacb3..0429225 100644 ---- a/arch/arm/mach-bcm2708/armctrl.c -+++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -305,7 +305,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, - irq_set_chip(irq, &armctrl_chip); - irq_set_chip_data(irq, (void *)data); - irq_set_handler(irq, handle_level_irq); -- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 3e08f98..7fa6d33 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -260,6 +260,12 @@ Params: ds1307 Select the DS1307 device + pcf8563 Select the PCF8563 device + + ++Name: i2s-mmap ++Info: Enables mmap support in the bcm2708-i2s driver ++Load: dtoverlay=i2s-mmap ++Params: ++ ++ + Name: iqaudio-dac + Info: Configures the IQaudio DAC audio card + Load: dtoverlay=iqaudio-dac + +From d9fa11803a0d2e3b1eaf4041ddd0ca5651300d96 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 17 Jun 2015 11:36:53 +0100 +Subject: [PATCH 77/85] bcm2835-sdhost: Improve error handling and recovery + +1) Expose the hw_reset method to the MMC framework, removing many + internal calls by the driver. + +2) Reduce overclock setting on error. + +3) Increase timeout to cope with high capacity cards. + +4) Add properties and parameters to control pio_limit and debug. + +5) Reduce messages at probe time. +--- + arch/arm/boot/dts/overlays/README | 8 +- + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 4 +- + drivers/mmc/host/bcm2835-sdhost.c | 578 ++++++++++++++++++-------- + 3 files changed, 404 insertions(+), 186 deletions(-) + +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 7fa6d33..63da266 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -408,7 +408,13 @@ Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock + Load: dtoverlay=sdhost,= + Params: overclock_50 Clock (in MHz) to use when the MMC framework + requests 50MHz +- force_pio Disable DMA support ++ ++ force_pio Disable DMA support (default off) ++ ++ pio_limit Number of blocks above which to use DMA ++ (default 2) ++ ++ debug Enable debug output (default off) + + + Name: spi-bcm2708 +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +index 8fb28e9..b408ab4 100644 +--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -22,6 +22,7 @@ + dma-names = "tx", "rx"; + brcm,delay-after-stop = <0>; + brcm,overclock-50 = <0>; ++ brcm,pio-limit = <2>; + status = "okay"; + }; + }; +@@ -70,9 +71,10 @@ + }; + + __overrides__ { +- delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; + overclock_50 = <&sdhost>,"brcm,overclock-50:0"; + force_pio = <&sdhost>,"brcm,force-pio?"; ++ pio_limit = <&sdhost>,"brcm,pio-limit:0"; ++ debug = <&sdhost>,"brcm,debug?"; + sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; + }; + }; +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +index eef8a24..6277e43 100644 +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -90,9 +90,8 @@ + /* Reserved */ + #define SDHSTS_DATA_FLAG 0x01 + +-#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) ++#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR|SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) + #define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) +-/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ + + #define SDHCFG_BUSY_IRPT_EN (1<<10) + #define SDHCFG_BLOCK_IRPT_EN (1<<8) +@@ -111,16 +110,7 @@ + #define SDEDM_READ_THRESHOLD_SHIFT 14 + #define SDEDM_THRESHOLD_MASK 0x1f + +-/* the inclusive limit in bytes under which PIO will be used instead of DMA */ +-#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER +-#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER +-#else +-#define PIO_DMA_BARRIER 0 +-#endif +- +-#define MIN_FREQ 400000 +-#define TIMEOUT_VAL 0xE +-#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) ++#define MHZ 1000000 + + #ifndef BCM2708_PERI_BASE + #define BCM2708_PERI_BASE 0x20000000 +@@ -138,19 +128,20 @@ struct bcm2835_host { + + struct mmc_host *mmc; + +- u32 timeout; ++ u32 pio_timeout; /* In jiffies */ + + int clock; /* Current clock speed */ + + bool slow_card; /* Force 11-bit divisor */ + + unsigned int max_clk; /* Max possible freq */ +- unsigned int timeout_clk; /* Timeout freq (KHz) */ + + struct tasklet_struct finish_tasklet; /* Tasklet structures */ + + struct timer_list timer; /* Timer for timeouts */ + ++ struct timer_list pio_timer; /* PIO error detection timer */ ++ + struct sg_mapping_iter sg_miter; /* SG state for PIO */ + unsigned int blocks; /* remaining PIO blocks */ + +@@ -170,6 +161,10 @@ struct bcm2835_host { + + unsigned int use_busy:1; /* Wait for busy interrupt */ + ++ unsigned int reduce_overclock:1; /* ...at the next opportunity */ ++ ++ unsigned int debug:1; /* Enable debug output */ ++ + u32 thread_isr; + + /*DMA part*/ +@@ -185,7 +180,8 @@ struct bcm2835_host { + struct timeval stop_time; /* when the last stop was issued */ + u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ +- u32 max_overclock; /* Highest reported */ ++ u32 overclock; /* Current frequency if overclocked, else zero */ ++ u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ + }; + + +@@ -204,41 +200,79 @@ static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg + return readl_relaxed(host->ioaddr + reg); + } + ++static void bcm2835_sdhost_dumpcmd(struct bcm2835_host *host, ++ struct mmc_command *cmd, ++ const char *label) ++{ ++ if (cmd) ++ pr_info("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", ++ mmc_hostname(host->mmc), ++ (cmd == host->cmd) ? '>' : ' ', ++ label, cmd->opcode, cmd->arg, cmd->flags, ++ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], ++ cmd->error); ++} ++ + static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) + { +- pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", ++ bcm2835_sdhost_dumpcmd(host, host->mrq->sbc, "sbc"); ++ bcm2835_sdhost_dumpcmd(host, host->mrq->cmd, "cmd"); ++ if (host->mrq->data) ++ pr_err("%s: data blocks %x blksz %x - err %d\n", ++ mmc_hostname(host->mmc), ++ host->mrq->data->blocks, ++ host->mrq->data->blksz, ++ host->mrq->data->error); ++ bcm2835_sdhost_dumpcmd(host, host->mrq->stop, "stop"); ++ ++ pr_info("%s: =========== REGISTER DUMP ===========\n", + mmc_hostname(host->mmc)); + +- pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", ++ pr_info("%s: SDCMD 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCMD)); +- pr_info(DRIVER_NAME ": SDARG 0x%08x\n", ++ pr_info("%s: SDARG 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDARG)); +- pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", ++ pr_info("%s: SDTOUT 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDTOUT)); +- pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", ++ pr_info("%s: SDCDIV 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCDIV)); +- pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", ++ pr_info("%s: SDRSP0 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP0)); +- pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", ++ pr_info("%s: SDRSP1 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP1)); +- pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", ++ pr_info("%s: SDRSP2 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP2)); +- pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", ++ pr_info("%s: SDRSP3 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP3)); +- pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", ++ pr_info("%s: SDHSTS 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHSTS)); +- pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", ++ pr_info("%s: SDVDD 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDVDD)); +- pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", ++ pr_info("%s: SDEDM 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDEDM)); +- pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", ++ pr_info("%s: SDHCFG 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHCFG)); +- pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", ++ pr_info("%s: SDHBCT 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBCT)); +- pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", ++ pr_info("%s: SDHBLC 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBLC)); + +- pr_debug(DRIVER_NAME ": ===========================================\n"); ++ pr_info("%s: ===========================================\n", ++ mmc_hostname(host->mmc)); + } + + +@@ -248,12 +282,10 @@ static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) + } + + +-static void bcm2835_sdhost_reset(struct bcm2835_host *host) ++static void bcm2835_sdhost_reset_internal(struct bcm2835_host *host) + { + u32 temp; + +- pr_debug("bcm2835_sdhost_reset\n"); +- + bcm2835_sdhost_set_power(host, false); + + bcm2835_sdhost_write(host, 0, SDCMD); +@@ -281,6 +313,20 @@ static void bcm2835_sdhost_reset(struct bcm2835_host *host) + mmiowb(); + } + ++ ++static void bcm2835_sdhost_reset(struct mmc_host *mmc) ++{ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ if (host->debug) ++ pr_info("%s: reset\n", mmc_hostname(mmc)); ++ spin_lock_irqsave(&host->lock, flags); ++ ++ bcm2835_sdhost_reset_internal(host); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ + static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + + static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) +@@ -290,7 +336,7 @@ static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) + /* Set interrupt enables */ + host->hcfg = SDHCFG_BUSY_IRPT_EN; + +- bcm2835_sdhost_reset(host); ++ bcm2835_sdhost_reset_internal(host); + + if (soft) { + /* force clock reconfiguration */ +@@ -420,6 +466,40 @@ static void bcm2835_sdhost_dma_complete(void *param) + spin_unlock_irqrestore(&host->lock, flags); + } + ++static bool data_transfer_wait(struct bcm2835_host *host, const char *caller) ++{ ++ unsigned long timeout = 1000000; ++ u32 hsts; ++ while (timeout) ++ { ++ hsts = bcm2835_sdhost_read(host, SDHSTS); ++ if (hsts & (SDHSTS_TRANSFER_ERROR_MASK | ++ SDHSTS_DATA_FLAG)) { ++ bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK, ++ SDHSTS); ++ break; ++ } ++ timeout--; ++ } ++ ++ if (hsts & (SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR)) { ++ pr_err("%s: data error in %s - HSTS %x\n", ++ mmc_hostname(host->mmc), caller, hsts); ++ host->data->error = -EILSEQ; ++ return false; ++ } else if ((timeout == 0) || ++ (hsts & (SDHSTS_CMD_TIME_OUT | ++ SDHSTS_REW_TIME_OUT))) { ++ pr_err("%s: timeout in %s - HSTS %x\n", ++ mmc_hostname(host->mmc), caller, hsts); ++ host->data->error = -ETIMEDOUT; ++ return false; ++ } ++ return true; ++} ++ + static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) + { + unsigned long flags; +@@ -443,35 +523,15 @@ static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) + buf = (u32 *)host->sg_miter.addr; + + while (len) { +- while (1) { +- u32 hsts; +- hsts = bcm2835_sdhost_read(host, SDHSTS); +- if (hsts & SDHSTS_DATA_FLAG) +- break; +- +- if (hsts & SDHSTS_ERROR_MASK) { +- pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", +- mmc_hostname(host->mmc), +- hsts, +- bcm2835_sdhost_read(host, SDHBCT), +- blksize + len); +- if (hsts & SDHSTS_REW_TIME_OUT) +- host->data->error = -ETIMEDOUT; +- else if (hsts & (SDHSTS_CRC16_ERROR || +- SDHSTS_CRC7_ERROR)) +- host->data->error = -EILSEQ; +- else { +- pr_err("%s: unexpected data error\n", +- mmc_hostname(host->mmc)); +- bcm2835_sdhost_dumpregs(host); +- host->cmd->error = -EIO; +- } +- } +- } ++ if (!data_transfer_wait(host, "read_block_pio")) ++ break; + + *(buf++) = bcm2835_sdhost_read(host, SDDATA); + len -= 4; + } ++ ++ if (host->data->error) ++ break; } - armctrl_pm_register(base, irq_start, resume_sources); -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cfc4f13..937c2d3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -1028,7 +1028,7 @@ static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) + sg_miter_stop(&host->sg_miter); +@@ -502,11 +562,15 @@ static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) + buf = host->sg_miter.addr; - static struct irqaction bcm2708_timer_irq = { - .name = "BCM2708 Timer Tick", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2708_timer_interrupt, + while (len) { +- while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) +- continue; ++ if (!data_transfer_wait(host, "write_block_pio")) ++ break; ++ + bcm2835_sdhost_write(host, *(buf++), SDDATA); + len -= 4; + } ++ ++ if (host->data->error) ++ break; + } + + sg_miter_stop(&host->sg_miter); +@@ -519,10 +583,15 @@ static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) + { + BUG_ON(!host->data); + +- if (host->data->flags & MMC_DATA_READ) ++ if (host->data->flags & MMC_DATA_READ) { + bcm2835_sdhost_read_block_pio(host); +- else ++ } else { + bcm2835_sdhost_write_block_pio(host); ++ ++ /* Start a timer in case a transfer error occurs because ++ there is no error interrupt */ ++ mod_timer(&host->pio_timer, jiffies + host->pio_timeout); ++ } + } + + +@@ -607,6 +676,7 @@ static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_co + host->flush_fifo = 0; + host->data->bytes_xfered = 0; + ++ host->use_dma = host->have_dma && (data->blocks > host->pio_limit); + if (!host->use_dma) { + int flags; + +@@ -619,8 +689,6 @@ static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_co + host->blocks = data->blocks; + } + +- host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; +- + bcm2835_sdhost_set_transfer_irqs(host); + + bcm2835_sdhost_write(host, data->blksz, SDHBCT); +@@ -638,22 +706,25 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + + WARN_ON(host->cmd); + +- if (1) { +- pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", +- cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); +- if (cmd->data) +- pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", +- (cmd->data->flags & MMC_DATA_READ) ? +- "read" : "write", cmd->data->blocks, +- cmd->data->blksz); +- } ++ if (cmd->data) ++ pr_debug("%s: send_command %d 0x%x " ++ "(flags 0x%x) - %s %d*%d\n", ++ mmc_hostname(host->mmc), ++ cmd->opcode, cmd->arg, cmd->flags, ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ else ++ pr_debug("%s: send_command %d 0x%x (flags 0x%x)\n", ++ mmc_hostname(host->mmc), ++ cmd->opcode, cmd->arg, cmd->flags); + + /* Wait max 10 ms */ + timeout = 1000; + + while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { + if (timeout == 0) { +- pr_err("%s: Previous command never completed.\n", ++ pr_err("%s: previous command never completed.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + cmd->error = -EIO; +@@ -666,16 +737,16 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + + if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { + host->max_delay = (1000-timeout)/100; +- pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); ++ pr_warning("%s: controller hung for %d ms\n", ++ mmc_hostname(host->mmc), ++ host->max_delay); + } + + timeout = jiffies; +-#ifdef CONFIG_ARCH_BCM2835 + if (!cmd->data && cmd->busy_timeout > 9000) + timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; + else +-#endif +- timeout += 10 * HZ; ++ timeout += 10 * HZ; + mod_timer(&host->timer, timeout); + + host->cmd = cmd; +@@ -685,7 +756,7 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + bcm2835_sdhost_write(host, cmd->arg, SDARG); + + if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { +- pr_err("%s: Unsupported response type!\n", ++ pr_err("%s: unsupported response type!\n", + mmc_hostname(host->mmc)); + cmd->error = -EINVAL; + tasklet_schedule(&host->finish_tasklet); +@@ -783,13 +854,6 @@ static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) + pr_debug("transfer_complete(error %d, stop %d)\n", + data->error, data->stop ? 1 : 0); + +- if (data->error) +- /* +- * The controller needs a reset of internal state machines +- * upon error conditions. +- */ +- bcm2835_sdhost_reset(host); +- + /* + * Need to send CMD12 if - + * a) open-ended multiblock transfer (no CMD23) +@@ -845,7 +909,7 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + #endif + + if (timeout == 0) { +- pr_err("%s: Command never completed.\n", ++ pr_err("%s: command never completed.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + host->cmd->error = -EIO; +@@ -875,14 +939,23 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + { + u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); + +- pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", +- mmc_hostname(host->mmc), sdcmd, sdhsts, +- bcm2835_sdhost_read(host, SDEDM)); +- +- if (sdhsts & SDHSTS_CMD_TIME_OUT) ++ if (host->debug) ++ pr_info("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", ++ mmc_hostname(host->mmc), sdcmd, sdhsts, ++ bcm2835_sdhost_read(host, SDEDM)); ++ ++ if (sdhsts & SDHSTS_CMD_TIME_OUT) { ++ switch (host->cmd->opcode) { ++ case 5: case 52: case 53: ++ /* Don't warn about SDIO commands */ ++ break; ++ default: ++ pr_err("%s: command timeout\n", ++ mmc_hostname(host->mmc)); ++ break; ++ } + host->cmd->error = -ETIMEDOUT; +- else +- { ++ } else { + pr_err("%s: unexpected command error\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); +@@ -897,11 +970,13 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + int i; + for (i = 0; i < 4; i++) + host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); +- pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", ++ pr_debug("%s: finish_command %08x %08x %08x %08x\n", ++ mmc_hostname(host->mmc), + host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); + } else { + host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); +- pr_debug("bcm2835_sdhost_finish_command: %08x\n", ++ pr_debug("%s: finish_command %08x\n", ++ mmc_hostname(host->mmc), + host->cmd->resp[0]); + } + } +@@ -932,7 +1007,7 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + } + } + +-static void bcm2835_sdhost_timeout_timer(unsigned long data) ++static void bcm2835_sdhost_timeout(unsigned long data) + { + struct bcm2835_host *host; + unsigned long flags; +@@ -942,7 +1017,7 @@ static void bcm2835_sdhost_timeout_timer(unsigned long data) + spin_lock_irqsave(&host->lock, flags); + + if (host->mrq) { +- pr_err("%s: Timeout waiting for hardware interrupt.\n", ++ pr_err("%s: timeout waiting for hardware interrupt.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + +@@ -964,6 +1039,41 @@ static void bcm2835_sdhost_timeout_timer(unsigned long data) + spin_unlock_irqrestore(&host->lock, flags); + } + ++static void bcm2835_sdhost_pio_timeout(unsigned long data) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ host = (struct bcm2835_host *)data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->data) { ++ u32 hsts = bcm2835_sdhost_read(host, SDHSTS); ++ ++ if (hsts & SDHSTS_REW_TIME_OUT) { ++ pr_err("%s: transfer timeout\n", ++ mmc_hostname(host->mmc)); ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); ++ } else { ++ pr_err("%s: unexpected transfer timeout\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++ bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK, ++ SDHSTS); ++ ++ host->data->error = -ETIMEDOUT; ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ + static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) + { + if (enable) +@@ -979,7 +1089,7 @@ static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + +- pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); ++ pr_debug("%s: enable_sdio_irq(%d)\n", mmc_hostname(mmc), enable); + spin_lock_irqsave(&host->lock, flags); + bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); + spin_unlock_irqrestore(&host->lock, flags); +@@ -987,11 +1097,12 @@ static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) + + static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + { +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT | ++ SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR); + + if (!host->cmd) { +- pr_err("%s: Got command busy interrupt 0x%08x even " ++ pr_err("%s: got command busy interrupt 0x%08x even " + "though no command operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); +@@ -999,7 +1110,7 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + } + + if (!host->use_busy) { +- pr_err("%s: Got command busy interrupt 0x%08x even " ++ pr_err("%s: got command busy interrupt 0x%08x even " + "though not expecting one.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); +@@ -1007,14 +1118,28 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + } + host->use_busy = 0; + +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | +- SDHSTS_FIFO_ERROR)) +- host->cmd->error = -EILSEQ; ++ if (intmask & SDHSTS_ERROR_MASK) ++ { ++ pr_err("sdhost_busy_irq: intmask %x, data %p\n", intmask, host->mrq->data); ++ if (intmask & SDHSTS_CRC7_ERROR) ++ host->cmd->error = -EILSEQ; ++ else if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) { ++ if (host->mrq->data) ++ host->mrq->data->error = -EILSEQ; ++ else ++ host->cmd->error = -EILSEQ; ++ } else if (intmask & SDHSTS_REW_TIME_OUT) { ++ if (host->mrq->data) ++ host->mrq->data->error = -ETIMEDOUT; ++ else ++ host->cmd->error = -ETIMEDOUT; ++ } else if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; + +- if (host->cmd->error) ++ bcm2835_sdhost_dumpregs(host); + tasklet_schedule(&host->finish_tasklet); ++ } + else + bcm2835_sdhost_finish_command(host); + +@@ -1023,8 +1148,9 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + + static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) + { +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | ++ SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR); + + /* There are no dedicated data/space available interrupt + status bits, so it is necessary to use the single shared +@@ -1034,13 +1160,19 @@ static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) + if (!host->data) + return 0; + +- // XXX FIFO_ERROR +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && +- ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) +- != MMC_BUS_TEST_R)) +- host->cmd->error = -EILSEQ; ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR | ++ SDHSTS_REW_TIME_OUT)) { ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->data->error = -EILSEQ; ++ else ++ host->data->error = -ETIMEDOUT; ++ ++ bcm2835_sdhost_dumpregs(host); ++ tasklet_schedule(&host->finish_tasklet); ++ return handled; ++ } + + /* Use the block interrupt for writes after the first block */ + if (host->data->flags & MMC_DATA_WRITE) { +@@ -1067,31 +1199,48 @@ static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) + { + struct dma_chan *dma_chan; + u32 dir_data; +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | ++ SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR); + + if (!host->data) { +- pr_err("%s: Got block interrupt 0x%08x even " ++ pr_err("%s: got block interrupt 0x%08x even " + "though no data operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); + return handled; + } + +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && +- ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) +- != MMC_BUS_TEST_R)) +- host->cmd->error = -EILSEQ; ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR | ++ SDHSTS_REW_TIME_OUT)) { ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->data->error = -EILSEQ; ++ else ++ host->data->error = -ETIMEDOUT; ++ ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); ++ tasklet_schedule(&host->finish_tasklet); ++ return handled; ++ } + + if (!host->use_dma) { + BUG_ON(!host->blocks); + host->blocks--; +- if ((host->blocks == 0) || host->data->error) ++ if ((host->blocks == 0) || host->data->error) { ++ /* Cancel the timer */ ++ del_timer(&host->pio_timer); ++ + bcm2835_sdhost_finish_data(host); +- else ++ } else { + bcm2835_sdhost_transfer_pio(host); ++ ++ /* Reset the timer */ ++ mod_timer(&host->pio_timer, ++ jiffies + host->pio_timeout); ++ } + } else if (host->data->flags & MMC_DATA_WRITE) { + dma_chan = host->dma_chan_tx; + dir_data = DMA_TO_DEVICE; +@@ -1125,7 +1274,7 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) + SDHSTS_BLOCK_IRPT | + SDHSTS_SDIO_IRPT | + SDHSTS_DATA_FLAG); +- if ((handled == SDHSTS_DATA_FLAG) && // XXX ++ if ((handled == SDHSTS_DATA_FLAG) && + (loops == 0) && !host->data) { + pr_err("%s: sdhost_irq data interrupt 0x%08x even " + "though no data operation was in progress.\n", +@@ -1177,10 +1326,11 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) + spin_unlock(&host->lock); + + if (early) +- pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); ++ pr_debug("%s: early %x (loops %d)\n", ++ mmc_hostname(host->mmc), early, loops); + + if (unexpected) { +- pr_err("%s: Unexpected interrupt 0x%08x.\n", ++ pr_err("%s: unexpected interrupt 0x%08x.\n", + mmc_hostname(host->mmc), unexpected); + bcm2835_sdhost_dumpregs(host); + } +@@ -1227,8 +1377,22 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) + int div = 0; /* Initialized for compiler warning */ + unsigned int input_clock = clock; + +- if (host->overclock_50 && (clock == 50000000)) +- clock = host->overclock_50 * 1000000 + 999999; ++ if (host->debug) ++ pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock); ++ ++ if ((clock == 0) && host->reduce_overclock) { ++ /* This is a reset following data corruption - reduce any ++ overclock */ ++ host->reduce_overclock = 0; ++ if (host->overclock_50 > 50) { ++ pr_warn("%s: reducing overclock due to errors\n", ++ mmc_hostname(host->mmc)); ++ host->overclock_50--; ++ } ++ } ++ ++ if (host->overclock_50 && (clock == 50*MHZ)) ++ clock = host->overclock_50 * MHZ + (MHZ - 1); + + /* The SDCDIV register has 11 bits, and holds (div - 2). + But in data mode the max is 50MHz wihout a minimum, and only the +@@ -1275,17 +1439,34 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) + clock = host->max_clk / (div + 2); + host->mmc->actual_clock = clock; + +- if ((clock > input_clock) && (clock > host->max_overclock)) { +- pr_warn("%s: Overclocking to %dHz\n", +- mmc_hostname(host->mmc), clock); +- host->max_overclock = clock; ++ if (clock > input_clock) { ++ /* Save the closest value, to make it easier ++ to reduce in the event of error */ ++ host->overclock_50 = (clock/MHZ); ++ ++ if (clock != host->overclock) { ++ pr_warn("%s: overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->overclock = clock; ++ } ++ } ++ else if ((clock == 50 * MHZ) && host->overclock) ++ { ++ pr_warn("%s: cancelling overclock\n", ++ mmc_hostname(host->mmc)); ++ host->overclock = 0; + } + + host->cdiv = div; + bcm2835_sdhost_write(host, host->cdiv, SDCDIV); + +- pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", +- input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); ++ /* Set the timeout to 500ms */ ++ bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT); ++ ++ if (host->debug) ++ pr_info("%s: clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", ++ mmc_hostname(host->mmc), input_clock, ++ host->max_clk, host->cdiv, host->mmc->actual_clock); + } + + static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) +@@ -1293,29 +1474,32 @@ static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq + struct bcm2835_host *host; + unsigned long flags; + +- if (1) { ++ host = mmc_priv(mmc); ++ ++ if (host->debug) { + struct mmc_command *cmd = mrq->cmd; +- const char *src = "cmd"; + BUG_ON(!cmd); +- pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", +- src, cmd->opcode, cmd->arg, cmd->flags); + if (cmd->data) +- pr_debug("bcm2835_sdhost_request: %s %d*%d\n", +- (cmd->data->flags & MMC_DATA_READ) ? +- "read" : "write", cmd->data->blocks, +- cmd->data->blksz); ++ pr_info("%s: cmd %d 0x%x (flags 0x%x) - %s %d*%d\n", ++ mmc_hostname(mmc), ++ cmd->opcode, cmd->arg, cmd->flags, ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ else ++ pr_info("%s: cmd %d 0x%x (flags 0x%x)\n", ++ mmc_hostname(mmc), ++ cmd->opcode, cmd->arg, cmd->flags); + } + + if (mrq->data && !is_power_of_2(mrq->data->blksz)) { +- pr_err("%s: Unsupported block size (%d bytes)\n", ++ pr_err("%s: unsupported block size (%d bytes)\n", + mmc_hostname(mmc), mrq->data->blksz); + mrq->cmd->error = -EINVAL; + mmc_request_done(mmc, mrq); + return; + } + +- host = mmc_priv(mmc); +- + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); +@@ -1345,9 +1529,12 @@ static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + +- pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", +- ios->clock, ios->power_mode, ios->bus_width, +- ios->timing, ios->signal_voltage, ios->drv_type); ++ if (host->debug) ++ pr_info("%s: ios clock %d, pwr %d, bus_width %d, " ++ "timing %d, vdd %d, drv_type %d\n", ++ mmc_hostname(mmc), ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); + + spin_lock_irqsave(&host->lock, flags); + +@@ -1396,6 +1583,7 @@ static struct mmc_host_ops bcm2835_sdhost_ops = { + .request = bcm2835_sdhost_request, + .set_ios = bcm2835_sdhost_set_ios, + .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, ++ .hw_reset = bcm2835_sdhost_reset, + .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, }; -diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c -index c1e9254..e33265d 100644 ---- a/arch/arm/mach-bcm2708/bcm2708_gpio.c -+++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c -@@ -306,7 +306,7 @@ static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) +@@ -1423,15 +1611,24 @@ static void bcm2835_sdhost_tasklet_finish(unsigned long param) - static struct irqaction bcm2708_gpio_irq = { - .name = "BCM2708 GPIO catchall handler", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2708_gpio_interrupt, + mrq = host->mrq; + +- /* +- * The controller needs a reset of internal state machines +- * upon error conditions. +- */ +- if (((mrq->cmd && mrq->cmd->error) || +- (mrq->data && (mrq->data->error || +- (mrq->data->stop && mrq->data->stop->error))))) { ++ /* Drop the overclock after any data corruption, or after any ++ error overclocked */ ++ if (mrq->data && (mrq->data->error == -EILSEQ)) ++ host->reduce_overclock = 1; ++ else if (host->overclock) { ++ /* Convert timeout errors while overclocked to data errors, ++ because the system recovers better. */ ++ if (mrq->cmd && mrq->cmd->error) { ++ host->reduce_overclock = 1; ++ if (mrq->cmd->error == -ETIMEDOUT) ++ mrq->cmd->error = -EILSEQ; ++ } + +- bcm2835_sdhost_reset(host); ++ if (mrq->data && mrq->data->error) { ++ host->reduce_overclock = 1; ++ if (mrq->data->error == -ETIMEDOUT) ++ mrq->data->error = -EILSEQ; ++ } + } + + host->mrq = NULL; +@@ -1450,35 +1647,37 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + { + struct mmc_host *mmc; + struct dma_slave_config cfg; ++ char pio_limit_string[20]; + int ret; + + mmc = host->mmc; + +- bcm2835_sdhost_reset(host); ++ bcm2835_sdhost_reset_internal(host); + + mmc->f_max = host->max_clk; + mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; + +- /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ +- host->timeout_clk = mmc->f_max / 1000; +-#ifdef CONFIG_ARCH_BCM2835 +- mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; +-#endif ++ mmc->max_busy_timeout = (~(unsigned int)0)/(mmc->f_max/1000); ++ ++ pr_debug("f_max %d, f_min %d, max_busy_timeout %d\n", ++ mmc->f_max, mmc->f_min, mmc->max_busy_timeout); ++ + /* host controller capabilities */ + mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | + MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | +- MMC_CAP_NEEDS_POLL | ++ MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | + (ALLOW_CMD23 * MMC_CAP_CMD23); + + spin_lock_init(&host->lock); + + if (host->allow_dma) { +- if (!host->dma_chan_tx || !host->dma_chan_rx || +- IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { +- pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); ++ if (IS_ERR_OR_NULL(host->dma_chan_tx) || ++ IS_ERR_OR_NULL(host->dma_chan_rx)) { ++ pr_err("%s: unable to initialise DMA channels. " ++ "Falling back to PIO\n", ++ mmc_hostname(mmc)); + host->have_dma = false; + } else { +- pr_info("DMA channels allocated for the SDHost driver"); + host->have_dma = true; + + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -1496,7 +1695,6 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); + } + } else { +- pr_info("Forcing PIO mode\n"); + host->have_dma = false; + } + +@@ -1512,18 +1710,23 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + tasklet_init(&host->finish_tasklet, + bcm2835_sdhost_tasklet_finish, (unsigned long)host); + +- setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); ++ setup_timer(&host->timer, bcm2835_sdhost_timeout, ++ (unsigned long)host); ++ ++ setup_timer(&host->pio_timer, bcm2835_sdhost_pio_timeout, ++ (unsigned long)host); + + bcm2835_sdhost_init(host, 0); + #ifndef CONFIG_ARCH_BCM2835 + ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, + mmc_hostname(mmc), host); + #else +- ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, ++ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, ++ bcm2835_sdhost_thread_irq, + IRQF_SHARED, mmc_hostname(mmc), host); + #endif + if (ret) { +- pr_err("%s: Failed to request IRQ %d: %d\n", ++ pr_err("%s: failed to request IRQ %d: %d\n", + mmc_hostname(mmc), host->irq, ret); + goto untasklet; + } +@@ -1531,10 +1734,13 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + mmiowb(); + mmc_add_host(mmc); + +- pr_info("Load BCM2835 SDHost driver\n"); +- if (host->delay_after_stop) +- pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", +- host->delay_after_stop); ++ pio_limit_string[0] = '\0'; ++ if (host->have_dma && (host->pio_limit > 0)) ++ sprintf(pio_limit_string, " (>%d)", host->pio_limit); ++ pr_info("%s: %s loaded - DMA %s%s\n", ++ mmc_hostname(mmc), DRIVER_NAME, ++ host->have_dma ? "enabled" : "disabled", ++ pio_limit_string); + + return 0; + +@@ -1562,7 +1768,7 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) + mmc->ops = &bcm2835_sdhost_ops; + host = mmc_priv(mmc); + host->mmc = mmc; +- host->timeout = msecs_to_jiffies(1000); ++ host->pio_timeout = msecs_to_jiffies(500); + spin_lock_init(&host->lock); + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1588,8 +1794,12 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) + of_property_read_u32(node, + "brcm,overclock-50", + &host->overclock_50); ++ of_property_read_u32(node, ++ "brcm,pio-limit", ++ &host->pio_limit); + host->allow_dma = ALLOW_DMA && + !of_property_read_bool(node, "brcm,force-pio"); ++ host->debug = of_property_read_bool(node, "brcm,debug"); + } + + if (host->allow_dma) { + +From 5920303037d30f0ecee57f83015cd8838ba1f77e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 4 Jun 2015 13:11:46 -0700 +Subject: [PATCH 78/85] ARM: bcm2835: Add the Raspberry Pi firmware driver + +This gives us a function for making mailbox property channel requests +of the firmware, which is most notable in that it will let us get and +set clock rates. + +Signed-off-by: Eric Anholt +--- + drivers/firmware/Kconfig | 7 + + drivers/firmware/Makefile | 1 + + drivers/firmware/raspberrypi.c | 260 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 115 +++++++++++++ + 4 files changed, 383 insertions(+) + create mode 100644 drivers/firmware/raspberrypi.c + create mode 100644 include/soc/bcm2835/raspberrypi-firmware.h + +diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig +index 6517132..564aa5b 100644 +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -136,6 +136,13 @@ config QCOM_SCM + bool + depends on ARM || ARM64 + ++config RASPBERRYPI_FIRMWARE ++ tristate "Raspberry Pi Firmware Driver" ++ depends on BCM2835_MBOX ++ help ++ This option enables support for communicating with the firmware on the ++ Raspberry Pi. ++ + source "drivers/firmware/google/Kconfig" + source "drivers/firmware/efi/Kconfig" + +diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile +index 3fdd391..ee101a2 100644 +--- a/drivers/firmware/Makefile ++++ b/drivers/firmware/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o + obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o + obj-$(CONFIG_QCOM_SCM) += qcom_scm.o + CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) ++obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o + + obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ + obj-$(CONFIG_EFI) += efi/ +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +new file mode 100644 +index 0000000..dd506cd +--- /dev/null ++++ b/drivers/firmware/raspberrypi.c +@@ -0,0 +1,260 @@ ++/* ++ * Defines interfaces for interacting wtih the Raspberry Pi firmware's ++ * property channel. ++ * ++ * Copyright © 2015 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_CHAN_PROPERTY 8 ++ ++struct rpi_firmware { ++ struct mbox_client cl; ++ struct mbox_chan *chan; /* The property channel. */ ++ struct completion c; ++ u32 enabled; ++}; ++ ++static DEFINE_MUTEX(transaction_lock); ++ ++static void response_callback(struct mbox_client *cl, void *msg) ++{ ++ struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl); ++ complete(&fw->c); ++} ++ ++/* ++ * Sends a request to the firmware through the BCM2835 mailbox driver, ++ * and synchronously waits for the reply. ++ */ ++static int ++rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) ++{ ++ u32 message = MBOX_MSG(chan, data); ++ int ret; ++ ++ WARN_ON(data & 0xf); ++ ++ mutex_lock(&transaction_lock); ++ reinit_completion(&fw->c); ++ ret = mbox_send_message(fw->chan, &message); ++ if (ret >= 0) { ++ wait_for_completion(&fw->c); ++ ret = 0; ++ } else { ++ dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret); ++ } ++ mutex_unlock(&transaction_lock); ++ ++ return ret; ++} ++ ++/** ++ * rpi_firmware_property_list - Submit firmware property list ++ * @fw: Pointer to firmware structure from rpi_firmware_get(). ++ * @data: Buffer holding tags. ++ * @tag_size: Size of tags buffer. ++ * ++ * Submits a set of concatenated tags to the VPU firmware through the ++ * mailbox property interface. ++ * ++ * The buffer header and the ending tag are added by this function and ++ * don't need to be supplied, just the actual tags for your operation. ++ * See struct rpi_firmware_property_tag_header for the per-tag ++ * structure. ++ */ ++int rpi_firmware_property_list(struct rpi_firmware *fw, ++ void *data, size_t tag_size) ++{ ++ size_t size = tag_size + 12; ++ u32 *buf; ++ dma_addr_t bus_addr; ++ int ret; ++ ++ /* Packets are processed a dword at a time. */ ++ if (size & 3) ++ return -EINVAL; ++ ++ buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) ++ return -ENOMEM; ++ ++ /* The firmware will error out without parsing in this case. */ ++ WARN_ON(size >= 1024 * 1024); ++ ++ buf[0] = size; ++ buf[1] = RPI_FIRMWARE_STATUS_REQUEST; ++ memcpy(&buf[2], data, tag_size); ++ buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END; ++ wmb(); ++ ++ ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr); ++ ++ rmb(); ++ memcpy(data, &buf[2], tag_size); ++ if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) { ++ /* ++ * The tag name here might not be the one causing the ++ * error, if there were multiple tags in the request. ++ * But single-tag is the most common, so go with it. ++ */ ++ dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n", ++ buf[2], buf[1]); ++ ret = -EINVAL; ++ } ++ ++ dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_property_list); ++ ++/** ++ * rpi_firmware_property - Submit single firmware property ++ * @fw: Pointer to firmware structure from rpi_firmware_get(). ++ * @tag: One of enum_mbox_property_tag. ++ * @tag_data: Tag data buffer. ++ * @buf_size: Buffer size. ++ * ++ * Submits a single tag to the VPU firmware through the mailbox ++ * property interface. ++ * ++ * This is a convenience wrapper around ++ * rpi_firmware_property_list() to avoid some of the ++ * boilerplate in property calls. ++ */ ++int rpi_firmware_property(struct rpi_firmware *fw, ++ u32 tag, void *tag_data, size_t buf_size) ++{ ++ /* Single tags are very small (generally 8 bytes), so the ++ * stack should be safe. ++ */ ++ u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)]; ++ struct rpi_firmware_property_tag_header *header = ++ (struct rpi_firmware_property_tag_header *)data; ++ int ret; ++ ++ header->tag = tag; ++ header->buf_size = buf_size; ++ header->req_resp_size = 0; ++ memcpy(data + sizeof(struct rpi_firmware_property_tag_header), ++ tag_data, buf_size); ++ ++ ret = rpi_firmware_property_list(fw, &data, sizeof(data)); ++ memcpy(tag_data, ++ data + sizeof(struct rpi_firmware_property_tag_header), ++ buf_size); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_property); ++ ++static void ++rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) ++{ ++ u32 packet; ++ int ret = rpi_firmware_property(fw, ++ RPI_FIRMWARE_GET_FIRMWARE_REVISION, ++ &packet, sizeof(packet)); ++ ++ if (ret == 0) { ++ struct tm tm; ++ ++ time_to_tm(packet, 0, &tm); ++ ++ dev_info(fw->cl.dev, ++ "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n", ++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min); ++ } ++} ++ ++static int rpi_firmware_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_firmware *fw; ++ ++ fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); ++ if (!fw) ++ return -ENOMEM; ++ ++ fw->cl.dev = dev; ++ fw->cl.rx_callback = response_callback; ++ fw->cl.tx_block = true; ++ ++ fw->chan = mbox_request_channel(&fw->cl, 0); ++ if (IS_ERR(fw->chan)) { ++ int ret = PTR_ERR(fw->chan); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get mbox channel: %d\n", ret); ++ return ret; ++ } ++ ++ init_completion(&fw->c); ++ ++ platform_set_drvdata(pdev, fw); ++ ++ rpi_firmware_print_firmware_revision(fw); ++ ++ return 0; ++} ++ ++static int rpi_firmware_remove(struct platform_device *pdev) ++{ ++ struct rpi_firmware *fw = platform_get_drvdata(pdev); ++ ++ mbox_free_channel(fw->chan); ++ ++ return 0; ++} ++ ++/** ++ * rpi_firmware_get - Get pointer to rpi_firmware structure. ++ * @firmware_node: Pointer to the firmware Device Tree node. ++ * ++ * Returns NULL is the firmware device is not ready. ++ */ ++struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) ++{ ++ struct platform_device *pdev = of_find_device_by_node(firmware_node); ++ ++ if (!pdev) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_get); ++ ++static const struct of_device_id rpi_firmware_of_match[] = { ++ { .compatible = "raspberrypi,bcm2835-firmware", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_firmware_of_match); ++ ++static struct platform_driver rpi_firmware_driver = { ++ .driver = { ++ .name = "raspberrypi-firmware", ++ .of_match_table = rpi_firmware_of_match, ++ }, ++ .probe = rpi_firmware_probe, ++ .remove = rpi_firmware_remove, ++}; ++module_platform_driver(rpi_firmware_driver); ++ ++MODULE_AUTHOR("Eric Anholt "); ++MODULE_DESCRIPTION("Raspberry Pi firmware driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +new file mode 100644 +index 0000000..9d9efb7 +--- /dev/null ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -0,0 +1,115 @@ ++/* ++ * Copyright © 2015 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++ ++struct rpi_firmware; ++ ++enum rpi_firmware_property_status { ++ RPI_FIRMWARE_STATUS_REQUEST = 0, ++ RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000, ++ RPI_FIRMWARE_STATUS_ERROR = 0x80000001, ++}; ++ ++/** ++ * struct rpi_firmware_property_tag_header - Firmware property tag header ++ * @tag: One of enum_mbox_property_tag. ++ * @buf_size: The number of bytes in the value buffer following this ++ * struct. ++ * @req_resp_size: On submit, the length of the request (though it doesn't ++ * appear to be currently used by the firmware). On return, ++ * the length of the response (always 4 byte aligned), with ++ * the low bit set. ++ */ ++struct rpi_firmware_property_tag_header { ++ u32 tag; ++ u32 buf_size; ++ u32 req_resp_size; ++}; ++ ++enum rpi_firmware_property_tag { ++ RPI_FIRMWARE_PROPERTY_END = 0, ++ RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001, ++ ++ RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010, ++ RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011, ++ ++ RPI_FIRMWARE_GET_BOARD_MODEL = 0x00010001, ++ RPI_FIRMWARE_GET_BOARD_REVISION = 0x00010002, ++ RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS = 0x00010003, ++ RPI_FIRMWARE_GET_BOARD_SERIAL = 0x00010004, ++ RPI_FIRMWARE_GET_ARM_MEMORY = 0x00010005, ++ RPI_FIRMWARE_GET_VC_MEMORY = 0x00010006, ++ RPI_FIRMWARE_GET_CLOCKS = 0x00010007, ++ RPI_FIRMWARE_GET_POWER_STATE = 0x00020001, ++ RPI_FIRMWARE_GET_TIMING = 0x00020002, ++ RPI_FIRMWARE_SET_POWER_STATE = 0x00028001, ++ RPI_FIRMWARE_GET_CLOCK_STATE = 0x00030001, ++ RPI_FIRMWARE_GET_CLOCK_RATE = 0x00030002, ++ RPI_FIRMWARE_GET_VOLTAGE = 0x00030003, ++ RPI_FIRMWARE_GET_MAX_CLOCK_RATE = 0x00030004, ++ RPI_FIRMWARE_GET_MAX_VOLTAGE = 0x00030005, ++ RPI_FIRMWARE_GET_TEMPERATURE = 0x00030006, ++ RPI_FIRMWARE_GET_MIN_CLOCK_RATE = 0x00030007, ++ RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, ++ RPI_FIRMWARE_GET_TURBO = 0x00030009, ++ RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, ++ RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, ++ RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, ++ RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, ++ RPI_FIRMWARE_RELEASE_MEMORY = 0x0003000f, ++ RPI_FIRMWARE_EXECUTE_CODE = 0x00030010, ++ RPI_FIRMWARE_EXECUTE_QPU = 0x00030011, ++ RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, ++ RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, ++ RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, ++ RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, ++ RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, ++ RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, ++ RPI_FIRMWARE_SET_TURBO = 0x00038009, ++ ++ /* Dispmanx TAGS */ ++ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, ++ RPI_FIRMWARE_FRAMEBUFFER_BLANK = 0x00040002, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH = 0x00040005, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH = 0x00040008, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, ++ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ ++ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, ++ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, ++}; ++ ++int rpi_firmware_property(struct rpi_firmware *fw, ++ u32 tag, void *data, size_t len); ++int rpi_firmware_property_list(struct rpi_firmware *fw, ++ void *data, size_t tag_size); ++struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); + +From c97b07c0494073a69820a78b6012dc62cb902144 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 13:33:23 +0000 +Subject: [PATCH 79/85] config: Enable ZSMALLOC, ZRAM and PGTABLE_MAPPING + +--- + arch/arm/configs/bcm2709_defconfig | 4 ++++ + arch/arm/configs/bcmrpi_defconfig | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index a3067bf..7ef615c 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -49,6 +49,8 @@ CONFIG_OABI_COMPAT=y + CONFIG_CLEANCACHE=y + CONFIG_FRONTSWAP=y + CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y + CONFIG_UACCESS_WITH_MEMCPY=y + CONFIG_SECCOMP=y + CONFIG_ZBOOT_ROM_TEXT=0x0 +@@ -389,6 +391,8 @@ CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y + CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_ZRAM=m ++CONFIG_ZRAM_LZ4_COMPRESS=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_CRYPTOLOOP=m + CONFIG_BLK_DEV_DRBD=m +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 6a41231..cacde14 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -44,6 +44,8 @@ CONFIG_OABI_COMPAT=y + CONFIG_CLEANCACHE=y + CONFIG_FRONTSWAP=y + CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y + CONFIG_UACCESS_WITH_MEMCPY=y + CONFIG_SECCOMP=y + CONFIG_ZBOOT_ROM_TEXT=0x0 +@@ -382,6 +384,8 @@ CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y + CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_ZRAM=m ++CONFIG_ZRAM_LZ4_COMPRESS=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_CRYPTOLOOP=m + CONFIG_BLK_DEV_DRBD=m + +From e547d7e94a85179d7ff7787eb95e29f0b0b657f4 Mon Sep 17 00:00:00 2001 +From: Gordon Hollingworth +Date: Mon, 22 Jun 2015 16:27:07 +0100 +Subject: [PATCH 80/85] Add rpi-ft5406 overlay Add rpi-ft5406 driver as module + +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 5 +++++ + arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 16 ++++++++++++++++ + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 5 files changed, 24 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts + +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +index 6947556..19eef3c 100644 +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -35,6 +35,7 @@ dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-ft5406-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 63da266..aa09b6c 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -396,6 +396,11 @@ Params: speed Display SPI bus speed + + xohms Touchpanel sensitivity (X-plate resistance) + ++Name: rpi-ft5406 ++Info: Official Raspberry Pi display touchscreen ++Load: dtoverlay=rpi-ft5406 ++Params: ++ + + Name: rpi-proto + Info: Configures the RPi Proto audio card +diff --git a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts +new file mode 100644 +index 0000000..40deab5 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts +@@ -0,0 +1,16 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ rpi_ft5406: rpi_ft5406 { ++ compatible = "rpi,rpi-ft5406"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7ef615c..7469d07 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -535,6 +535,7 @@ CONFIG_JOYSTICK_XPAD_FF=y + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m + CONFIG_INPUT_MISC=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index cacde14..f952ff2 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -528,6 +528,7 @@ CONFIG_JOYSTICK_XPAD_FF=y + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m + CONFIG_INPUT_MISC=y + +From 9dea271e610d0524fad677b9cccdd3be84ab25da Mon Sep 17 00:00:00 2001 +From: Gordon Hollingworth +Date: Tue, 23 Jun 2015 09:53:40 +0100 +Subject: [PATCH 81/85] Fix driver detection failure Check that the buffer + response is non-zero meaning the touchscreen was detected + +--- + drivers/input/touchscreen/rpi-ft5406.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c +index f55151b..d41851d 100644 +--- a/drivers/input/touchscreen/rpi-ft5406.c ++++ b/drivers/input/touchscreen/rpi-ft5406.c +@@ -184,7 +184,7 @@ static int ft5406_probe(struct platform_device *pdev) + + bcm_mailbox_property(&request, sizeof(request)); + +- if(request.request_code == VCMSG_REQUEST_SUCCESSFUL) ++ if(request.request_code == VCMSG_REQUEST_SUCCESSFUL && request.tag.val != 0) + { + dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", request.tag.val); + } + +From 8ad2b6ac33fca9a40238c42fdd2b5ed840c2fc8d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Jun 2015 13:24:01 +0100 +Subject: [PATCH 82/85] config: Enable 8250 serial port + +--- + arch/arm/configs/bcm2709_defconfig | 7 +++++++ + arch/arm/configs/bcmrpi_defconfig | 7 +++++++ + 2 files changed, 14 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7469d07..7e8643c 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -557,8 +557,15 @@ CONFIG_GAMEPORT_L4=m + CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=1 + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_TTY_PRINTK=y + CONFIG_HW_RANDOM=y + CONFIG_HW_RANDOM_BCM2835=m +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index f952ff2..0c25d8b 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -550,8 +550,15 @@ CONFIG_GAMEPORT_L4=m + CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=1 + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_TTY_PRINTK=y + CONFIG_HW_RANDOM=y + CONFIG_HW_RANDOM_BCM2835=m + +From cc78a5ef74fc67465fdacffe452a5fab5848b33c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Jun 2015 14:10:58 +0100 +Subject: [PATCH 83/85] config: Enable POWER_RESET_GPIO + +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7e8643c..46d56d7 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -606,6 +606,8 @@ CONFIG_W1_SLAVE_DS2781=m + CONFIG_W1_SLAVE_DS28E04=m + CONFIG_W1_SLAVE_BQ27000=m + CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y + # CONFIG_HWMON is not set + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 0c25d8b..e757db6 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -599,6 +599,8 @@ CONFIG_W1_SLAVE_DS2781=m + CONFIG_W1_SLAVE_DS28E04=m + CONFIG_W1_SLAVE_BQ27000=m + CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y + # CONFIG_HWMON is not set + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y + +From 01f5e319010c90770e0c8a87656c360a18a35208 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 26 Jun 2015 17:37:38 +0100 +Subject: [PATCH 84/85] bcm2708-vcio: Remove restriction of only a single + instance being open + +We need more than one process to be able to use mailbox interface (e.g. HW cursor in fbturbo and hello_fft). +Locking should be handled on each mailbox access +--- + drivers/mailbox/bcm2708-vcio.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c +index d91672b..06fb2c2f 100644 +--- a/drivers/mailbox/bcm2708-vcio.c ++++ b/drivers/mailbox/bcm2708-vcio.c +@@ -242,20 +242,9 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); + + /* Platform Device for Mailbox */ + +-/* +- * Is the device open right now? Used to prevent +- * concurent access into the same device +- */ +-static bool device_is_open; +- + /* This is called whenever a process attempts to open the device file */ + static int device_open(struct inode *inode, struct file *file) + { +- /* We don't want to talk to two processes at the same time */ +- if (device_is_open) +- return -EBUSY; +- +- device_is_open = true; + try_module_get(THIS_MODULE); + + return 0; +@@ -263,9 +252,6 @@ static int device_open(struct inode *inode, struct file *file) + + static int device_release(struct inode *inode, struct file *file) + { +- /* We're now ready for our next caller */ +- device_is_open = false; +- + module_put(THIS_MODULE); + + return 0; + +From 2cdae3dcbcca3d818f64d14580f22c67e32d851c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 26 Jun 2015 08:39:19 +0100 +Subject: [PATCH 85/85] BCM270X_DT: Create a "core" clock, use it for SPI and + sdhost + +--- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 1 + + arch/arm/boot/dts/bcm2708_common.dtsi | 6 +++--- + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 28 ++------------------------- + 6 files changed, 9 insertions(+), 29 deletions(-) + +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +index 0fa2210..3b252dc 100644 +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -124,6 +124,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts +index 3fd49d0..40fded1 100644 +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -118,6 +118,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +index 238bd65..e82fcb2 100755 +--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -14,5 +14,6 @@ + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + }; }; +diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi +index 8caa234..4a975dfd 100644 +--- a/arch/arm/boot/dts/bcm2708_common.dtsi ++++ b/arch/arm/boot/dts/bcm2708_common.dtsi +@@ -110,7 +110,7 @@ + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; +- clocks = <&clk_spi>; ++ clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +@@ -203,11 +203,11 @@ + clock-frequency = <250000000>; + }; -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index c5e51e8..fe71c50 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1050,7 +1050,7 @@ static irqreturn_t bcm2709_timer_interrupt(int irq, void *dev_id) +- clk_spi: clock@2 { ++ clk_core: clock@2 { + compatible = "fixed-clock"; + reg = <2>; + #clock-cells = <0>; +- clock-output-names = "spi"; ++ clock-output-names = "core"; + clock-frequency = <250000000>; + }; - static struct irqaction bcm2709_timer_irq = { - .name = "BCM2709 Timer Tick", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2709_timer_interrupt, +diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +index 8aaaf1f..24fa849 100644 +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -124,6 +124,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +index b408ab4..897204a 100644 +--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -16,7 +16,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + interrupts = <2 24>; +- clocks = <&clk_sdhost>; ++ clocks = <&clk_core>; + dmas = <&dma 13>, + <&dma 13>; + dma-names = "tx", "rx"; +@@ -29,22 +29,6 @@ + }; + + fragment@1 { +- target = <&clocks>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- clk_sdhost: sdhost { +- compatible = "fixed-clock"; +- reg = <0>; +- #clock-cells = <0>; +- clock-output-names = "sdhost"; +- clock-frequency = <250000000>; +- }; +- }; +- }; +- +- fragment@2 { + target = <&gpio>; + __overlay__ { + sdhost_pins: sdhost_pins { +@@ -54,7 +38,7 @@ + }; + }; + +- fragment@3 { ++ fragment@2 { + target = <&mmc>; + __overlay__ { + /* Find a way to disable the other driver */ +@@ -63,18 +47,10 @@ + }; + }; + +- fragment@4 { +- target-path = "/__overrides__"; +- __overlay__ { +- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; +- }; +- }; +- + __overrides__ { + overclock_50 = <&sdhost>,"brcm,overclock-50:0"; + force_pio = <&sdhost>,"brcm,force-pio?"; + pio_limit = <&sdhost>,"brcm,pio-limit:0"; + debug = <&sdhost>,"brcm,debug?"; +- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; + }; }; - diff --git a/projects/RPi2/patches/linux/linux-01-RPi_support.patch b/projects/RPi2/patches/linux/linux-01-RPi_support.patch index 0008aa8b30..a35c13d26b 100644 --- a/projects/RPi2/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi2/patches/linux/linux-01-RPi_support.patch @@ -1,7 +1,7 @@ -From 8e2bdce040b3459de0954cb2f212dea47549131c Mon Sep 17 00:00:00 2001 +From e9ee97a62574359de01411f0c74e23856e359952 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 01/77] Main bcm2708/bcm2709 linux port +Subject: [PATCH 01/85] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -310,7 +310,7 @@ index 0000000..67039c3 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c new file mode 100644 -index 0000000..cd252fa +index 0000000..4868cd37 --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -0,0 +1,304 @@ @@ -611,7 +611,7 @@ index 0000000..cd252fa + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + armctrl_pm_register(base, irq_start, resume_sources); @@ -653,7 +653,7 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 -index 0000000..d6659b0 +index 0000000..a209c58 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -0,0 +1,622 @@ @@ -1164,7 +1164,7 @@ index 0000000..d6659b0 + +static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, +}; + @@ -3577,7 +3577,7 @@ index 0000000..e33265d +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c new file mode 100644 -index 0000000..19d0601 +index 0000000..d135620 --- /dev/null +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -0,0 +1,801 @@ @@ -4120,7 +4120,7 @@ index 0000000..19d0601 + +static struct irqaction bcm2709_timer_irq = { + .name = "BCM2709 Timer Tick", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2709_timer_interrupt, +}; + @@ -7002,10 +7002,10 @@ index b5bedae..b0258e8 100644 mmc_pm_flag_t pm_caps; /* supported pm features */ -From aa090a771afa15310eb10d3209c190441f3ecefd Mon Sep 17 00:00:00 2001 +From 081ebd4ba394a354c03f7800b8d14519f165a0f9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Jun 2015 23:48:09 +0100 -Subject: [PATCH 02/77] power: Add power driver +Subject: [PATCH 02/85] power: Add power driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -7362,10 +7362,10 @@ index 0000000..bf22b26 + +#endif -From 9409d45ef7d82d4f0677ea1a16bb6e87d41ed8de Mon Sep 17 00:00:00 2001 +From ddd21104179e4df6cf77762b1a7f4dabe65cc808 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 Oct 2014 18:50:05 +0100 -Subject: [PATCH 03/77] Add bcm2708_gpio driver +Subject: [PATCH 03/85] Add bcm2708_gpio driver Signed-off-by: popcornmix @@ -7439,7 +7439,7 @@ index e7d5a29..5120994 100644 obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index d6659b0..c606853 100644 +index a209c58..6c1c616 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -298,6 +298,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -7476,7 +7476,7 @@ index d6659b0..c606853 100644 int ret; diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c new file mode 100644 -index 0000000..c1e9254 +index 0000000..e33265d --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c @@ -0,0 +1,426 @@ @@ -7788,7 +7788,7 @@ index 0000000..c1e9254 + +static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, +}; + @@ -7930,7 +7930,7 @@ index 0000000..7965a97 + +#endif diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 19d0601..6060a0d 100644 +index d135620..b173422 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -329,6 +329,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -7995,10 +7995,10 @@ index 0000000..fb69624 + +#endif -From 4b9ec02bb6738a9c29f6308c55cbcab58c2c88a3 Mon Sep 17 00:00:00 2001 +From 8957f79b301a70ab625baa2f9a4c613f871c3f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 19:11:03 +0200 -Subject: [PATCH 04/77] mailbox: bcm2708: Add bcm2708-vcio +Subject: [PATCH 04/85] mailbox: bcm2708: Add bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -8629,10 +8629,10 @@ index 0000000..cc284ed + +#endif -From c921ec1cd21e8a8eb4e453834a205e9da5dff30a Mon Sep 17 00:00:00 2001 +From c1a8c5708161961f248f228d25da578e90fe127f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 05/77] Add dwc_otg driver +Subject: [PATCH 05/85] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -9253,7 +9253,7 @@ index 8dd26e1..eef4847 100644 + mov pc, r8 +ENDPROC(__FIQ_Branch) diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index cd252fa..74bacb3 100644 +index 4868cd37..0429225 100644 --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -54,8 +54,12 @@ static void armctrl_mask_irq(struct irq_data *d) @@ -9297,7 +9297,7 @@ index cd252fa..74bacb3 100644 return 0; } diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c606853..4455f34 100644 +index 6c1c616..1735b72 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -254,12 +254,23 @@ static struct resource bcm2708_usb_resources[] = { @@ -69906,10 +69906,10 @@ index 0000000..cdc9963 +test_main(); +0; -From 560486db654a651cebb107628426d1705ef4cc20 Mon Sep 17 00:00:00 2001 +From 2aced0ae5562b3dc60806a3ba2799af134732bdb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 06/77] bcm2708 watchdog driver +Subject: [PATCH 06/85] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -70346,10 +70346,10 @@ index 0000000..8a27d68 +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); -From 7014dbd386a6ce510bd6b9fa3a3fcfc2bd89d237 Mon Sep 17 00:00:00 2001 +From 4a64377d42fac96be299fd210b0eb0bc3ba159b2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 07/77] bcm2708 framebuffer driver +Subject: [PATCH 07/85] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73788,10 +73788,10 @@ index 3c14e43..7626beb6a 100644 +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 5efe288a95d60bd10a162be79442d04b6f1d4079 Mon Sep 17 00:00:00 2001 +From b04b39dfe4cb2a287062d3b81287d9a9bf80e91a Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 08/77] dmaengine: Add support for BCM2708 +Subject: [PATCH 08/85] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73907,7 +73907,7 @@ Without this field set properly we get playback issues with I2S cards. create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 4455f34..6b0b6c4 100644 +index 1735b72..1622300 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -234,6 +234,73 @@ static struct amba_device *amba_devs[] __initdata = { @@ -73993,7 +73993,7 @@ index 4455f34..6b0b6c4 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 6060a0d..86ebfbe 100644 +index b173422..fee17e2 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -244,6 +244,73 @@ static struct amba_device *amba_devs[] __initdata = { @@ -75559,10 +75559,10 @@ index 0000000..2310e34 + +#endif /* _PLAT_BCM2708_DMA_H */ -From be30ad8849aa9fd6ffbe6f8198a5af4bb62c465f Mon Sep 17 00:00:00 2001 +From 34e4aa2e25b49261e2aa9d17a1ce767a3dfb90cf Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 09/77] MMC: added alternative MMC driver +Subject: [PATCH 09/85] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75637,7 +75637,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/mmc/host/bcm2835-mmc.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 6b0b6c4..5b10802 100644 +index 1622300..6257407 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -401,6 +401,34 @@ static struct platform_device bcm2708_gpio_device = { @@ -75686,7 +75686,7 @@ index 6b0b6c4..5b10802 100644 bcm2708_init_uart1(); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 86ebfbe..54c5444 100644 +index fee17e2..07750ed 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -421,6 +421,34 @@ static struct platform_device bcm2708_gpio_device = { @@ -77378,10 +77378,10 @@ index 0000000..b7c4883 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 81cff325dce6ba8765e23e542a219d3c9103a70b Mon Sep 17 00:00:00 2001 +From f1a7eefd17fbaf9335a5fdf6215d319b4042bb55 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 10/77] Adding bcm2835-sdhost driver, and an overlay to enable +Subject: [PATCH 10/85] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -79151,10 +79151,10 @@ index 0000000..eef8a24 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From 34fb9ba0190b9f9e18e6c136c64af8dcea23376d Mon Sep 17 00:00:00 2001 +From effb9e4dd94cc200500fb22061ede69047cceea7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 11/77] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 11/85] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix @@ -80479,10 +80479,10 @@ index 0000000..5325832 + +#endif /* VC_CMA_H */ -From 0e6896e85bf10d584b555ecae4b55f066a774b54 Mon Sep 17 00:00:00 2001 +From d83761e1a337d8eee9e9a196e23ceeefe51fff1e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 12/77] bcm2708: alsa sound driver +Subject: [PATCH 12/85] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -80539,7 +80539,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 sound/arm/vc_vchi_audioserv_defs.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5b10802..06271df 100644 +index 6257407..df32241 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -429,6 +429,57 @@ struct platform_device bcm2835_emmc_device = { @@ -80610,7 +80610,7 @@ index 5b10802..06271df 100644 if (!use_dt) { for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 54c5444..0f875ff 100644 +index 07750ed..62c95cb 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -449,6 +449,57 @@ struct platform_device bcm2835_emmc_device = { @@ -83324,10 +83324,10 @@ index 0000000..af3e6eb + +#endif // _VC_AUDIO_DEFS_H_ -From b2b5ab24c875e79e1fbb55ae76dc5a914fe301d0 Mon Sep 17 00:00:00 2001 +From 53e9a31fe01ae9460b2361ec93a54bac888d8f5f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 13/77] bcm2708 vchiq driver +Subject: [PATCH 13/85] bcm2708 vchiq driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -83493,7 +83493,7 @@ vchiq: Change logging level for inbound data create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 06271df..86011af 100644 +index df32241..ecf0524 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -376,6 +376,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -83550,7 +83550,7 @@ index 2e7e1bb..69674e9 100644 /* diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 0f875ff..bc1ee1c 100644 +index 62c95cb..de9feaa 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -396,6 +396,31 @@ static struct platform_device bcm2708_vcio_device = { @@ -96581,10 +96581,10 @@ index 0000000..b6bfa21 + return vchiq_build_time; +} -From 6290b45c0e5fa71d2131718d1b5770e7849aedeb Mon Sep 17 00:00:00 2001 +From 3f8c3cd61c11d730699b14ee1d64db95215487e8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 14/77] vc_mem: Add vc_mem driver +Subject: [PATCH 14/85] vc_mem: Add vc_mem driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -97590,10 +97590,10 @@ index 0000000..20a4753 + +#endif /* _VC_MEM_H */ -From e9ebded52208b6164753a82d268cd80e833e2737 Mon Sep 17 00:00:00 2001 +From 138483d8fb3cbfcad83b0c450e3c3eb2fca5a8de Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 15/77] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 15/85] vcsm: VideoCore shared memory service for BCM2835 Add experimental support for the VideoCore shared memory service. This allows user processes to allocate memory from VideoCore's @@ -102003,10 +102003,10 @@ index 0000000..0bfb42e +MODULE_DESCRIPTION("VideoCore SharedMemory Driver"); +MODULE_LICENSE("GPL v2"); -From 7f769de038003dcf3f6eff180e2e295888789dc2 Mon Sep 17 00:00:00 2001 +From 3b4d6cc19851307c0426fe31be9627558bb1b2cf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 16/77] Add hwrng (hardware random number generator) driver +Subject: [PATCH 16/85] Add hwrng (hardware random number generator) driver --- drivers/char/hw_random/Kconfig | 13 +++- @@ -102183,10 +102183,10 @@ index 0000000..340f004 +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); -From 68990b28334ea63cdc56bfe9663025dade9d7822 Mon Sep 17 00:00:00 2001 +From 8312a7efc6b5c8fe996e41f62adf6e9c71f7a5f8 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 17/77] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 17/85] 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 @@ -103039,10 +103039,10 @@ index 0000000..24563ec +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -From b359d4ff9144f1ee3f333eee7b49bab1c6d92c1f Mon Sep 17 00:00:00 2001 +From 4905ceea875bf96a9dbf4989347ed1d5e4e3875b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 18/77] Add cpufreq driver +Subject: [PATCH 18/85] Add cpufreq driver Signed-off-by: popcornmix --- @@ -103315,10 +103315,10 @@ index 0000000..6735da9 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 37e551cc949ea14042539b089e08df475bab0f59 Mon Sep 17 00:00:00 2001 +From 50ef992dbbc2e7e1c1a87a61b540c0b84f7cb3ee Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 19/77] Added hwmon/thermal driver for reporting core +Subject: [PATCH 19/85] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -103341,7 +103341,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 86011af..f2d9b03 100644 +index ecf0524..978aaff 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -505,6 +505,10 @@ static struct platform_device bcm2708_alsa_devices[] = { @@ -103365,7 +103365,7 @@ index 86011af..f2d9b03 100644 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index bc1ee1c..9631bdb 100644 +index de9feaa..0e5c8e3 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -525,6 +525,10 @@ static struct platform_device bcm2708_alsa_devices[] = { @@ -103615,10 +103615,10 @@ index 0000000..3bc80f1 + +module_platform_driver(bcm2835_thermal_driver); -From 4d5da3fa21e1d94e38644bf9a5493bb677854e42 Mon Sep 17 00:00:00 2001 +From 0e6c5417c62642c7481e57ce937007277fe31cfd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:41:33 +0100 -Subject: [PATCH 20/77] Add Chris Boot's spi driver. +Subject: [PATCH 20/85] Add Chris Boot's spi driver. spi: bcm2708: add device tree support @@ -103679,7 +103679,7 @@ index 4cbda0c..68e3706 100644 + Binds spidev driver to the SPI0 master endmenu diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f2d9b03..e3aa6fc 100644 +index 978aaff..31ad9da 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -34,6 +34,7 @@ @@ -103764,7 +103764,7 @@ index f2d9b03..e3aa6fc 100644 static void timer_set_mode(enum clock_event_mode mode, diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 9631bdb..5fb99b6 100644 +index 0e5c8e3..6874633 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -34,6 +34,7 @@ @@ -104530,10 +104530,10 @@ index 0000000..041b5e2 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 75d6625177ee7e4746baf70b60380069d58231ba Mon Sep 17 00:00:00 2001 +From 68bec2f411f5f7ea1720f555cadc7a5c6c214934 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 21/77] Add Chris Boot's i2c driver +Subject: [PATCH 21/85] Add Chris Boot's i2c driver i2c-bcm2708: fixed baudrate @@ -104594,7 +104594,7 @@ i2c-bcm2708: When using DT, leave the GPIO setup to pinctrl create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e3aa6fc..efb3544 100644 +index 31ad9da..26be516 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -83,6 +83,7 @@ static unsigned uart_clock = UART0_CLOCK; @@ -104674,7 +104674,7 @@ index e3aa6fc..efb3544 100644 +module_param(vc_i2c_override, bool, 0644); +MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 5fb99b6..8017c50 100644 +index 6874633..50843df 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -85,6 +85,7 @@ static unsigned uart_clock = UART0_CLOCK; @@ -105334,10 +105334,10 @@ index 0000000..8773203 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 87711afd62feac0850e063b279057c91fe0aabbf Mon Sep 17 00:00:00 2001 +From f039d3ed041c0fd3267b149ef476638142535ef3 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 22/77] bcm2835: add v4l2 camera device +Subject: [PATCH 22/85] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -112664,10 +112664,10 @@ index 0000000..9d1d11e + +#endif /* MMAL_VCHIQ_H */ -From 0ecc87e37d9107eb533346a4a482bbf78920d16c Mon Sep 17 00:00:00 2001 +From 35af37046308a29d529e83d908c1fea9cd01a8a2 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 23 Jan 2015 14:48:55 +0000 -Subject: [PATCH 23/77] scripts/dtc: Update to upstream version with overlay +Subject: [PATCH 23/85] scripts/dtc: Update to upstream version with overlay patches --- @@ -117880,10 +117880,10 @@ index 54d4e904..d644002 100644 -#define DTC_VERSION "DTC 1.4.0-dirty" +#define DTC_VERSION "DTC 1.4.1-g36c70742" -From 4cccd63c16e3ef4e2a35144e2806d1d1c56bc381 Mon Sep 17 00:00:00 2001 +From 7b42e6d4640654b00e46f0b14a2f4d4f9979610e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 24/77] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 24/85] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -118368,10 +118368,10 @@ index 0000000..3dff948 + return (($val eq 'y') || ($val eq '1')); +} -From 780d72c0e43679ff58f9f3f005ef17a5fa79ee9f Mon Sep 17 00:00:00 2001 +From 23bd48a5f3cae21a2074ef421a675dfba54866de Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 25/77] fdt: Add support for the CONFIG_CMDLINE_EXTEND option +Subject: [PATCH 25/85] fdt: Add support for the CONFIG_CMDLINE_EXTEND option --- drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- @@ -118426,10 +118426,10 @@ index cde35c5d01..dd7fbfe 100644 pr_debug("Command line is: %s\n", (char*)data); -From 7ff1afbc6732a16d87c5640be8fec1de73a39770 Mon Sep 17 00:00:00 2001 +From 4c4001e3bc03206e4d87273ac410a719c7a128b4 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 26/77] BCM2708: Add core Device Tree support +Subject: [PATCH 26/85] BCM2708: Add core Device Tree support Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -122306,10 +122306,10 @@ index 0000000..66a98f6 + }; +}; -From 4bd17cf8893beb8fb36fe6e321abfe2bc091eb17 Mon Sep 17 00:00:00 2001 +From 5cbd38e967d11494dbf7d401bfcce0240a176f1f Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 27/77] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 27/85] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -122402,10 +122402,10 @@ index fb795c3..fa72af0 100644 #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -From 54459bf0dcbd9019a1bc98cdc77a5c37811c1be5 Mon Sep 17 00:00:00 2001 +From 9907bcbcbae0e355d82cbc29e4f9667fb6fadfac Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 30/77] Speed up console framebuffer imageblit function +Subject: [PATCH 30/85] 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 @@ -122614,10 +122614,10 @@ index a2bb276..436494f 100644 start_index, pitch_index); } else -From b78abfc78e582f82fda5e69816eaa97b1097c853 Mon Sep 17 00:00:00 2001 +From c50184c27d8c47aa92288d11c79ccbc193f91a74 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 31/77] Allow mac address to be set in smsc95xx +Subject: [PATCH 31/85] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -122708,10 +122708,10 @@ index 26423ad..e29a323 100644 if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, dev->net->dev_addr) == 0) { -From 468a5ebe451a5e3bc693fdbd67173f2fadb7d217 Mon Sep 17 00:00:00 2001 +From b579f8fd561c7347d6354d3f7fc6880ac6b49e7f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 32/77] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 32/85] 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 @@ -122741,7 +122741,7 @@ w1-gpio: Sort out the pullup/parasitic power tangle 7 files changed, 157 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index efb3544..c7b4b61 100644 +index 26be516..55d2889 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -36,6 +36,7 @@ @@ -122814,7 +122814,7 @@ index efb3544..c7b4b61 100644 module_param(vc_i2c_override, bool, 0644); MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 8017c50..03e208b 100644 +index 50843df..0a5e4188 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -36,6 +36,7 @@ @@ -123109,10 +123109,10 @@ index d58594a..feae942 100644 unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From 00d8013737c9e736f70e04e07b761517559e495e Mon Sep 17 00:00:00 2001 +From 8828223a011c97121c5824e4a9056ebfdb178612 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 34/77] config: Enable CONFIG_MEMCG, but leave it disabled (due +Subject: [PATCH 34/85] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -123167,10 +123167,10 @@ index a04225d..a2ef8af 100644 /** -From 5e192d7296061c5d70da39b3fbd1eeedef467923 Mon Sep 17 00:00:00 2001 +From 9028029fe919c229779c848fd2a645bf02d2d959 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:33:38 +0100 -Subject: [PATCH 35/77] ASoC: Add support for BCM2708 +Subject: [PATCH 35/85] ASoC: Add support for BCM2708 This driver adds support for digital audio (I2S) for the BCM2708 SoC that is used by the @@ -124313,10 +124313,10 @@ index 0000000..6fdcbc1 + +#endif -From 355253cae3f2e9200926bfeb8d21646600d0768e Mon Sep 17 00:00:00 2001 +From 2cd4bdd8e03b8a9ce11d39741d5670d10b58f13e Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 36/77] ASoC: Add support for PCM5102A codec +Subject: [PATCH 36/85] ASoC: Add support for PCM5102A codec Some definitions to support the PCM5102A codec by Texas Instruments. @@ -124441,10 +124441,10 @@ index 0000000..126f1e9 +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From 49e137bd21361ad8f4439f35956ceab424013411 Mon Sep 17 00:00:00 2001 +From 214e3f42b42cc6512664e15c2e6d48c44397ff30 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:04:54 +0100 -Subject: [PATCH 37/77] BCM2708: Add I2S support to board file +Subject: [PATCH 37/85] BCM2708: Add I2S support to board file Adds the required initializations for I2S to the board file of mach-bcm2708. @@ -124464,7 +124464,7 @@ See: #1004 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c7b4b61..dc57983 100644 +index 55d2889..01f2de7 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -616,6 +616,28 @@ static struct platform_device bcm2835_thermal_device = { @@ -124533,10 +124533,10 @@ index a3b65dc..a515992 100644 for (i = 0; i <= 1; i++) { void __iomem *base; -From 5786483930fcb7863012d8bb81d1f73a67b258da Mon Sep 17 00:00:00 2001 +From 7cf3e108eda83b02d6dcf336c5e1842b36fab753 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 38/77] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 38/85] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -124685,10 +124685,10 @@ index 0000000..4b70b45 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 47d7a2a48fd4b2da2f9400de4307febe755b2ef2 Mon Sep 17 00:00:00 2001 +From 895fd13e0cf6dc5febf489837d068825db70d7ac Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:21:34 +0100 -Subject: [PATCH 39/77] BCM2708: Add HifiBerry DAC to board file +Subject: [PATCH 39/85] BCM2708: Add HifiBerry DAC to board file This adds the initalization of the HifiBerry DAC to the mach-bcm2708 board file. @@ -124699,7 +124699,7 @@ Signed-off-by: Florian Meier 1 file changed, 19 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index dc57983..ef7c48d 100644 +index 01f2de7..1d9b788 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -638,6 +638,20 @@ static struct platform_device bcm2708_i2s_device = { @@ -124736,10 +124736,10 @@ index dc57983..ef7c48d 100644 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; -From 403dc5c76505dd5813174532b2f032e52cbe06b8 Mon Sep 17 00:00:00 2001 +From e01a75a2784a659fbd297dc849a2e25ae120e35c Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 6 Dec 2013 20:50:28 +0100 -Subject: [PATCH 40/77] ASoC: BCM2708: Add support for RPi-DAC +Subject: [PATCH 40/85] ASoC: BCM2708: Add support for RPi-DAC This adds a machine driver for the RPi-DAC. @@ -124757,7 +124757,7 @@ Signed-off-by: Florian Meier create mode 100644 sound/soc/codecs/pcm1794a.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index ef7c48d..be27073 100644 +index 1d9b788..6d53beb 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125034,10 +125034,10 @@ index 0000000..b4eaa44 +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From 0418e9bd3eab8e21b5d69ed0b7899dd5a80263f1 Mon Sep 17 00:00:00 2001 +From 4250d743113025b72b841b0b801aee698d8761ef Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 41/77] ASoC: wm8804: Implement MCLK configuration options, add +Subject: [PATCH 41/85] 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 @@ -125077,10 +125077,10 @@ index 1e403f6..d4efa85 100644 #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ -From 82c2f5a297701240bf5a77611d2d93c041497246 Mon Sep 17 00:00:00 2001 +From bb771a22197d65ccab827fe36a8699d18b961693 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 42/77] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 42/85] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -125345,10 +125345,10 @@ index 0000000..92e9e46 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From df14e52cd5e411324c58e28ec158f503d4905dbb Mon Sep 17 00:00:00 2001 +From 6081cb2ed879b4e99cd91a36331460bf6ec2e3f0 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Thu, 16 Jan 2014 07:26:08 +0100 -Subject: [PATCH 43/77] BCM2708: Added support for HiFiBerry Digi board Board +Subject: [PATCH 43/85] BCM2708: Added support for HiFiBerry Digi board Board initalization by I2C Signed-off-by: Daniel Matuschek @@ -125357,7 +125357,7 @@ Signed-off-by: Daniel Matuschek 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index be27073..2a33663 100644 +index 6d53beb..a062d7f 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,21 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125395,10 +125395,10 @@ index be27073..2a33663 100644 bcm_register_device_dt(&snd_rpi_dac_device); bcm_register_device_dt(&snd_pcm1794a_codec_device); -From d8de9644604c68b7148b023608d70d8ac3bf466f Mon Sep 17 00:00:00 2001 +From 6d26e73e4afc0f00e514498776ff0e24d595f919 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Thu, 16 Jan 2014 07:36:35 +0100 -Subject: [PATCH 44/77] ASoC: wm8804: Set idle_bias_off to false Idle bias has +Subject: [PATCH 44/85] ASoC: wm8804: Set idle_bias_off to false Idle bias has been change to remove warning on driver startup Signed-off-by: Daniel Matuschek @@ -125420,10 +125420,10 @@ index d4efa85..f3f26a2 100644 .dapm_widgets = wm8804_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), -From 40f01186460630fa704c88adbefbc347e5e402e4 Mon Sep 17 00:00:00 2001 +From 76c18d6844de1ab292a34baf6c96566ba05db024 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 45/77] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 45/85] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -125440,7 +125440,7 @@ limit of 0dB for this control. create mode 100644 sound/soc/bcm/iqaudio-dac.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 2a33663..957504e 100644 +index a062d7f..a51a6168 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -681,6 +681,22 @@ static struct platform_device snd_pcm1794a_codec_device = { @@ -125631,10 +125631,10 @@ index 0000000..aff7377 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From 5d1014e6dfa91f7f4b07851eefaa0a8bc544fda8 Mon Sep 17 00:00:00 2001 +From 712b1f5ed46d64ace42306b175e84247ad466a86 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 46/77] vmstat: Workaround for issue where dirty page count +Subject: [PATCH 46/85] vmstat: Workaround for issue where dirty page count goes negative See: @@ -125661,10 +125661,10 @@ index 82e7db7..f87d16d 100644 static inline void __inc_zone_page_state(struct page *page, -From 462ac627ee409f190f5519727c80942afafd0d6d Mon Sep 17 00:00:00 2001 +From 8fe8c0d0126e286164be182add69b996012753b6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 47/77] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 47/85] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -125700,10 +125700,10 @@ index bfbe1be..a738b25 100644 ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From 6a68d9854eed6f1c5741aff8466cb5877deecd54 Mon Sep 17 00:00:00 2001 +From db5d9cfda38672c42a52574924297223f44ab568 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 48/77] Added support for HiFiBerry DAC+ +Subject: [PATCH 48/85] 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. @@ -125716,7 +125716,7 @@ a different codec chip (PCM5122), therefore a new driver is necessary. create mode 100644 sound/soc/bcm/hifiberry_dacplus.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 957504e..90459b8 100644 +index a51a6168..d421a89 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -652,6 +652,20 @@ static struct platform_device snd_pcm5102a_codec_device = { @@ -125914,10 +125914,10 @@ index 0000000..c63387b +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); +MODULE_LICENSE("GPL v2"); -From 1ca3777a5f3e17847136937e1bab1717281c73ca Mon Sep 17 00:00:00 2001 +From f929e0ea9b902ca56a57439ad326a7fe1bc190d2 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 49/77] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 49/85] 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. @@ -125947,7 +125947,7 @@ Some code to load the driver based on device-tree-overlays was missing. This is create mode 100644 sound/soc/codecs/tas5713.h diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 90459b8..785cf1a 100644 +index d421a89..363b9c5 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -681,6 +681,20 @@ static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { @@ -126786,10 +126786,10 @@ index 0000000..8f019e0 + +#endif /* _TAS5713_H */ -From 06c9b132b1340b495048f8814be13fe71b5cd77e Mon Sep 17 00:00:00 2001 +From 0d10a0439bbde5d1bf74427cb93a55a29ea7ec12 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Apr 2015 19:14:18 +0100 -Subject: [PATCH 50/77] bcm2708: Allow option card devices to be configured via +Subject: [PATCH 50/85] bcm2708: Allow option card devices to be configured via DT If the kernel is built with Device Tree support, and if a DT blob @@ -126814,10 +126814,10 @@ index 03fa1cb..c816526 100644 static struct platform_driver bcm2835_i2s_driver = { .probe = bcm2835_i2s_probe, -From a9fff3c9005e6658977bd5e7df92114e70e1f813 Mon Sep 17 00:00:00 2001 +From 8eaeacdeca7966b710fbdefad07bd3f0de14447c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 18:45:39 +0100 -Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards +Subject: [PATCH 51/85] Adding Device Tree support for some RPi audio cards --- arch/arm/mach-bcm2709/bcm2709.c | 143 ++++++++++++++++++++++++++++++++++++++ @@ -126829,7 +126829,7 @@ Subject: [PATCH 51/77] Adding Device Tree support for some RPi audio cards 6 files changed, 232 insertions(+) diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 03e208b..2ae79d9 100644 +index 0a5e4188..57e1f3d 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -636,6 +636,115 @@ static struct platform_device bcm2835_thermal_device = { @@ -127180,10 +127180,10 @@ index 126f1e9..7c6598e 100644 }; -From 9518bd237c4fb516a0ec78f7ec81e5784f8425e0 Mon Sep 17 00:00:00 2001 +From 7dfce43c57cc203535e6098fcc1e8977d85ddeac Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Wed, 29 Oct 2014 23:30:30 -0700 -Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used +Subject: [PATCH 52/85] Added support to reserve/enable a GPIO pin to be used from pps-gpio module (LinuxPPS). Enable PPS modules in default config for RPi. @@ -127193,7 +127193,7 @@ Subject: [PATCH 52/77] Added support to reserve/enable a GPIO pin to be used 2 files changed, 54 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 785cf1a..e42f5a5 100644 +index 363b9c5..74ec578 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -37,6 +37,7 @@ @@ -127256,7 +127256,7 @@ index 785cf1a..e42f5a5 100644 +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 2ae79d9..95223ff 100644 +index 57e1f3d..721559b 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -37,6 +37,7 @@ @@ -127319,10 +127319,10 @@ index 2ae79d9..95223ff 100644 +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); -From 6831eded602a01774036cb24d3195dbbd51f9135 Mon Sep 17 00:00:00 2001 +From a3936496fcb450e52716292427b60570447b6b03 Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 53/77] Update ds1307 driver for device-tree support +Subject: [PATCH 53/85] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -127349,10 +127349,10 @@ index 4ffabb3..c6789a7 100644 .driver = { .name = "rtc-ds1307", -From 47ca2482bc03a888435d35139cd2f5989354ee1b Mon Sep 17 00:00:00 2001 +From eed1565f9cb449204057486a48c39f917c269fa1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 54/77] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 54/85] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -127463,10 +127463,10 @@ index 0000000..2ca2b98 +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); -From 38c278bba1388423ba1508d0712babb717685530 Mon Sep 17 00:00:00 2001 +From 494f12e28e415f895a337fcfcfe45cd530c1cc99 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Jun 2014 17:19:27 +0100 -Subject: [PATCH 55/77] bcm2709: Simplify and strip down IRQ handler +Subject: [PATCH 55/85] bcm2709: Simplify and strip down IRQ handler --- arch/arm/include/asm/entry-macro-multi.S | 2 + @@ -127685,10 +127685,10 @@ index d08591b..08d184c 100644 +1: get_irqnr_and_base r0, r2, r6, lr + .endm -From a69146643bae1215ab2860b9646f0f380bd3c50f Mon Sep 17 00:00:00 2001 +From 3e2b399180b8f5a0090134ba1889443945a13cf6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Feb 2015 11:17:53 +0000 -Subject: [PATCH 56/77] Fix LED "input" trigger implementation for 3.19 +Subject: [PATCH 56/85] Fix LED "input" trigger implementation for 3.19 --- drivers/leds/leds-gpio.c | 10 +++++++++- @@ -127775,10 +127775,10 @@ index 9a2b000..60accc5 100644 /* Set LED brightness level */ /* Must not sleep, use a workqueue if needed */ -From d8f6c527b14c125e58173e8bd0e7c6c59bab4919 Mon Sep 17 00:00:00 2001 +From 5c958120f03edcedf40ff2d07b825229d348d26b Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 57/77] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 57/85] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -127800,10 +127800,10 @@ index 8d908e3..7a1900d 100644 .can_sleep = false, }; -From bf8c97c74733237b219a22da649cb6cb7029615d Mon Sep 17 00:00:00 2001 +From 784bb9af1427a9b17cd6894cff2dc3c2eb8c4735 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 4 Feb 2015 10:02:24 +0000 -Subject: [PATCH 58/77] pinctrl-bcm2835: bcm2835_gpio_direction_output must set +Subject: [PATCH 58/85] pinctrl-bcm2835: bcm2835_gpio_direction_output must set the value --- @@ -127831,10 +127831,10 @@ index 7a1900d..62f85aa 100644 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -From 1262602778ac5adbe798e7ace41b22262a578fcf Mon Sep 17 00:00:00 2001 +From c885a17c2aee5d4f00b2dc950bcdadd3ed7bd7cb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 59/77] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 +Subject: [PATCH 59/85] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -127980,10 +127980,10 @@ index 62f85aa..c7cf266 100644 }, }; -From fd7e740e1c83bd550444192a8beff54ea5291c50 Mon Sep 17 00:00:00 2001 +From ead5cb2483b2fb0943121dfb69786e6ec1c20ced Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 60/77] pinctrl-bcm2835: Only request the interrupts listed in +Subject: [PATCH 60/85] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -128010,10 +128010,10 @@ index c7cf266..986779a 100644 pc->irq_data[i].irqgroup = i; -From c24fbfc7a5bc3c7cb35f51d0a40ad25b98a8a422 Mon Sep 17 00:00:00 2001 +From 15eff0b34d5eba282dfa1fc0303bb66f08d237ad Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 61/77] enc28j60: Add device tree compatible string and an +Subject: [PATCH 61/85] enc28j60: Add device tree compatible string and an overlay --- @@ -128047,10 +128047,10 @@ index b1b5f66..c6b6e1a 100644 .probe = enc28j60_probe, .remove = enc28j60_remove, -From 331cdec0de30933d5e7839f0e3def9b98d3fa968 Mon Sep 17 00:00:00 2001 +From 4c1fa7e5d19f7f006576def6cdf591c325d9a167 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 62/77] Add driver for rpi-proto +Subject: [PATCH 62/85] 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 @@ -128265,10 +128265,10 @@ index 0000000..c6e45a0 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From 2079392f1bde4f50d8c1ad65c2f7b52a6ff34848 Mon Sep 17 00:00:00 2001 +From 3a796c13d6cf8d6cd51170b34944b18d50f30bba Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Thu, 2 Apr 2015 12:22:55 +0100 -Subject: [PATCH 63/77] Add Device Tree support for RPi-DAC. +Subject: [PATCH 63/85] Add Device Tree support for RPi-DAC. --- sound/soc/bcm/rpi-dac.c | 21 +++++++++++++++++++++ @@ -128343,10 +128343,10 @@ index b4eaa44..afe1b41 100644 }; -From 4725644a3f7c09811486c1324f9653e79ecbdcb7 Mon Sep 17 00:00:00 2001 +From 69754b2aaecf3eb2dd3bef6f68d7e7787a9dc6cc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 64/77] config: Add default configs +Subject: [PATCH 64/85] config: Add default configs --- arch/arm/configs/bcm2709_defconfig | 1204 ++++++++++++++++++++++++++++++++++++ @@ -130771,10 +130771,10 @@ index 0000000..6a41231 +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 7de29243d1ac891a526c77e17129d6e2d547361d Mon Sep 17 00:00:00 2001 +From c6ed3e60b55412cdf8e130053f600c05c3e1460a Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 65/77] smsx95xx: fix crimes against truesize +Subject: [PATCH 65/85] 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. @@ -130809,10 +130809,10 @@ index e29a323..aff63dc usbnet_skb_return(dev, ax_skb); } -From 4772a6e4cc3921cb41515b7b0a91ad646d1491aa Mon Sep 17 00:00:00 2001 +From ef3796d3a8cdb18963e2eeb04fa493abca03af14 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 66/77] smsc95xx: Disable turbo mode by default +Subject: [PATCH 66/85] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- @@ -130832,10 +130832,10 @@ index aff63dc..08a8a8c 100755 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From 9d1fbb7b2dbe16c506f54984c361a55d1b2603fb Mon Sep 17 00:00:00 2001 +From 831d4392562d46f0d9a55c755c1363b84832af2a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Apr 2015 19:30:22 +0100 -Subject: [PATCH 67/77] Add blk_pos parameter to mmc multi_io_quirk callback +Subject: [PATCH 67/85] Add blk_pos parameter to mmc multi_io_quirk callback --- drivers/mmc/card/block.c | 1 + @@ -130918,10 +130918,10 @@ index b0258e8..d3cdad9 100644 struct mmc_card; -From d8492b31751e7eda1b9b2c92dd381b5d7df1679d Mon Sep 17 00:00:00 2001 +From a20e01130fd949a90e5e91821edd63581e95cc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 29 Apr 2015 17:24:02 +0200 -Subject: [PATCH 68/77] bcm2835: bcm2835_defconfig +Subject: [PATCH 68/85] bcm2835: bcm2835_defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -132251,10 +132251,10 @@ index 31cb073..2e8a95a 100644 # CONFIG_XZ_DEC_ARM is not set # CONFIG_XZ_DEC_ARMTHUMB is not set -From 4e2ed4a7a7971ea763017bc6234d30cdc5bfb984 Mon Sep 17 00:00:00 2001 +From f06ed380a59b6b336820510c6716db5bd9928e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 1 May 2015 23:00:15 +0200 -Subject: [PATCH 69/77] BCM270x_DT: Add mailbox bcm2708-vcio +Subject: [PATCH 69/85] BCM270x_DT: Add mailbox bcm2708-vcio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -132269,7 +132269,7 @@ Signed-off-by: Noralf Trønnes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e42f5a5..de2f93a 100644 +index 74ec578..5527d5c 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -870,7 +870,7 @@ void __init bcm2708_init(void) @@ -132282,7 +132282,7 @@ index e42f5a5..de2f93a 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 95223ff..350647a 100644 +index 721559b..4a00561 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -890,7 +890,7 @@ void __init bcm2709_init(void) @@ -132295,10 +132295,10 @@ index 95223ff..350647a 100644 #ifdef CONFIG_BCM2708_GPIO bcm_register_device_dt(&bcm2708_gpio_device); -From 2867da0a54803e6eb8e748b63a474877e16899b0 Mon Sep 17 00:00:00 2001 +From ad4a25a7e27ffac5b4f5b9eba60c8588ec2e04c1 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 70/77] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 70/85] rpi-ft5406: Add touchscreen driver for pi LCD display --- drivers/input/touchscreen/Kconfig | 7 + @@ -132615,10 +132615,10 @@ index cc284ed..d3ea839 100644 VCMSG_SET_CURSOR_STATE = 0x00008011, }; -From f794a0549b3a54cbe6dcfef3b37c421dda92d13a Mon Sep 17 00:00:00 2001 +From 4d11ea5e022aa484a8884a54d08bb5d3f26bed0b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 71/77] Improve __copy_to_user and __copy_from_user performance +Subject: [PATCH 71/85] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use optimised memcpy/memmove/memcmp/memset implementations. @@ -134142,10 +134142,10 @@ index 3e58d71..0622891 100644 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From 5787d557e062cdac5f3e19ccd60394dc6df38aab Mon Sep 17 00:00:00 2001 +From 961d37927bd0de6c86334892d19341f427a6d543 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 27 May 2015 17:22:15 +0100 -Subject: [PATCH 72/77] bcm2835-audio: Create the platform device if the DT +Subject: [PATCH 72/85] bcm2835-audio: Create the platform device if the DT node is disabled For backwards compatibility, allow the built-in ALSA driver to be enabled @@ -134157,7 +134157,7 @@ node in DT. 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index de2f93a..cfc4f13 100644 +index 5527d5c..937c2d3 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -898,8 +898,14 @@ void __init bcm2708_init(void) @@ -134178,7 +134178,7 @@ index de2f93a..cfc4f13 100644 bcm_register_device_dt(&bcm2708_spi_device); diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 350647a..507ff52 100644 +index 4a00561..dec8043 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -918,8 +918,14 @@ void __init bcm2709_init(void) @@ -134199,10 +134199,10 @@ index 350647a..507ff52 100644 bcm_register_device_dt(&bcm2708_spi_device); -From 070a6f51cd5f81f635cfcccd3452ee5f252a7ee4 Mon Sep 17 00:00:00 2001 +From 729ca6d5fc85ce618d61af67f400d1f20ddd2fbd 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 73/77] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 73/85] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -134261,10 +134261,10 @@ index 70f2f39..f7fdacd 100644 static const char * const bcm2835_compat[] = { -From 3add74da14e27d18ef276f66c55a69e6dc014216 Mon Sep 17 00:00:00 2001 +From 9a645229a554cd9b0f211bd15310ceb4c61f32b2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Jun 2015 17:47:27 +0100 -Subject: [PATCH 74/77] platform: Add force_core command line setting to boot +Subject: [PATCH 74/85] platform: Add force_core command line setting to boot from a different core number --- @@ -134315,7 +134315,7 @@ index a366275..90805a6 100644 writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index 507ff52..c5e51e8 100644 +index dec8043..fe71c50 100644 --- a/arch/arm/mach-bcm2709/bcm2709.c +++ b/arch/arm/mach-bcm2709/bcm2709.c @@ -96,6 +96,7 @@ static unsigned w1_gpio_pin = W1_GPIO; @@ -134335,112 +134335,2041 @@ index 507ff52..c5e51e8 100644 module_param(serial, uint, 0644); module_param(uart_clock, uint, 0644); -From a283be0c98260b1f29c8c46df7e8fb2a9cdaf5a8 Mon Sep 17 00:00:00 2001 +From 0733a658a5b233abd9da4157ab2bfd52ceebf404 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 18 Jun 2015 17:46:17 +0100 -Subject: [PATCH 75/77] mach-bcm270x: Enable the building of pinctrl-bcm2835 +Subject: [PATCH 75/85] mach-bcm270x: Enable the building of pinctrl-bcm2835 --- drivers/pinctrl/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index 6eadf04..ca6e1be 100644 +index 6eadf04..9119513 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o -+obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ - obj-$(CONFIG_ARCH_BCM) += bcm/ - obj-$(CONFIG_ARCH_BERLIN) += berlin/ - obj-y += freescale/ - -From fd08db11f15960c30449a5a2cb14d3ab7fd470ea Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 18 Jun 2015 18:06:28 +0100 -Subject: [PATCH 76/77] squash: Fix inconsistency in pinctrl Makefile patch - ---- - drivers/pinctrl/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index ca6e1be..9119513 100644 ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -38,7 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o - obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o - obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o - --obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_MACH_BCM2709) += bcm/ +obj-$(CONFIG_ARCH_BCM2708)$(CONFIG_ARCH_BCM2709) += bcm/ obj-$(CONFIG_ARCH_BCM) += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-y += freescale/ -From 05376fce25aaab4f47182a5af04928bfa06f30d6 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 18 Jun 2015 19:53:58 +0100 -Subject: [PATCH 77/77] platform: squash: Remove IRQF_DISABLED +From 3c7dc45eee7c0339b72469bf6674e842385b7ab9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 19 Jun 2015 16:41:39 +0100 +Subject: [PATCH 76/85] BCM270X_DT: Document the i2s-mmap overlay --- - arch/arm/mach-bcm2708/armctrl.c | 2 +- - arch/arm/mach-bcm2708/bcm2708.c | 2 +- - arch/arm/mach-bcm2708/bcm2708_gpio.c | 2 +- - arch/arm/mach-bcm2709/bcm2709.c | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) + arch/arm/boot/dts/overlays/README | 6 ++++++ + 1 file changed, 6 insertions(+) -diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c -index 74bacb3..0429225 100644 ---- a/arch/arm/mach-bcm2708/armctrl.c -+++ b/arch/arm/mach-bcm2708/armctrl.c -@@ -305,7 +305,7 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, - irq_set_chip(irq, &armctrl_chip); - irq_set_chip_data(irq, (void *)data); - irq_set_handler(irq, handle_level_irq); -- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 3e08f98..7fa6d33 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -260,6 +260,12 @@ Params: ds1307 Select the DS1307 device + pcf8563 Select the PCF8563 device + + ++Name: i2s-mmap ++Info: Enables mmap support in the bcm2708-i2s driver ++Load: dtoverlay=i2s-mmap ++Params: ++ ++ + Name: iqaudio-dac + Info: Configures the IQaudio DAC audio card + Load: dtoverlay=iqaudio-dac + +From d9fa11803a0d2e3b1eaf4041ddd0ca5651300d96 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 17 Jun 2015 11:36:53 +0100 +Subject: [PATCH 77/85] bcm2835-sdhost: Improve error handling and recovery + +1) Expose the hw_reset method to the MMC framework, removing many + internal calls by the driver. + +2) Reduce overclock setting on error. + +3) Increase timeout to cope with high capacity cards. + +4) Add properties and parameters to control pio_limit and debug. + +5) Reduce messages at probe time. +--- + arch/arm/boot/dts/overlays/README | 8 +- + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 4 +- + drivers/mmc/host/bcm2835-sdhost.c | 578 ++++++++++++++++++-------- + 3 files changed, 404 insertions(+), 186 deletions(-) + +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 7fa6d33..63da266 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -408,7 +408,13 @@ Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock + Load: dtoverlay=sdhost,= + Params: overclock_50 Clock (in MHz) to use when the MMC framework + requests 50MHz +- force_pio Disable DMA support ++ ++ force_pio Disable DMA support (default off) ++ ++ pio_limit Number of blocks above which to use DMA ++ (default 2) ++ ++ debug Enable debug output (default off) + + + Name: spi-bcm2708 +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +index 8fb28e9..b408ab4 100644 +--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -22,6 +22,7 @@ + dma-names = "tx", "rx"; + brcm,delay-after-stop = <0>; + brcm,overclock-50 = <0>; ++ brcm,pio-limit = <2>; + status = "okay"; + }; + }; +@@ -70,9 +71,10 @@ + }; + + __overrides__ { +- delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; + overclock_50 = <&sdhost>,"brcm,overclock-50:0"; + force_pio = <&sdhost>,"brcm,force-pio?"; ++ pio_limit = <&sdhost>,"brcm,pio-limit:0"; ++ debug = <&sdhost>,"brcm,debug?"; + sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; + }; + }; +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +index eef8a24..6277e43 100644 +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -90,9 +90,8 @@ + /* Reserved */ + #define SDHSTS_DATA_FLAG 0x01 + +-#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) ++#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR|SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) + #define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) +-/* SDHSTS_CRC7_ERROR - ignore this as MMC cards generate this spuriously */ + + #define SDHCFG_BUSY_IRPT_EN (1<<10) + #define SDHCFG_BLOCK_IRPT_EN (1<<8) +@@ -111,16 +110,7 @@ + #define SDEDM_READ_THRESHOLD_SHIFT 14 + #define SDEDM_THRESHOLD_MASK 0x1f + +-/* the inclusive limit in bytes under which PIO will be used instead of DMA */ +-#ifdef CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER +-#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_SDHOST_PIO_DMA_BARRIER +-#else +-#define PIO_DMA_BARRIER 0 +-#endif +- +-#define MIN_FREQ 400000 +-#define TIMEOUT_VAL 0xE +-#define BCM2835_SDHOST_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) ++#define MHZ 1000000 + + #ifndef BCM2708_PERI_BASE + #define BCM2708_PERI_BASE 0x20000000 +@@ -138,19 +128,20 @@ struct bcm2835_host { + + struct mmc_host *mmc; + +- u32 timeout; ++ u32 pio_timeout; /* In jiffies */ + + int clock; /* Current clock speed */ + + bool slow_card; /* Force 11-bit divisor */ + + unsigned int max_clk; /* Max possible freq */ +- unsigned int timeout_clk; /* Timeout freq (KHz) */ + + struct tasklet_struct finish_tasklet; /* Tasklet structures */ + + struct timer_list timer; /* Timer for timeouts */ + ++ struct timer_list pio_timer; /* PIO error detection timer */ ++ + struct sg_mapping_iter sg_miter; /* SG state for PIO */ + unsigned int blocks; /* remaining PIO blocks */ + +@@ -170,6 +161,10 @@ struct bcm2835_host { + + unsigned int use_busy:1; /* Wait for busy interrupt */ + ++ unsigned int reduce_overclock:1; /* ...at the next opportunity */ ++ ++ unsigned int debug:1; /* Enable debug output */ ++ + u32 thread_isr; + + /*DMA part*/ +@@ -185,7 +180,8 @@ struct bcm2835_host { + struct timeval stop_time; /* when the last stop was issued */ + u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ +- u32 max_overclock; /* Highest reported */ ++ u32 overclock; /* Current frequency if overclocked, else zero */ ++ u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ + }; + + +@@ -204,41 +200,79 @@ static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg + return readl_relaxed(host->ioaddr + reg); + } + ++static void bcm2835_sdhost_dumpcmd(struct bcm2835_host *host, ++ struct mmc_command *cmd, ++ const char *label) ++{ ++ if (cmd) ++ pr_info("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", ++ mmc_hostname(host->mmc), ++ (cmd == host->cmd) ? '>' : ' ', ++ label, cmd->opcode, cmd->arg, cmd->flags, ++ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], ++ cmd->error); ++} ++ + static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host) + { +- pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", ++ bcm2835_sdhost_dumpcmd(host, host->mrq->sbc, "sbc"); ++ bcm2835_sdhost_dumpcmd(host, host->mrq->cmd, "cmd"); ++ if (host->mrq->data) ++ pr_err("%s: data blocks %x blksz %x - err %d\n", ++ mmc_hostname(host->mmc), ++ host->mrq->data->blocks, ++ host->mrq->data->blksz, ++ host->mrq->data->error); ++ bcm2835_sdhost_dumpcmd(host, host->mrq->stop, "stop"); ++ ++ pr_info("%s: =========== REGISTER DUMP ===========\n", + mmc_hostname(host->mmc)); + +- pr_info(DRIVER_NAME ": SDCMD 0x%08x\n", ++ pr_info("%s: SDCMD 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCMD)); +- pr_info(DRIVER_NAME ": SDARG 0x%08x\n", ++ pr_info("%s: SDARG 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDARG)); +- pr_info(DRIVER_NAME ": SDTOUT 0x%08x\n", ++ pr_info("%s: SDTOUT 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDTOUT)); +- pr_info(DRIVER_NAME ": SDCDIV 0x%08x\n", ++ pr_info("%s: SDCDIV 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCDIV)); +- pr_info(DRIVER_NAME ": SDRSP0 0x%08x\n", ++ pr_info("%s: SDRSP0 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP0)); +- pr_info(DRIVER_NAME ": SDRSP1 0x%08x\n", ++ pr_info("%s: SDRSP1 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP1)); +- pr_info(DRIVER_NAME ": SDRSP2 0x%08x\n", ++ pr_info("%s: SDRSP2 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP2)); +- pr_info(DRIVER_NAME ": SDRSP3 0x%08x\n", ++ pr_info("%s: SDRSP3 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP3)); +- pr_info(DRIVER_NAME ": SDHSTS 0x%08x\n", ++ pr_info("%s: SDHSTS 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHSTS)); +- pr_info(DRIVER_NAME ": SDVDD 0x%08x\n", ++ pr_info("%s: SDVDD 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDVDD)); +- pr_info(DRIVER_NAME ": SDEDM 0x%08x\n", ++ pr_info("%s: SDEDM 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDEDM)); +- pr_info(DRIVER_NAME ": SDHCFG 0x%08x\n", ++ pr_info("%s: SDHCFG 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHCFG)); +- pr_info(DRIVER_NAME ": SDHBCT 0x%08x\n", ++ pr_info("%s: SDHBCT 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBCT)); +- pr_info(DRIVER_NAME ": SDHBLC 0x%08x\n", ++ pr_info("%s: SDHBLC 0x%08x\n", ++ mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBLC)); + +- pr_debug(DRIVER_NAME ": ===========================================\n"); ++ pr_info("%s: ===========================================\n", ++ mmc_hostname(host->mmc)); + } + + +@@ -248,12 +282,10 @@ static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on) + } + + +-static void bcm2835_sdhost_reset(struct bcm2835_host *host) ++static void bcm2835_sdhost_reset_internal(struct bcm2835_host *host) + { + u32 temp; + +- pr_debug("bcm2835_sdhost_reset\n"); +- + bcm2835_sdhost_set_power(host, false); + + bcm2835_sdhost_write(host, 0, SDCMD); +@@ -281,6 +313,20 @@ static void bcm2835_sdhost_reset(struct bcm2835_host *host) + mmiowb(); + } + ++ ++static void bcm2835_sdhost_reset(struct mmc_host *mmc) ++{ ++ struct bcm2835_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ if (host->debug) ++ pr_info("%s: reset\n", mmc_hostname(mmc)); ++ spin_lock_irqsave(&host->lock, flags); ++ ++ bcm2835_sdhost_reset_internal(host); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ + static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + + static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) +@@ -290,7 +336,7 @@ static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft) + /* Set interrupt enables */ + host->hcfg = SDHCFG_BUSY_IRPT_EN; + +- bcm2835_sdhost_reset(host); ++ bcm2835_sdhost_reset_internal(host); + + if (soft) { + /* force clock reconfiguration */ +@@ -420,6 +466,40 @@ static void bcm2835_sdhost_dma_complete(void *param) + spin_unlock_irqrestore(&host->lock, flags); + } + ++static bool data_transfer_wait(struct bcm2835_host *host, const char *caller) ++{ ++ unsigned long timeout = 1000000; ++ u32 hsts; ++ while (timeout) ++ { ++ hsts = bcm2835_sdhost_read(host, SDHSTS); ++ if (hsts & (SDHSTS_TRANSFER_ERROR_MASK | ++ SDHSTS_DATA_FLAG)) { ++ bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK, ++ SDHSTS); ++ break; ++ } ++ timeout--; ++ } ++ ++ if (hsts & (SDHSTS_CRC16_ERROR | ++ SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR)) { ++ pr_err("%s: data error in %s - HSTS %x\n", ++ mmc_hostname(host->mmc), caller, hsts); ++ host->data->error = -EILSEQ; ++ return false; ++ } else if ((timeout == 0) || ++ (hsts & (SDHSTS_CMD_TIME_OUT | ++ SDHSTS_REW_TIME_OUT))) { ++ pr_err("%s: timeout in %s - HSTS %x\n", ++ mmc_hostname(host->mmc), caller, hsts); ++ host->data->error = -ETIMEDOUT; ++ return false; ++ } ++ return true; ++} ++ + static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) + { + unsigned long flags; +@@ -443,35 +523,15 @@ static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host) + buf = (u32 *)host->sg_miter.addr; + + while (len) { +- while (1) { +- u32 hsts; +- hsts = bcm2835_sdhost_read(host, SDHSTS); +- if (hsts & SDHSTS_DATA_FLAG) +- break; +- +- if (hsts & SDHSTS_ERROR_MASK) { +- pr_err("%s: Transfer error - HSTS %x, HBCT %x - %x left\n", +- mmc_hostname(host->mmc), +- hsts, +- bcm2835_sdhost_read(host, SDHBCT), +- blksize + len); +- if (hsts & SDHSTS_REW_TIME_OUT) +- host->data->error = -ETIMEDOUT; +- else if (hsts & (SDHSTS_CRC16_ERROR || +- SDHSTS_CRC7_ERROR)) +- host->data->error = -EILSEQ; +- else { +- pr_err("%s: unexpected data error\n", +- mmc_hostname(host->mmc)); +- bcm2835_sdhost_dumpregs(host); +- host->cmd->error = -EIO; +- } +- } +- } ++ if (!data_transfer_wait(host, "read_block_pio")) ++ break; + + *(buf++) = bcm2835_sdhost_read(host, SDDATA); + len -= 4; + } ++ ++ if (host->data->error) ++ break; } - armctrl_pm_register(base, irq_start, resume_sources); -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index cfc4f13..937c2d3 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -1028,7 +1028,7 @@ static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) + sg_miter_stop(&host->sg_miter); +@@ -502,11 +562,15 @@ static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host) + buf = host->sg_miter.addr; - static struct irqaction bcm2708_timer_irq = { - .name = "BCM2708 Timer Tick", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2708_timer_interrupt, + while (len) { +- while (!(bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG)) +- continue; ++ if (!data_transfer_wait(host, "write_block_pio")) ++ break; ++ + bcm2835_sdhost_write(host, *(buf++), SDDATA); + len -= 4; + } ++ ++ if (host->data->error) ++ break; + } + + sg_miter_stop(&host->sg_miter); +@@ -519,10 +583,15 @@ static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host) + { + BUG_ON(!host->data); + +- if (host->data->flags & MMC_DATA_READ) ++ if (host->data->flags & MMC_DATA_READ) { + bcm2835_sdhost_read_block_pio(host); +- else ++ } else { + bcm2835_sdhost_write_block_pio(host); ++ ++ /* Start a timer in case a transfer error occurs because ++ there is no error interrupt */ ++ mod_timer(&host->pio_timer, jiffies + host->pio_timeout); ++ } + } + + +@@ -607,6 +676,7 @@ static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_co + host->flush_fifo = 0; + host->data->bytes_xfered = 0; + ++ host->use_dma = host->have_dma && (data->blocks > host->pio_limit); + if (!host->use_dma) { + int flags; + +@@ -619,8 +689,6 @@ static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_co + host->blocks = data->blocks; + } + +- host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; +- + bcm2835_sdhost_set_transfer_irqs(host); + + bcm2835_sdhost_write(host, data->blksz, SDHBCT); +@@ -638,22 +706,25 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + + WARN_ON(host->cmd); + +- if (1) { +- pr_debug("bcm2835_sdhost_send_command: %08x %08x (flags %x)\n", +- cmd->opcode, cmd->arg, (cmd->flags & 0xff) | (cmd->data ? cmd->data->flags : 0)); +- if (cmd->data) +- pr_debug("bcm2835_sdhost_send_command: %s %d*%x\n", +- (cmd->data->flags & MMC_DATA_READ) ? +- "read" : "write", cmd->data->blocks, +- cmd->data->blksz); +- } ++ if (cmd->data) ++ pr_debug("%s: send_command %d 0x%x " ++ "(flags 0x%x) - %s %d*%d\n", ++ mmc_hostname(host->mmc), ++ cmd->opcode, cmd->arg, cmd->flags, ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ else ++ pr_debug("%s: send_command %d 0x%x (flags 0x%x)\n", ++ mmc_hostname(host->mmc), ++ cmd->opcode, cmd->arg, cmd->flags); + + /* Wait max 10 ms */ + timeout = 1000; + + while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { + if (timeout == 0) { +- pr_err("%s: Previous command never completed.\n", ++ pr_err("%s: previous command never completed.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + cmd->error = -EIO; +@@ -666,16 +737,16 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + + if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { + host->max_delay = (1000-timeout)/100; +- pr_warning("Warning: SDHost controller hung for %d ms\n", host->max_delay); ++ pr_warning("%s: controller hung for %d ms\n", ++ mmc_hostname(host->mmc), ++ host->max_delay); + } + + timeout = jiffies; +-#ifdef CONFIG_ARCH_BCM2835 + if (!cmd->data && cmd->busy_timeout > 9000) + timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; + else +-#endif +- timeout += 10 * HZ; ++ timeout += 10 * HZ; + mod_timer(&host->timer, timeout); + + host->cmd = cmd; +@@ -685,7 +756,7 @@ void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command * + bcm2835_sdhost_write(host, cmd->arg, SDARG); + + if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { +- pr_err("%s: Unsupported response type!\n", ++ pr_err("%s: unsupported response type!\n", + mmc_hostname(host->mmc)); + cmd->error = -EINVAL; + tasklet_schedule(&host->finish_tasklet); +@@ -783,13 +854,6 @@ static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host) + pr_debug("transfer_complete(error %d, stop %d)\n", + data->error, data->stop ? 1 : 0); + +- if (data->error) +- /* +- * The controller needs a reset of internal state machines +- * upon error conditions. +- */ +- bcm2835_sdhost_reset(host); +- + /* + * Need to send CMD12 if - + * a) open-ended multiblock transfer (no CMD23) +@@ -845,7 +909,7 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + #endif + + if (timeout == 0) { +- pr_err("%s: Command never completed.\n", ++ pr_err("%s: command never completed.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + host->cmd->error = -EIO; +@@ -875,14 +939,23 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + { + u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS); + +- pr_debug("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", +- mmc_hostname(host->mmc), sdcmd, sdhsts, +- bcm2835_sdhost_read(host, SDEDM)); +- +- if (sdhsts & SDHSTS_CMD_TIME_OUT) ++ if (host->debug) ++ pr_info("%s: error detected - CMD %x, HSTS %03x, EDM %x\n", ++ mmc_hostname(host->mmc), sdcmd, sdhsts, ++ bcm2835_sdhost_read(host, SDEDM)); ++ ++ if (sdhsts & SDHSTS_CMD_TIME_OUT) { ++ switch (host->cmd->opcode) { ++ case 5: case 52: case 53: ++ /* Don't warn about SDIO commands */ ++ break; ++ default: ++ pr_err("%s: command timeout\n", ++ mmc_hostname(host->mmc)); ++ break; ++ } + host->cmd->error = -ETIMEDOUT; +- else +- { ++ } else { + pr_err("%s: unexpected command error\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); +@@ -897,11 +970,13 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + int i; + for (i = 0; i < 4; i++) + host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4); +- pr_debug("bcm2835_sdhost_finish_command: %08x %08x %08x %08x\n", ++ pr_debug("%s: finish_command %08x %08x %08x %08x\n", ++ mmc_hostname(host->mmc), + host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]); + } else { + host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0); +- pr_debug("bcm2835_sdhost_finish_command: %08x\n", ++ pr_debug("%s: finish_command %08x\n", ++ mmc_hostname(host->mmc), + host->cmd->resp[0]); + } + } +@@ -932,7 +1007,7 @@ static void bcm2835_sdhost_finish_command(struct bcm2835_host *host) + } + } + +-static void bcm2835_sdhost_timeout_timer(unsigned long data) ++static void bcm2835_sdhost_timeout(unsigned long data) + { + struct bcm2835_host *host; + unsigned long flags; +@@ -942,7 +1017,7 @@ static void bcm2835_sdhost_timeout_timer(unsigned long data) + spin_lock_irqsave(&host->lock, flags); + + if (host->mrq) { +- pr_err("%s: Timeout waiting for hardware interrupt.\n", ++ pr_err("%s: timeout waiting for hardware interrupt.\n", + mmc_hostname(host->mmc)); + bcm2835_sdhost_dumpregs(host); + +@@ -964,6 +1039,41 @@ static void bcm2835_sdhost_timeout_timer(unsigned long data) + spin_unlock_irqrestore(&host->lock, flags); + } + ++static void bcm2835_sdhost_pio_timeout(unsigned long data) ++{ ++ struct bcm2835_host *host; ++ unsigned long flags; ++ ++ host = (struct bcm2835_host *)data; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host->data) { ++ u32 hsts = bcm2835_sdhost_read(host, SDHSTS); ++ ++ if (hsts & SDHSTS_REW_TIME_OUT) { ++ pr_err("%s: transfer timeout\n", ++ mmc_hostname(host->mmc)); ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); ++ } else { ++ pr_err("%s: unexpected transfer timeout\n", ++ mmc_hostname(host->mmc)); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ ++ bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK, ++ SDHSTS); ++ ++ host->data->error = -ETIMEDOUT; ++ ++ bcm2835_sdhost_finish_data(host); ++ } ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ + static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) + { + if (enable) +@@ -979,7 +1089,7 @@ static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + +- pr_debug("bcm2835_sdhost_enable_sdio_irq(%d)\n", enable); ++ pr_debug("%s: enable_sdio_irq(%d)\n", mmc_hostname(mmc), enable); + spin_lock_irqsave(&host->lock, flags); + bcm2835_sdhost_enable_sdio_irq_nolock(host, enable); + spin_unlock_irqrestore(&host->lock, flags); +@@ -987,11 +1097,12 @@ static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable) + + static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + { +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT | ++ SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | ++ SDHSTS_FIFO_ERROR); + + if (!host->cmd) { +- pr_err("%s: Got command busy interrupt 0x%08x even " ++ pr_err("%s: got command busy interrupt 0x%08x even " + "though no command operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); +@@ -999,7 +1110,7 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + } + + if (!host->use_busy) { +- pr_err("%s: Got command busy interrupt 0x%08x even " ++ pr_err("%s: got command busy interrupt 0x%08x even " + "though not expecting one.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); +@@ -1007,14 +1118,28 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + } + host->use_busy = 0; + +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR | +- SDHSTS_FIFO_ERROR)) +- host->cmd->error = -EILSEQ; ++ if (intmask & SDHSTS_ERROR_MASK) ++ { ++ pr_err("sdhost_busy_irq: intmask %x, data %p\n", intmask, host->mrq->data); ++ if (intmask & SDHSTS_CRC7_ERROR) ++ host->cmd->error = -EILSEQ; ++ else if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) { ++ if (host->mrq->data) ++ host->mrq->data->error = -EILSEQ; ++ else ++ host->cmd->error = -EILSEQ; ++ } else if (intmask & SDHSTS_REW_TIME_OUT) { ++ if (host->mrq->data) ++ host->mrq->data->error = -ETIMEDOUT; ++ else ++ host->cmd->error = -ETIMEDOUT; ++ } else if (intmask & SDHSTS_CMD_TIME_OUT) ++ host->cmd->error = -ETIMEDOUT; + +- if (host->cmd->error) ++ bcm2835_sdhost_dumpregs(host); + tasklet_schedule(&host->finish_tasklet); ++ } + else + bcm2835_sdhost_finish_command(host); + +@@ -1023,8 +1148,9 @@ static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask) + + static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) + { +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | ++ SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR); + + /* There are no dedicated data/space available interrupt + status bits, so it is necessary to use the single shared +@@ -1034,13 +1160,19 @@ static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask) + if (!host->data) + return 0; + +- // XXX FIFO_ERROR +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && +- ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) +- != MMC_BUS_TEST_R)) +- host->cmd->error = -EILSEQ; ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR | ++ SDHSTS_REW_TIME_OUT)) { ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->data->error = -EILSEQ; ++ else ++ host->data->error = -ETIMEDOUT; ++ ++ bcm2835_sdhost_dumpregs(host); ++ tasklet_schedule(&host->finish_tasklet); ++ return handled; ++ } + + /* Use the block interrupt for writes after the first block */ + if (host->data->flags & MMC_DATA_WRITE) { +@@ -1067,31 +1199,48 @@ static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask) + { + struct dma_chan *dma_chan; + u32 dir_data; +- const u32 handled = (SDHSTS_CMD_TIME_OUT | SDHSTS_CRC16_ERROR | +- SDHSTS_CRC7_ERROR | SDHSTS_FIFO_ERROR); ++ const u32 handled = (SDHSTS_REW_TIME_OUT | ++ SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR); + + if (!host->data) { +- pr_err("%s: Got block interrupt 0x%08x even " ++ pr_err("%s: got block interrupt 0x%08x even " + "though no data operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_sdhost_dumpregs(host); + return handled; + } + +- if (intmask & SDHSTS_CMD_TIME_OUT) +- host->cmd->error = -ETIMEDOUT; +- else if ((intmask & (SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR)) && +- ((bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK) +- != MMC_BUS_TEST_R)) +- host->cmd->error = -EILSEQ; ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR | ++ SDHSTS_REW_TIME_OUT)) { ++ if (intmask & (SDHSTS_CRC16_ERROR | ++ SDHSTS_FIFO_ERROR)) ++ host->data->error = -EILSEQ; ++ else ++ host->data->error = -ETIMEDOUT; ++ ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); ++ tasklet_schedule(&host->finish_tasklet); ++ return handled; ++ } + + if (!host->use_dma) { + BUG_ON(!host->blocks); + host->blocks--; +- if ((host->blocks == 0) || host->data->error) ++ if ((host->blocks == 0) || host->data->error) { ++ /* Cancel the timer */ ++ del_timer(&host->pio_timer); ++ + bcm2835_sdhost_finish_data(host); +- else ++ } else { + bcm2835_sdhost_transfer_pio(host); ++ ++ /* Reset the timer */ ++ mod_timer(&host->pio_timer, ++ jiffies + host->pio_timeout); ++ } + } else if (host->data->flags & MMC_DATA_WRITE) { + dma_chan = host->dma_chan_tx; + dir_data = DMA_TO_DEVICE; +@@ -1125,7 +1274,7 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) + SDHSTS_BLOCK_IRPT | + SDHSTS_SDIO_IRPT | + SDHSTS_DATA_FLAG); +- if ((handled == SDHSTS_DATA_FLAG) && // XXX ++ if ((handled == SDHSTS_DATA_FLAG) && + (loops == 0) && !host->data) { + pr_err("%s: sdhost_irq data interrupt 0x%08x even " + "though no data operation was in progress.\n", +@@ -1177,10 +1326,11 @@ static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id) + spin_unlock(&host->lock); + + if (early) +- pr_debug("%s: early %x (loops %d)\n", mmc_hostname(host->mmc), early, loops); ++ pr_debug("%s: early %x (loops %d)\n", ++ mmc_hostname(host->mmc), early, loops); + + if (unexpected) { +- pr_err("%s: Unexpected interrupt 0x%08x.\n", ++ pr_err("%s: unexpected interrupt 0x%08x.\n", + mmc_hostname(host->mmc), unexpected); + bcm2835_sdhost_dumpregs(host); + } +@@ -1227,8 +1377,22 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) + int div = 0; /* Initialized for compiler warning */ + unsigned int input_clock = clock; + +- if (host->overclock_50 && (clock == 50000000)) +- clock = host->overclock_50 * 1000000 + 999999; ++ if (host->debug) ++ pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock); ++ ++ if ((clock == 0) && host->reduce_overclock) { ++ /* This is a reset following data corruption - reduce any ++ overclock */ ++ host->reduce_overclock = 0; ++ if (host->overclock_50 > 50) { ++ pr_warn("%s: reducing overclock due to errors\n", ++ mmc_hostname(host->mmc)); ++ host->overclock_50--; ++ } ++ } ++ ++ if (host->overclock_50 && (clock == 50*MHZ)) ++ clock = host->overclock_50 * MHZ + (MHZ - 1); + + /* The SDCDIV register has 11 bits, and holds (div - 2). + But in data mode the max is 50MHz wihout a minimum, and only the +@@ -1275,17 +1439,34 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) + clock = host->max_clk / (div + 2); + host->mmc->actual_clock = clock; + +- if ((clock > input_clock) && (clock > host->max_overclock)) { +- pr_warn("%s: Overclocking to %dHz\n", +- mmc_hostname(host->mmc), clock); +- host->max_overclock = clock; ++ if (clock > input_clock) { ++ /* Save the closest value, to make it easier ++ to reduce in the event of error */ ++ host->overclock_50 = (clock/MHZ); ++ ++ if (clock != host->overclock) { ++ pr_warn("%s: overclocking to %dHz\n", ++ mmc_hostname(host->mmc), clock); ++ host->overclock = clock; ++ } ++ } ++ else if ((clock == 50 * MHZ) && host->overclock) ++ { ++ pr_warn("%s: cancelling overclock\n", ++ mmc_hostname(host->mmc)); ++ host->overclock = 0; + } + + host->cdiv = div; + bcm2835_sdhost_write(host, host->cdiv, SDCDIV); + +- pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", +- input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); ++ /* Set the timeout to 500ms */ ++ bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT); ++ ++ if (host->debug) ++ pr_info("%s: clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", ++ mmc_hostname(host->mmc), input_clock, ++ host->max_clk, host->cdiv, host->mmc->actual_clock); + } + + static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) +@@ -1293,29 +1474,32 @@ static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq + struct bcm2835_host *host; + unsigned long flags; + +- if (1) { ++ host = mmc_priv(mmc); ++ ++ if (host->debug) { + struct mmc_command *cmd = mrq->cmd; +- const char *src = "cmd"; + BUG_ON(!cmd); +- pr_debug("bcm2835_sdhost_request: %s %08x %08x (flags %x)\n", +- src, cmd->opcode, cmd->arg, cmd->flags); + if (cmd->data) +- pr_debug("bcm2835_sdhost_request: %s %d*%d\n", +- (cmd->data->flags & MMC_DATA_READ) ? +- "read" : "write", cmd->data->blocks, +- cmd->data->blksz); ++ pr_info("%s: cmd %d 0x%x (flags 0x%x) - %s %d*%d\n", ++ mmc_hostname(mmc), ++ cmd->opcode, cmd->arg, cmd->flags, ++ (cmd->data->flags & MMC_DATA_READ) ? ++ "read" : "write", cmd->data->blocks, ++ cmd->data->blksz); ++ else ++ pr_info("%s: cmd %d 0x%x (flags 0x%x)\n", ++ mmc_hostname(mmc), ++ cmd->opcode, cmd->arg, cmd->flags); + } + + if (mrq->data && !is_power_of_2(mrq->data->blksz)) { +- pr_err("%s: Unsupported block size (%d bytes)\n", ++ pr_err("%s: unsupported block size (%d bytes)\n", + mmc_hostname(mmc), mrq->data->blksz); + mrq->cmd->error = -EINVAL; + mmc_request_done(mmc, mrq); + return; + } + +- host = mmc_priv(mmc); +- + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); +@@ -1345,9 +1529,12 @@ static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + +- pr_debug("bcm2835_sdhost_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", +- ios->clock, ios->power_mode, ios->bus_width, +- ios->timing, ios->signal_voltage, ios->drv_type); ++ if (host->debug) ++ pr_info("%s: ios clock %d, pwr %d, bus_width %d, " ++ "timing %d, vdd %d, drv_type %d\n", ++ mmc_hostname(mmc), ++ ios->clock, ios->power_mode, ios->bus_width, ++ ios->timing, ios->signal_voltage, ios->drv_type); + + spin_lock_irqsave(&host->lock, flags); + +@@ -1396,6 +1583,7 @@ static struct mmc_host_ops bcm2835_sdhost_ops = { + .request = bcm2835_sdhost_request, + .set_ios = bcm2835_sdhost_set_ios, + .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq, ++ .hw_reset = bcm2835_sdhost_reset, + .multi_io_quirk = bcm2835_sdhost_multi_io_quirk, }; -diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c -index c1e9254..e33265d 100644 ---- a/arch/arm/mach-bcm2708/bcm2708_gpio.c -+++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c -@@ -306,7 +306,7 @@ static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) +@@ -1423,15 +1611,24 @@ static void bcm2835_sdhost_tasklet_finish(unsigned long param) - static struct irqaction bcm2708_gpio_irq = { - .name = "BCM2708 GPIO catchall handler", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2708_gpio_interrupt, + mrq = host->mrq; + +- /* +- * The controller needs a reset of internal state machines +- * upon error conditions. +- */ +- if (((mrq->cmd && mrq->cmd->error) || +- (mrq->data && (mrq->data->error || +- (mrq->data->stop && mrq->data->stop->error))))) { ++ /* Drop the overclock after any data corruption, or after any ++ error overclocked */ ++ if (mrq->data && (mrq->data->error == -EILSEQ)) ++ host->reduce_overclock = 1; ++ else if (host->overclock) { ++ /* Convert timeout errors while overclocked to data errors, ++ because the system recovers better. */ ++ if (mrq->cmd && mrq->cmd->error) { ++ host->reduce_overclock = 1; ++ if (mrq->cmd->error == -ETIMEDOUT) ++ mrq->cmd->error = -EILSEQ; ++ } + +- bcm2835_sdhost_reset(host); ++ if (mrq->data && mrq->data->error) { ++ host->reduce_overclock = 1; ++ if (mrq->data->error == -ETIMEDOUT) ++ mrq->data->error = -EILSEQ; ++ } + } + + host->mrq = NULL; +@@ -1450,35 +1647,37 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + { + struct mmc_host *mmc; + struct dma_slave_config cfg; ++ char pio_limit_string[20]; + int ret; + + mmc = host->mmc; + +- bcm2835_sdhost_reset(host); ++ bcm2835_sdhost_reset_internal(host); + + mmc->f_max = host->max_clk; + mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV; + +- /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ +- host->timeout_clk = mmc->f_max / 1000; +-#ifdef CONFIG_ARCH_BCM2835 +- mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; +-#endif ++ mmc->max_busy_timeout = (~(unsigned int)0)/(mmc->f_max/1000); ++ ++ pr_debug("f_max %d, f_min %d, max_busy_timeout %d\n", ++ mmc->f_max, mmc->f_min, mmc->max_busy_timeout); ++ + /* host controller capabilities */ + mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA | + MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | +- MMC_CAP_NEEDS_POLL | ++ MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | + (ALLOW_CMD23 * MMC_CAP_CMD23); + + spin_lock_init(&host->lock); + + if (host->allow_dma) { +- if (!host->dma_chan_tx || !host->dma_chan_rx || +- IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { +- pr_err("%s: Unable to initialise DMA channels. Falling back to PIO\n", DRIVER_NAME); ++ if (IS_ERR_OR_NULL(host->dma_chan_tx) || ++ IS_ERR_OR_NULL(host->dma_chan_rx)) { ++ pr_err("%s: unable to initialise DMA channels. " ++ "Falling back to PIO\n", ++ mmc_hostname(mmc)); + host->have_dma = false; + } else { +- pr_info("DMA channels allocated for the SDHost driver"); + host->have_dma = true; + + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -1496,7 +1695,6 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + ret = dmaengine_slave_config(host->dma_chan_rx, &cfg); + } + } else { +- pr_info("Forcing PIO mode\n"); + host->have_dma = false; + } + +@@ -1512,18 +1710,23 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + tasklet_init(&host->finish_tasklet, + bcm2835_sdhost_tasklet_finish, (unsigned long)host); + +- setup_timer(&host->timer, bcm2835_sdhost_timeout_timer, (unsigned long)host); ++ setup_timer(&host->timer, bcm2835_sdhost_timeout, ++ (unsigned long)host); ++ ++ setup_timer(&host->pio_timer, bcm2835_sdhost_pio_timeout, ++ (unsigned long)host); + + bcm2835_sdhost_init(host, 0); + #ifndef CONFIG_ARCH_BCM2835 + ret = request_irq(host->irq, bcm2835_sdhost_irq, 0 /*IRQF_SHARED*/, + mmc_hostname(mmc), host); + #else +- ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, bcm2835_sdhost_thread_irq, ++ ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq, ++ bcm2835_sdhost_thread_irq, + IRQF_SHARED, mmc_hostname(mmc), host); + #endif + if (ret) { +- pr_err("%s: Failed to request IRQ %d: %d\n", ++ pr_err("%s: failed to request IRQ %d: %d\n", + mmc_hostname(mmc), host->irq, ret); + goto untasklet; + } +@@ -1531,10 +1734,13 @@ int bcm2835_sdhost_add_host(struct bcm2835_host *host) + mmiowb(); + mmc_add_host(mmc); + +- pr_info("Load BCM2835 SDHost driver\n"); +- if (host->delay_after_stop) +- pr_info("BCM2835 SDHost: delay_after_stop=%dus\n", +- host->delay_after_stop); ++ pio_limit_string[0] = '\0'; ++ if (host->have_dma && (host->pio_limit > 0)) ++ sprintf(pio_limit_string, " (>%d)", host->pio_limit); ++ pr_info("%s: %s loaded - DMA %s%s\n", ++ mmc_hostname(mmc), DRIVER_NAME, ++ host->have_dma ? "enabled" : "disabled", ++ pio_limit_string); + + return 0; + +@@ -1562,7 +1768,7 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) + mmc->ops = &bcm2835_sdhost_ops; + host = mmc_priv(mmc); + host->mmc = mmc; +- host->timeout = msecs_to_jiffies(1000); ++ host->pio_timeout = msecs_to_jiffies(500); + spin_lock_init(&host->lock); + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1588,8 +1794,12 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) + of_property_read_u32(node, + "brcm,overclock-50", + &host->overclock_50); ++ of_property_read_u32(node, ++ "brcm,pio-limit", ++ &host->pio_limit); + host->allow_dma = ALLOW_DMA && + !of_property_read_bool(node, "brcm,force-pio"); ++ host->debug = of_property_read_bool(node, "brcm,debug"); + } + + if (host->allow_dma) { + +From 5920303037d30f0ecee57f83015cd8838ba1f77e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Thu, 4 Jun 2015 13:11:46 -0700 +Subject: [PATCH 78/85] ARM: bcm2835: Add the Raspberry Pi firmware driver + +This gives us a function for making mailbox property channel requests +of the firmware, which is most notable in that it will let us get and +set clock rates. + +Signed-off-by: Eric Anholt +--- + drivers/firmware/Kconfig | 7 + + drivers/firmware/Makefile | 1 + + drivers/firmware/raspberrypi.c | 260 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 115 +++++++++++++ + 4 files changed, 383 insertions(+) + create mode 100644 drivers/firmware/raspberrypi.c + create mode 100644 include/soc/bcm2835/raspberrypi-firmware.h + +diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig +index 6517132..564aa5b 100644 +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -136,6 +136,13 @@ config QCOM_SCM + bool + depends on ARM || ARM64 + ++config RASPBERRYPI_FIRMWARE ++ tristate "Raspberry Pi Firmware Driver" ++ depends on BCM2835_MBOX ++ help ++ This option enables support for communicating with the firmware on the ++ Raspberry Pi. ++ + source "drivers/firmware/google/Kconfig" + source "drivers/firmware/efi/Kconfig" + +diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile +index 3fdd391..ee101a2 100644 +--- a/drivers/firmware/Makefile ++++ b/drivers/firmware/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o + obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o + obj-$(CONFIG_QCOM_SCM) += qcom_scm.o + CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) ++obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o + + obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ + obj-$(CONFIG_EFI) += efi/ +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +new file mode 100644 +index 0000000..dd506cd +--- /dev/null ++++ b/drivers/firmware/raspberrypi.c +@@ -0,0 +1,260 @@ ++/* ++ * Defines interfaces for interacting wtih the Raspberry Pi firmware's ++ * property channel. ++ * ++ * Copyright © 2015 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_CHAN_PROPERTY 8 ++ ++struct rpi_firmware { ++ struct mbox_client cl; ++ struct mbox_chan *chan; /* The property channel. */ ++ struct completion c; ++ u32 enabled; ++}; ++ ++static DEFINE_MUTEX(transaction_lock); ++ ++static void response_callback(struct mbox_client *cl, void *msg) ++{ ++ struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl); ++ complete(&fw->c); ++} ++ ++/* ++ * Sends a request to the firmware through the BCM2835 mailbox driver, ++ * and synchronously waits for the reply. ++ */ ++static int ++rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) ++{ ++ u32 message = MBOX_MSG(chan, data); ++ int ret; ++ ++ WARN_ON(data & 0xf); ++ ++ mutex_lock(&transaction_lock); ++ reinit_completion(&fw->c); ++ ret = mbox_send_message(fw->chan, &message); ++ if (ret >= 0) { ++ wait_for_completion(&fw->c); ++ ret = 0; ++ } else { ++ dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret); ++ } ++ mutex_unlock(&transaction_lock); ++ ++ return ret; ++} ++ ++/** ++ * rpi_firmware_property_list - Submit firmware property list ++ * @fw: Pointer to firmware structure from rpi_firmware_get(). ++ * @data: Buffer holding tags. ++ * @tag_size: Size of tags buffer. ++ * ++ * Submits a set of concatenated tags to the VPU firmware through the ++ * mailbox property interface. ++ * ++ * The buffer header and the ending tag are added by this function and ++ * don't need to be supplied, just the actual tags for your operation. ++ * See struct rpi_firmware_property_tag_header for the per-tag ++ * structure. ++ */ ++int rpi_firmware_property_list(struct rpi_firmware *fw, ++ void *data, size_t tag_size) ++{ ++ size_t size = tag_size + 12; ++ u32 *buf; ++ dma_addr_t bus_addr; ++ int ret; ++ ++ /* Packets are processed a dword at a time. */ ++ if (size & 3) ++ return -EINVAL; ++ ++ buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) ++ return -ENOMEM; ++ ++ /* The firmware will error out without parsing in this case. */ ++ WARN_ON(size >= 1024 * 1024); ++ ++ buf[0] = size; ++ buf[1] = RPI_FIRMWARE_STATUS_REQUEST; ++ memcpy(&buf[2], data, tag_size); ++ buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END; ++ wmb(); ++ ++ ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr); ++ ++ rmb(); ++ memcpy(data, &buf[2], tag_size); ++ if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) { ++ /* ++ * The tag name here might not be the one causing the ++ * error, if there were multiple tags in the request. ++ * But single-tag is the most common, so go with it. ++ */ ++ dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n", ++ buf[2], buf[1]); ++ ret = -EINVAL; ++ } ++ ++ dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_property_list); ++ ++/** ++ * rpi_firmware_property - Submit single firmware property ++ * @fw: Pointer to firmware structure from rpi_firmware_get(). ++ * @tag: One of enum_mbox_property_tag. ++ * @tag_data: Tag data buffer. ++ * @buf_size: Buffer size. ++ * ++ * Submits a single tag to the VPU firmware through the mailbox ++ * property interface. ++ * ++ * This is a convenience wrapper around ++ * rpi_firmware_property_list() to avoid some of the ++ * boilerplate in property calls. ++ */ ++int rpi_firmware_property(struct rpi_firmware *fw, ++ u32 tag, void *tag_data, size_t buf_size) ++{ ++ /* Single tags are very small (generally 8 bytes), so the ++ * stack should be safe. ++ */ ++ u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)]; ++ struct rpi_firmware_property_tag_header *header = ++ (struct rpi_firmware_property_tag_header *)data; ++ int ret; ++ ++ header->tag = tag; ++ header->buf_size = buf_size; ++ header->req_resp_size = 0; ++ memcpy(data + sizeof(struct rpi_firmware_property_tag_header), ++ tag_data, buf_size); ++ ++ ret = rpi_firmware_property_list(fw, &data, sizeof(data)); ++ memcpy(tag_data, ++ data + sizeof(struct rpi_firmware_property_tag_header), ++ buf_size); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_property); ++ ++static void ++rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) ++{ ++ u32 packet; ++ int ret = rpi_firmware_property(fw, ++ RPI_FIRMWARE_GET_FIRMWARE_REVISION, ++ &packet, sizeof(packet)); ++ ++ if (ret == 0) { ++ struct tm tm; ++ ++ time_to_tm(packet, 0, &tm); ++ ++ dev_info(fw->cl.dev, ++ "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n", ++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min); ++ } ++} ++ ++static int rpi_firmware_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_firmware *fw; ++ ++ fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); ++ if (!fw) ++ return -ENOMEM; ++ ++ fw->cl.dev = dev; ++ fw->cl.rx_callback = response_callback; ++ fw->cl.tx_block = true; ++ ++ fw->chan = mbox_request_channel(&fw->cl, 0); ++ if (IS_ERR(fw->chan)) { ++ int ret = PTR_ERR(fw->chan); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get mbox channel: %d\n", ret); ++ return ret; ++ } ++ ++ init_completion(&fw->c); ++ ++ platform_set_drvdata(pdev, fw); ++ ++ rpi_firmware_print_firmware_revision(fw); ++ ++ return 0; ++} ++ ++static int rpi_firmware_remove(struct platform_device *pdev) ++{ ++ struct rpi_firmware *fw = platform_get_drvdata(pdev); ++ ++ mbox_free_channel(fw->chan); ++ ++ return 0; ++} ++ ++/** ++ * rpi_firmware_get - Get pointer to rpi_firmware structure. ++ * @firmware_node: Pointer to the firmware Device Tree node. ++ * ++ * Returns NULL is the firmware device is not ready. ++ */ ++struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) ++{ ++ struct platform_device *pdev = of_find_device_by_node(firmware_node); ++ ++ if (!pdev) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++EXPORT_SYMBOL_GPL(rpi_firmware_get); ++ ++static const struct of_device_id rpi_firmware_of_match[] = { ++ { .compatible = "raspberrypi,bcm2835-firmware", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_firmware_of_match); ++ ++static struct platform_driver rpi_firmware_driver = { ++ .driver = { ++ .name = "raspberrypi-firmware", ++ .of_match_table = rpi_firmware_of_match, ++ }, ++ .probe = rpi_firmware_probe, ++ .remove = rpi_firmware_remove, ++}; ++module_platform_driver(rpi_firmware_driver); ++ ++MODULE_AUTHOR("Eric Anholt "); ++MODULE_DESCRIPTION("Raspberry Pi firmware driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +new file mode 100644 +index 0000000..9d9efb7 +--- /dev/null ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -0,0 +1,115 @@ ++/* ++ * Copyright © 2015 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++ ++struct rpi_firmware; ++ ++enum rpi_firmware_property_status { ++ RPI_FIRMWARE_STATUS_REQUEST = 0, ++ RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000, ++ RPI_FIRMWARE_STATUS_ERROR = 0x80000001, ++}; ++ ++/** ++ * struct rpi_firmware_property_tag_header - Firmware property tag header ++ * @tag: One of enum_mbox_property_tag. ++ * @buf_size: The number of bytes in the value buffer following this ++ * struct. ++ * @req_resp_size: On submit, the length of the request (though it doesn't ++ * appear to be currently used by the firmware). On return, ++ * the length of the response (always 4 byte aligned), with ++ * the low bit set. ++ */ ++struct rpi_firmware_property_tag_header { ++ u32 tag; ++ u32 buf_size; ++ u32 req_resp_size; ++}; ++ ++enum rpi_firmware_property_tag { ++ RPI_FIRMWARE_PROPERTY_END = 0, ++ RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001, ++ ++ RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010, ++ RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011, ++ ++ RPI_FIRMWARE_GET_BOARD_MODEL = 0x00010001, ++ RPI_FIRMWARE_GET_BOARD_REVISION = 0x00010002, ++ RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS = 0x00010003, ++ RPI_FIRMWARE_GET_BOARD_SERIAL = 0x00010004, ++ RPI_FIRMWARE_GET_ARM_MEMORY = 0x00010005, ++ RPI_FIRMWARE_GET_VC_MEMORY = 0x00010006, ++ RPI_FIRMWARE_GET_CLOCKS = 0x00010007, ++ RPI_FIRMWARE_GET_POWER_STATE = 0x00020001, ++ RPI_FIRMWARE_GET_TIMING = 0x00020002, ++ RPI_FIRMWARE_SET_POWER_STATE = 0x00028001, ++ RPI_FIRMWARE_GET_CLOCK_STATE = 0x00030001, ++ RPI_FIRMWARE_GET_CLOCK_RATE = 0x00030002, ++ RPI_FIRMWARE_GET_VOLTAGE = 0x00030003, ++ RPI_FIRMWARE_GET_MAX_CLOCK_RATE = 0x00030004, ++ RPI_FIRMWARE_GET_MAX_VOLTAGE = 0x00030005, ++ RPI_FIRMWARE_GET_TEMPERATURE = 0x00030006, ++ RPI_FIRMWARE_GET_MIN_CLOCK_RATE = 0x00030007, ++ RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, ++ RPI_FIRMWARE_GET_TURBO = 0x00030009, ++ RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, ++ RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, ++ RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, ++ RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, ++ RPI_FIRMWARE_RELEASE_MEMORY = 0x0003000f, ++ RPI_FIRMWARE_EXECUTE_CODE = 0x00030010, ++ RPI_FIRMWARE_EXECUTE_QPU = 0x00030011, ++ RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, ++ RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, ++ RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, ++ RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, ++ RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, ++ RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, ++ RPI_FIRMWARE_SET_TURBO = 0x00038009, ++ ++ /* Dispmanx TAGS */ ++ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, ++ RPI_FIRMWARE_FRAMEBUFFER_BLANK = 0x00040002, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH = 0x00040005, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH = 0x00040008, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, ++ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ ++ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, ++ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, ++}; ++ ++int rpi_firmware_property(struct rpi_firmware *fw, ++ u32 tag, void *data, size_t len); ++int rpi_firmware_property_list(struct rpi_firmware *fw, ++ void *data, size_t tag_size); ++struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); + +From c97b07c0494073a69820a78b6012dc62cb902144 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 13:33:23 +0000 +Subject: [PATCH 79/85] config: Enable ZSMALLOC, ZRAM and PGTABLE_MAPPING + +--- + arch/arm/configs/bcm2709_defconfig | 4 ++++ + arch/arm/configs/bcmrpi_defconfig | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index a3067bf..7ef615c 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -49,6 +49,8 @@ CONFIG_OABI_COMPAT=y + CONFIG_CLEANCACHE=y + CONFIG_FRONTSWAP=y + CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y + CONFIG_UACCESS_WITH_MEMCPY=y + CONFIG_SECCOMP=y + CONFIG_ZBOOT_ROM_TEXT=0x0 +@@ -389,6 +391,8 @@ CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y + CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_ZRAM=m ++CONFIG_ZRAM_LZ4_COMPRESS=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_CRYPTOLOOP=m + CONFIG_BLK_DEV_DRBD=m +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 6a41231..cacde14 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -44,6 +44,8 @@ CONFIG_OABI_COMPAT=y + CONFIG_CLEANCACHE=y + CONFIG_FRONTSWAP=y + CONFIG_CMA=y ++CONFIG_ZSMALLOC=m ++CONFIG_PGTABLE_MAPPING=y + CONFIG_UACCESS_WITH_MEMCPY=y + CONFIG_SECCOMP=y + CONFIG_ZBOOT_ROM_TEXT=0x0 +@@ -382,6 +384,8 @@ CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y + CONFIG_DMA_CMA=y + CONFIG_CMA_SIZE_MBYTES=5 ++CONFIG_ZRAM=m ++CONFIG_ZRAM_LZ4_COMPRESS=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_BLK_DEV_CRYPTOLOOP=m + CONFIG_BLK_DEV_DRBD=m + +From e547d7e94a85179d7ff7787eb95e29f0b0b657f4 Mon Sep 17 00:00:00 2001 +From: Gordon Hollingworth +Date: Mon, 22 Jun 2015 16:27:07 +0100 +Subject: [PATCH 80/85] Add rpi-ft5406 overlay Add rpi-ft5406 driver as module + +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 5 +++++ + arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 16 ++++++++++++++++ + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 5 files changed, 24 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts + +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +index 6947556..19eef3c 100644 +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -35,6 +35,7 @@ dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb ++dtb-$(RPI_DT_OVERLAYS) += rpi-ft5406-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb + dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 63da266..aa09b6c 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -396,6 +396,11 @@ Params: speed Display SPI bus speed + + xohms Touchpanel sensitivity (X-plate resistance) + ++Name: rpi-ft5406 ++Info: Official Raspberry Pi display touchscreen ++Load: dtoverlay=rpi-ft5406 ++Params: ++ + + Name: rpi-proto + Info: Configures the RPi Proto audio card +diff --git a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts +new file mode 100644 +index 0000000..40deab5 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts +@@ -0,0 +1,16 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ rpi_ft5406: rpi_ft5406 { ++ compatible = "rpi,rpi-ft5406"; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7ef615c..7469d07 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -535,6 +535,7 @@ CONFIG_JOYSTICK_XPAD_FF=y + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m + CONFIG_INPUT_MISC=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index cacde14..f952ff2 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -528,6 +528,7 @@ CONFIG_JOYSTICK_XPAD_FF=y + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m ++CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m + CONFIG_INPUT_MISC=y + +From 9dea271e610d0524fad677b9cccdd3be84ab25da Mon Sep 17 00:00:00 2001 +From: Gordon Hollingworth +Date: Tue, 23 Jun 2015 09:53:40 +0100 +Subject: [PATCH 81/85] Fix driver detection failure Check that the buffer + response is non-zero meaning the touchscreen was detected + +--- + drivers/input/touchscreen/rpi-ft5406.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/rpi-ft5406.c b/drivers/input/touchscreen/rpi-ft5406.c +index f55151b..d41851d 100644 +--- a/drivers/input/touchscreen/rpi-ft5406.c ++++ b/drivers/input/touchscreen/rpi-ft5406.c +@@ -184,7 +184,7 @@ static int ft5406_probe(struct platform_device *pdev) + + bcm_mailbox_property(&request, sizeof(request)); + +- if(request.request_code == VCMSG_REQUEST_SUCCESSFUL) ++ if(request.request_code == VCMSG_REQUEST_SUCCESSFUL && request.tag.val != 0) + { + dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", request.tag.val); + } + +From 8ad2b6ac33fca9a40238c42fdd2b5ed840c2fc8d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Jun 2015 13:24:01 +0100 +Subject: [PATCH 82/85] config: Enable 8250 serial port + +--- + arch/arm/configs/bcm2709_defconfig | 7 +++++++ + arch/arm/configs/bcmrpi_defconfig | 7 +++++++ + 2 files changed, 14 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7469d07..7e8643c 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -557,8 +557,15 @@ CONFIG_GAMEPORT_L4=m + CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=1 + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_TTY_PRINTK=y + CONFIG_HW_RANDOM=y + CONFIG_HW_RANDOM_BCM2835=m +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index f952ff2..0c25d8b 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -550,8 +550,15 @@ CONFIG_GAMEPORT_L4=m + CONFIG_DEVPTS_MULTIPLE_INSTANCES=y + # CONFIG_LEGACY_PTYS is not set + # CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=1 + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_TTY_PRINTK=y + CONFIG_HW_RANDOM=y + CONFIG_HW_RANDOM_BCM2835=m + +From cc78a5ef74fc67465fdacffe452a5fab5848b33c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Jun 2015 14:10:58 +0100 +Subject: [PATCH 83/85] config: Enable POWER_RESET_GPIO + +--- + arch/arm/configs/bcm2709_defconfig | 2 ++ + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 7e8643c..46d56d7 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -606,6 +606,8 @@ CONFIG_W1_SLAVE_DS2781=m + CONFIG_W1_SLAVE_DS28E04=m + CONFIG_W1_SLAVE_BQ27000=m + CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y + # CONFIG_HWMON is not set + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 0c25d8b..e757db6 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -599,6 +599,8 @@ CONFIG_W1_SLAVE_DS2781=m + CONFIG_W1_SLAVE_DS28E04=m + CONFIG_W1_SLAVE_BQ27000=m + CONFIG_BATTERY_DS2760=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y + # CONFIG_HWMON is not set + CONFIG_THERMAL=y + CONFIG_THERMAL_BCM2835=y + +From 01f5e319010c90770e0c8a87656c360a18a35208 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 26 Jun 2015 17:37:38 +0100 +Subject: [PATCH 84/85] bcm2708-vcio: Remove restriction of only a single + instance being open + +We need more than one process to be able to use mailbox interface (e.g. HW cursor in fbturbo and hello_fft). +Locking should be handled on each mailbox access +--- + drivers/mailbox/bcm2708-vcio.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/drivers/mailbox/bcm2708-vcio.c b/drivers/mailbox/bcm2708-vcio.c +index d91672b..06fb2c2f 100644 +--- a/drivers/mailbox/bcm2708-vcio.c ++++ b/drivers/mailbox/bcm2708-vcio.c +@@ -242,20 +242,9 @@ EXPORT_SYMBOL_GPL(bcm_mailbox_property); + + /* Platform Device for Mailbox */ + +-/* +- * Is the device open right now? Used to prevent +- * concurent access into the same device +- */ +-static bool device_is_open; +- + /* This is called whenever a process attempts to open the device file */ + static int device_open(struct inode *inode, struct file *file) + { +- /* We don't want to talk to two processes at the same time */ +- if (device_is_open) +- return -EBUSY; +- +- device_is_open = true; + try_module_get(THIS_MODULE); + + return 0; +@@ -263,9 +252,6 @@ static int device_open(struct inode *inode, struct file *file) + + static int device_release(struct inode *inode, struct file *file) + { +- /* We're now ready for our next caller */ +- device_is_open = false; +- + module_put(THIS_MODULE); + + return 0; + +From 2cdae3dcbcca3d818f64d14580f22c67e32d851c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 26 Jun 2015 08:39:19 +0100 +Subject: [PATCH 85/85] BCM270X_DT: Create a "core" clock, use it for SPI and + sdhost + +--- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 1 + + arch/arm/boot/dts/bcm2708_common.dtsi | 6 +++--- + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 28 ++------------------------- + 6 files changed, 9 insertions(+), 29 deletions(-) + +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +index 0fa2210..3b252dc 100644 +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -124,6 +124,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts +index 3fd49d0..40fded1 100644 +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -118,6 +118,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +index 238bd65..e82fcb2 100755 +--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -14,5 +14,6 @@ + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + }; }; +diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi +index 8caa234..4a975dfd 100644 +--- a/arch/arm/boot/dts/bcm2708_common.dtsi ++++ b/arch/arm/boot/dts/bcm2708_common.dtsi +@@ -110,7 +110,7 @@ + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; +- clocks = <&clk_spi>; ++ clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +@@ -203,11 +203,11 @@ + clock-frequency = <250000000>; + }; -diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c -index c5e51e8..fe71c50 100644 ---- a/arch/arm/mach-bcm2709/bcm2709.c -+++ b/arch/arm/mach-bcm2709/bcm2709.c -@@ -1050,7 +1050,7 @@ static irqreturn_t bcm2709_timer_interrupt(int irq, void *dev_id) +- clk_spi: clock@2 { ++ clk_core: clock@2 { + compatible = "fixed-clock"; + reg = <2>; + #clock-cells = <0>; +- clock-output-names = "spi"; ++ clock-output-names = "core"; + clock-frequency = <250000000>; + }; - static struct irqaction bcm2709_timer_irq = { - .name = "BCM2709 Timer Tick", -- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcm2709_timer_interrupt, +diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +index 8aaaf1f..24fa849 100644 +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -124,6 +124,7 @@ + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; +diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +index b408ab4..897204a 100644 +--- a/arch/arm/boot/dts/overlays/sdhost-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sdhost-overlay.dts +@@ -16,7 +16,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + interrupts = <2 24>; +- clocks = <&clk_sdhost>; ++ clocks = <&clk_core>; + dmas = <&dma 13>, + <&dma 13>; + dma-names = "tx", "rx"; +@@ -29,22 +29,6 @@ + }; + + fragment@1 { +- target = <&clocks>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- clk_sdhost: sdhost { +- compatible = "fixed-clock"; +- reg = <0>; +- #clock-cells = <0>; +- clock-output-names = "sdhost"; +- clock-frequency = <250000000>; +- }; +- }; +- }; +- +- fragment@2 { + target = <&gpio>; + __overlay__ { + sdhost_pins: sdhost_pins { +@@ -54,7 +38,7 @@ + }; + }; + +- fragment@3 { ++ fragment@2 { + target = <&mmc>; + __overlay__ { + /* Find a way to disable the other driver */ +@@ -63,18 +47,10 @@ + }; + }; + +- fragment@4 { +- target-path = "/__overrides__"; +- __overlay__ { +- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; +- }; +- }; +- + __overrides__ { + overclock_50 = <&sdhost>,"brcm,overclock-50:0"; + force_pio = <&sdhost>,"brcm,force-pio?"; + pio_limit = <&sdhost>,"brcm,pio-limit:0"; + debug = <&sdhost>,"brcm,debug?"; +- sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; + }; }; - From 398d3e2339a85dce1fdca331febe5bff5dccec22 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 28 Jun 2015 13:56:55 +0200 Subject: [PATCH 29/29] gcc: update to gcc-4.9.3 Signed-off-by: Stephan Raue --- packages/lang/gcc/package.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lang/gcc/package.mk b/packages/lang/gcc/package.mk index 04d6b0a776..18ee4dda15 100644 --- a/packages/lang/gcc/package.mk +++ b/packages/lang/gcc/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="gcc" -PKG_VERSION="4.9.2" +PKG_VERSION="4.9.3" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL"