[PATCH] pl2303: restore the old baud rate encoding for HXD (and newer) chips

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Mika Westerberg has reported that the fixed+improved divisor based baud rate 
encoding method doesn't work anymore with his HXD device.
So until we've found out what's going on, reintroduce the old encoding algorithm
and use it for this and all newer chips for baud rates > 115200 baud.
Also switch back to the direct encoding method for baud rates <= 115200, because
it's unclear if the old divisor based encoding algorithm works for them.

Reported-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
Signed-off-by: Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx>
---
 drivers/usb/serial/pl2303.c |   64 +++++++++++++++++++++++++++++++++++++++----
 1 Datei geändert, 58 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)

diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index bedf8e4..32f0410 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -372,14 +372,14 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
 	return baud;
 }
 
-static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
+static int pl2303_baudrate_encode_divisor_HX(int baud, enum pl2303_type type,
 								      u8 buf[4])
 {
 	/*
-	 * Divisor based baud rate encoding method
+	 * Divisor based baud rate encoding method for HX chips
 	 *
 	 * NOTE: HX clones do NOT support this method.
-	 * It's not clear if the type_0/1 chips support it.
+	 * It's not clear if other chips support it.
 	 *
 	 * divisor = 12MHz * 32 / baudrate = 2^A * B
 	 *
@@ -456,6 +456,53 @@ static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
 	return baud;
 }
 
+static int pl2303_baudrate_encode_divisor_HXD(int baud, enum pl2303_type type,
+								      u8 buf[4])
+{
+	/*
+	 * Divisor based baud rate encoding method for HXD chips
+	 * 
+	 * NOTE: This method has been used since kernel 3.1 for all chips and
+	 * baud rates > 115200. It is very similar to the new (and better) 
+	 * method for HX chips, but it has been reported that the HX method
+	 * doesn't work at least for HXD chips and baud rates > 115200.
+	 */
+	unsigned tmp;
+
+	/*
+	 * NOTE: The Windows driver allows maximum baud rates of 110% of the
+	 * specified maximium value.
+	 * Quick tests with early (2004) HX (rev. A) chips suggest, that even
+	 * higher baud rates (up to the maximum of 24M baud !) are working fine,
+	 * but that should really be tested carefully in "real life" scenarios
+	 * before removing the upper limit completely.
+	 * 
+	 * Specified max. baud rates:
+	 * HXD, EA, TB: 12Mbps; RA: 1Mbps; SA: 115200 bps
+	 *
+	 * FIXME: as long as we don't know how to distinguish between
+	 * these chip variants, allow the max. of these values
+	 */
+	baud = min_t(int, baud, 12000000 * 1.1);
+
+	/* apparently the formula for higher speeds is:
+	 * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+	 */
+	tmp = 12*1000*1000*32 / baud;
+	buf[3] = 0x80;
+	buf[2] = 0;
+	buf[1] = (tmp >= 256);
+	while (tmp >= 256) {
+		tmp >>= 2;
+		buf[1] <<= 1;
+	}
+	buf[0] = tmp;
+	/* Calculate the actual/resulting baud rate */
+	baud = 12000000 * 32 / ((1 << buf[1]) * buf[0]);
+
+	return baud;
+}
+
 static void pl2303_encode_baudrate(struct tty_struct *tty,
 					struct usb_serial_port *port,
 					enum pl2303_type type,
@@ -473,6 +520,9 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
 	 *    => supported by all chip types
 	 * 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
 	 *    => not supported by HX clones (and likely type_0/1 chips)
+	 *    => supported by HX chips for the whole baud rate range
+	 *    => HXD (and likely also EA, RA, SA, TB chips) support this method
+	 *       only for baud rates > 115200
 	 *
 	 * NOTE: Although the divisor based baud rate encoding method is much
 	 * more flexible, some of the standard baud rate values can not be
@@ -480,10 +530,12 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
 	 * the device likely uses the same baud rate generator for both methods
 	 * so that there is likley no difference.
 	 */
-	if (type == type_0 || type == type_1 || type == HX_CLONE)
-		baud = pl2303_baudrate_encode_direct(baud, type, buf);
+	if (type == HX_TA)
+		baud = pl2303_baudrate_encode_divisor_HX(baud, type, buf);
+	else if ((type == HXD_EA_RA_SA || type == TB) && baud > 115200)
+  		baud = pl2303_baudrate_encode_divisor_HXD(baud, type, buf);
 	else
-		baud = pl2303_baudrate_encode_divisor(baud, type, buf);
+		baud = pl2303_baudrate_encode_direct(baud, type, buf);
 	/* Save resulting baud rate */
 	tty_encode_baud_rate(tty, baud, baud);
 	dev_dbg(&port->dev, "baud set = %d\n", baud);
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux