#!/bin/bash

# Joshua V. Dillon
# jvdillon (a) gmail (.) com
# Tue Sep  6 19:04:58 EDT 2011 - initial version
# Wed Sep  7 09:10:35 EDT 2011 - supported 11" because kujuntuluntufurtu is mad
# Sat Sep 10 10:21:45 EDT 2011 - minor tweaks; fixed install path issue
# Mon Sep 12 11:15:18 EDT 2011 - pointless minor tweaks
# Fri Sep 16 08:02:18 EDT 2011 - uncommented 'extra' cp
# Sun Sep 18 00:55:17 EDT 2011 - MBA4,1 (LG & Samsung) modeline
# Fri Sep 23 08:46:45 EDT 2011 - MBA4,2 (Samsung) modeline (chinasailor)
# Sun Dec  4 12:14:39 PST 2011 - 01_remove-unnecesary-xorg-edgers-recommendation.patch (poliva)
# Sun Dec  4 13:28:42 PST 2011 - new modeline (khilman), cleaned code
#
# Forces the i915 driver to use the correct modeline for either
# MBA4,1 or MBA4,2. This script is not suitable for any other
# machine nor is it even ideal for MBA4.
#
# Implements hack anonymously submitted at:
#    https://bugs.freedesktop.org/show_bug.cgi?id=39533
# by following kernel build recipe from:
#    https://wiki.ubuntu.com/KernelCustomBuild
#
# Copyright (c) 2011 Joshua V Dillon
# All rights reserved. See end-of-file for license.

# ----------------------------------------------------------------
# to get modeline info:
#
# 1) boot with "drm.debug=0x14" and without: "nomodeset" and "i915.modeset=0"
# 2) dmesg|grep -i modeline
# 3) For example, for the 'MacBookAir4,2/LP133WP1-TJA3':
#    [drm:drm_mode_debug_printmodeline], Modeline 24:"1440x900" 60 91540 1440 1504 1546 1652 900 903 909 926 0x48 0xa
# ---------------------------------------------------------------

[ $(lsb_release -sir 2>/dev/null|tr -d [:space:]) != 'Ubuntu11.10' ] && \
	{ echo >&2 "ERROR: Must be running Ubuntu 11.10.";exit 1; }

[ ${BASH_VERSION%%\.*} -lt 4 ] && \
	{ echo >&2 "ERROR: Must have bash version >=4.";exit 2; }


# --- Modeline Information --------------------------------------

declare -A modeline

# patch confirmed at: https://bugs.freedesktop.org/show_bug.cgi?id=39533#c61
modeline['MacBookAir4,1/LTH116AT01A04']='72500 1366 1398 1566 1734 768 772 776 792 0x48 0xa'

# patch confirmed at: https://bugs.freedesktop.org/show_bug.cgi?id=39533#c29
modeline['MacBookAir4,1/LP116WH4-TJA3']='91540 1366 1380 1436 1500 768 769 772 800 0x48 0xa'

# patch confirmed by: khilman (personal email)
modeline['MacBookAir4,1/B116XW05V6']='72000 1366 1380 1436 1500 768 769 772 800 0x48 0xa'

# patch confirmed by: chinasailor
modeline['MacBookAir4,2/LTH133BT01A03']='88890 1440 1488 1520 1600 900 903 909 926 0x48 0xa'

# patch confirmed by: author
modeline['MacBookAir4,2/LP133WP1-TJA3']='91540 1440 1504 1546 1652 900 903 909 926 0x48 0xa'



# --- Verify Hardware -------------------------------------------

# get aptitude because its better
[ -z "$(which aptitude)" ] && sudo apt-get install aptitude

# sometimes saw trailing non-printables which confuse strcmp; echo cleans-up
#SysPrdNam=$(echo $(sudo dmidecode -s system-product-name))
SysPrdNam=$(cat /sys/class/dmi/id/product_name)

# --- identify panel type
[ -z "$(which get-edid)" ] && sudo aptitude install read-edid
PanelType=$(sudo get-edid 2>/dev/null|strings -5|head -1|tr -d ' ')
# sometimes get-edid doesn't work.
[ -z "${PanelType}" ] && \
	PanelType=$(grep -B2 "EDID (in hex)" /var/log/Xorg.0.log|head -1|tr -d '[:blank:]'|cut -d: -f2)

mymodeline=(${modeline["${SysPrdNam}/${PanelType}"]})

[ -z "${mymodeline[*]}" ] && \
	{ echo >&2 "ERROR: '${SysPrdNam}/${PanelType}' not recognized";exit 3; }

echo >&2 -e "\nSUCCESS: detected '${SysPrdNam}' with panel '${PanelType}'\n"


# --- Perform Updates -------------------------------------------

if false; then
	tee 1>&2 <<-EOF
		ATTENTION:
		It is recommended that you use experimental drivers provided by
		xorg-edgers, in addition to the patch applied by this script.
		To install drivers from "ppa:xorg-edgers/ppa" press Y.
		To skip this step, press any other key. 
	EOF
	read -n 1 -r choice
	[ ${choice,,} = 'y' ] && sudo add-apt-repository ppa:xorg-edgers/ppa
fi

echo >&2 "WARNING: Updating system before applying patch."
sudo aptitude update -q2
sudo aptitude safe-upgrade

[ -f /var/run/reboot-required ] && \
	tee 1>&2 <<-EOF
		WARNING:
		Reboot required for update to complete. Proceeding anyway. You
		may need to re-run this script after reboot.
	EOF


# --- Patch Driver ----------------------------------------------

# get kernel

sudo aptitude install build-essential
sudo apt-get build-dep --no-install-recommends linux-image-$(uname -r)
apt-get source linux-image-$(uname -r)

# patch
cd linux-$(uname -r|cut -d- -f1)/drivers/gpu/drm/i915/

unset i
patch<<EOF
--- intel_bios.c	2011-09-06 18:49:02.701486674 -0400
+++ intel_bios.c	2011-09-06 18:52:25.921492221 -0400
@@ -175,6 +175,18 @@
 	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
 
 	DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
+	panel_fixed_mode->hdisplay = ${mymodeline[++i]};
+	panel_fixed_mode->hsync_start = ${mymodeline[++i]};
+	panel_fixed_mode->hsync_end = ${mymodeline[++i]};
+	panel_fixed_mode->htotal = ${mymodeline[++i]};
+	panel_fixed_mode->vdisplay = ${mymodeline[++i]};
+	panel_fixed_mode->vsync_start = ${mymodeline[++i]};
+	panel_fixed_mode->vsync_end = ${mymodeline[++i]};
+	panel_fixed_mode->vtotal = ${mymodeline[++i]};
+	panel_fixed_mode->clock = ${mymodeline[0]};
+	panel_fixed_mode->type = ${mymodeline[++i]};
+	panel_fixed_mode->flags = ${mymodeline[++i]};
+	drm_mode_set_name(panel_fixed_mode);
 	drm_mode_debug_printmodeline(panel_fixed_mode);
 
 	temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
EOF



# --- Install Driver --------------------------------------------

# build
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

# install
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install

# I have no idea why the following command seems to be necessary for some
# people. For some reason the kernel prefers the drivers/gpu/drm over extra,
# which to my view defeats the point of having extra (a place to shadow things)
# this is a hack (on top of a hack!):
# make (one-time) backup
[ -e /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/i915/i915.ko.bak ] || \
	sudo cp /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/i915/i915.ko \
		/lib/modules/$(uname -r)/kernel/drivers/gpu/drm/i915/i915.ko.bak
# overwrite
sudo cp /lib/modules/$(uname -r)/extra/i915.ko \
	/lib/modules/$(uname -r)/kernel/drivers/gpu/drm/i915/i915.ko

# depmod,update-initramfs are necessary?
sudo depmod -a
sudo update-initramfs -u

# check install locations
if [ ! -e "/lib/modules/$(uname -r)/extra/i915.ko" ]; then
	echo >&2 "WARNING: The i915 module did not install to the expected location."
fi
echo >&2 -e "ATTENTION: The following i915 driver will be used after reboot:" \
	"\n  " $(modinfo i915|head -1|cut -b17-)

exit 0


# --- Miscellaneous Documentation -------------------------------

# you may also find this useful:
# sudo aptitude install intel-gpu-tools
# sudo intel_backlight 50

# git clone git://kernel.ubuntu.com/ubuntu/ubuntu-oneiric.git

# https://spreadsheets.google.com/spreadsheet/viewform?formkey=dHFhcmFieEZzMmtSZjdwWDNhNVlPOFE6MQ
# https://spreadsheets.google.com/spreadsheet/ccc?key=0Aq4LUv8YJH25dHFhcmFieEZzMmtSZjdwWDNhNVlPOFE&hl=en_US#gid=0

# MacBookAir4,1
#    38  LP116WH4-TJA3
#    51  LTH116AT01A04
# MacBookAir4,2
#   190  LP133WP1-TJA3
#   150  LTH133BT01A03

#  3 MBA11 - i5,
# 18 MBA11 - i5,LP116WH4-TJA3
# 32 MBA11 - i5,LTH116AT01A04
#  3 MBA11 - i5,LTH133BT01A03
#  6 MBA11 - i7,
# 18 MBA11 - i7,LP116WH4-TJA3
#  1 MBA11 - i7,LP133WP1-TJA3
# 17 MBA11 - i7,LTH116AT01A04
#  1 MBA11 - i7,LTH133BT01A03
#
#  4 MBA13 - i5,
#  1 MBA13 - i5,?
#  1 MBA13 - i5,IDK. I have an LP
#  2 MBA13 - i5,LP116WH4-TJA3
#114 MBA13 - i5,LP133WP1-TJA3
#  2 MBA13 - i5,LTH116AT01A04
# 99 MBA13 - i5,LTH133BT01A03
#  1 MBA13 - i7,
# 75 MBA13 - i7,LP133WP1-TJA3
# 47 MBA13 - i7,LTH133BT01A03



#  Redistribution and use in source and binary forms, with or
#  without modification, are permitted provided that the
#  following conditions are met:
#   * Redistributions of source code must retain the above
#     copyright notice, this list of conditions and the
#     following disclaimer.
#   * Redistributions in binary form must reproduce the above
#     copyright notice, this list of conditions and the
#     following disclaimer in the documentation and/or other
#     materials provided with the distribution.
#   * Neither the name of the author nor the names of its
#     contributors may be used to endorse or promote products
#     derived from this software without specific prior written
#     permission.
#  
#  THIS SOFTWARE IS PROVIDED BY JOSHUA V DILLON ''AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
#  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOSHUA
#  V DILLON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
#  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

